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

Commit ce7c8074 authored by Charles Chen's avatar Charles Chen
Browse files

Fix race when show error dialogs

Test: atest AnrTests AmStartOptionsTests#testDashD
fixes: 148344287

Change-Id: Ie7a2d6fdf8ba8452cd4102fa1fbed760a1bad85c
parent 848b6d44
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -798,7 +798,6 @@ class AppErrors {
        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;

        final String packageName;
        final int userId;
        synchronized (mService) {
            final ProcessRecord proc = data.proc;
@@ -807,7 +806,6 @@ class AppErrors {
                Slog.e(TAG, "handleShowAppErrorUi: proc is null");
                return;
            }
            packageName = proc.info.packageName;
            userId = proc.userId;
            if (proc.getDialogController().hasCrashDialogs()) {
                Slog.e(TAG, "App already has crash dialog: " + proc);
+38 −9
Original line number Diff line number Diff line
@@ -1901,8 +1901,7 @@ class ProcessRecord implements WindowProcessListener {
            mWaitDialog = null;
        }

        void forAllDialogs(List<? extends BaseErrorDialog> dialogs,
                Consumer<BaseErrorDialog> c) {
        void forAllDialogs(List<? extends BaseErrorDialog> dialogs, Consumer<BaseErrorDialog> c) {
            for (int i = dialogs.size() - 1; i >= 0; i--) {
                c.accept(dialogs.get(i));
            }
@@ -1911,42 +1910,72 @@ class ProcessRecord implements WindowProcessListener {
        void showCrashDialogs(AppErrorDialog.Data data) {
            List<Context> contexts = getDisplayContexts(false /* lastUsedOnly */);
            mCrashDialogs = new ArrayList<>();

            for (int i = contexts.size() - 1; i >= 0; i--) {
                final Context c = contexts.get(i);
                mCrashDialogs.add(new AppErrorDialog(c, mService, data));
            }
            mService.mUiHandler.post(() -> mCrashDialogs.forEach(Dialog::show));
            mService.mUiHandler.post(() -> {
                List<AppErrorDialog> dialogs;
                synchronized (mService) {
                    dialogs = mCrashDialogs;
                }
                if (dialogs != null) {
                    forAllDialogs(dialogs, Dialog::show);
                }
            });
        }

        void showAnrDialogs(AppNotRespondingDialog.Data data) {
            List<Context> contexts = getDisplayContexts(isSilentAnr() /* lastUsedOnly */);
            mAnrDialogs = new ArrayList<>();

            for (int i = contexts.size() - 1; i >= 0; i--) {
                final Context c = contexts.get(i);
                mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
            }
            mService.mUiHandler.post(() -> mAnrDialogs.forEach(Dialog::show));
            mService.mUiHandler.post(() -> {
                List<AppNotRespondingDialog> dialogs;
                synchronized (mService) {
                    dialogs = mAnrDialogs;
                }
                if (dialogs != null) {
                    forAllDialogs(dialogs, Dialog::show);
                }
            });
        }

        void showViolationDialogs(AppErrorResult res) {
            List<Context> contexts = getDisplayContexts(false /* lastUsedOnly */);
            mViolationDialogs = new ArrayList<>();

            for (int i = contexts.size() - 1; i >= 0; i--) {
                final Context c = contexts.get(i);
                mViolationDialogs.add(
                        new StrictModeViolationDialog(c, mService, res, ProcessRecord.this));
            }
            mService.mUiHandler.post(() -> mViolationDialogs.forEach(Dialog::show));
            mService.mUiHandler.post(() -> {
                List<StrictModeViolationDialog> dialogs;
                synchronized (mService) {
                    dialogs = mViolationDialogs;
                }
                if (dialogs != null) {
                    forAllDialogs(dialogs, Dialog::show);
                }
            });
        }

        void showDebugWaitingDialogs() {
            List<Context> contexts = getDisplayContexts(true /* lastUsedOnly */);
            final Context c = contexts.get(0);
            mWaitDialog = new AppWaitingForDebuggerDialog(mService, c, ProcessRecord.this);
            mService.mUiHandler.post(() -> mWaitDialog.show());

            mService.mUiHandler.post(() -> {
                Dialog dialog;
                synchronized (mService) {
                    dialog = mWaitDialog;
                }
                if (dialog != null) {
                    dialog.show();
                }
            });
        }

        /**