/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import android.annotation.Nullable;
import android.app.AnrController;
import android.app.Dialog;
import android.content.Context;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * A controller to generate error dialogs in {@link ProcessRecord}.
 */
final class ErrorDialogController {
    private final ProcessRecord mApp;
    private final ActivityManagerService mService;
    private final ActivityManagerGlobalLock mProcLock;

    /**
     * Dialogs being displayed due to crash.
     */
    @GuardedBy("mProcLock")
    private List<AppErrorDialog> mCrashDialogs;

    /**
     * Dialogs being displayed due to app not responding.
     */
    @GuardedBy("mProcLock")
    private List<AppNotRespondingDialog> mAnrDialogs;

    /**
     * Dialogs displayed due to strict mode violation.
     */
    @GuardedBy("mProcLock")
    private List<StrictModeViolationDialog> mViolationDialogs;

    /**
     * Current wait for debugger dialog.
     */
    @GuardedBy("mProcLock")
    private AppWaitingForDebuggerDialog mWaitDialog;

    /**
     * ANR dialog controller
     */
    @GuardedBy("mProcLock")
    @Nullable
    private AnrController mAnrController;

    @GuardedBy("mProcLock")
    boolean hasCrashDialogs() {
        return mCrashDialogs != null;
    }

    @GuardedBy("mProcLock")
    List<AppErrorDialog> getCrashDialogs() {
        return mCrashDialogs;
    }

    @GuardedBy("mProcLock")
    boolean hasAnrDialogs() {
        return mAnrDialogs != null;
    }

    @GuardedBy("mProcLock")
    List<AppNotRespondingDialog> getAnrDialogs() {
        return mAnrDialogs;
    }

    @GuardedBy("mProcLock")
    boolean hasViolationDialogs() {
        return mViolationDialogs != null;
    }

    @GuardedBy("mProcLock")
    boolean hasDebugWaitingDialog() {
        return mWaitDialog != null;
    }

    @GuardedBy("mProcLock")
    void clearAllErrorDialogs() {
        clearCrashDialogs();
        clearAnrDialogs();
        clearViolationDialogs();
        clearWaitingDialog();
    }

    @GuardedBy("mProcLock")
    void clearCrashDialogs() {
        clearCrashDialogs(true /* needDismiss */);
    }

    @GuardedBy("mProcLock")
    void clearCrashDialogs(boolean needDismiss) {
        if (mCrashDialogs == null) {
            return;
        }
        if (needDismiss) {
            scheduleForAllDialogs(mCrashDialogs, Dialog::dismiss);
        }
        mCrashDialogs = null;
    }

    @GuardedBy("mProcLock")
    void clearAnrDialogs() {
        if (mAnrDialogs == null) {
            return;
        }
        scheduleForAllDialogs(mAnrDialogs, Dialog::dismiss);
        mAnrDialogs = null;
        mAnrController = null;
    }

    @GuardedBy("mProcLock")
    void clearViolationDialogs() {
        if (mViolationDialogs == null) {
            return;
        }
        scheduleForAllDialogs(mViolationDialogs, Dialog::dismiss);
        mViolationDialogs = null;
    }

    @GuardedBy("mProcLock")
    void clearWaitingDialog() {
        if (mWaitDialog == null) {
            return;
        }
        final BaseErrorDialog dialog = mWaitDialog;
        mService.mUiHandler.post(dialog::dismiss);
        mWaitDialog = null;
    }

    @GuardedBy("mProcLock")
    void scheduleForAllDialogs(List<? extends BaseErrorDialog> dialogs,
            Consumer<BaseErrorDialog> c) {
        mService.mUiHandler.post(() -> {
            if (dialogs != null) {
                forAllDialogs(dialogs, c);
            }
        });
    }

    void forAllDialogs(List<? extends BaseErrorDialog> dialogs, Consumer<BaseErrorDialog> c) {
        for (int i = dialogs.size() - 1; i >= 0; i--) {
            c.accept(dialogs.get(i));
        }
    }

    @GuardedBy("mProcLock")
    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(() -> {
            List<AppErrorDialog> dialogs;
            synchronized (mProcLock) {
                dialogs = mCrashDialogs;
            }
            if (dialogs != null) {
                forAllDialogs(dialogs, Dialog::show);
            }
        });
    }

    @GuardedBy("mProcLock")
    void showAnrDialogs(AppNotRespondingDialog.Data data) {
        List<Context> contexts = getDisplayContexts(
                mApp.mErrorState.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));
        }
        scheduleForAllDialogs(mAnrDialogs, Dialog::show);
    }

    @GuardedBy("mProcLock")
    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, mApp));
        }
        scheduleForAllDialogs(mViolationDialogs, Dialog::show);
    }

    @GuardedBy("mProcLock")
    void showDebugWaitingDialogs() {
        List<Context> contexts = getDisplayContexts(true /* lastUsedOnly */);
        final Context c = contexts.get(0);
        mWaitDialog = new AppWaitingForDebuggerDialog(mService, c, mApp);

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

    @GuardedBy("mProcLock")
    @Nullable
    AnrController getAnrController() {
        return mAnrController;
    }

    @GuardedBy("mProcLock")
    void setAnrController(AnrController controller) {
        mAnrController = controller;
    }

    /**
     * Helper function to collect contexts from crashed app located displays.
     *
     * @param lastUsedOnly Sets to {@code true} to indicate to only get last used context.
     *                     Sets to {@code false} to collect contexts from crashed app located
     *                     displays.
     *
     * @return display context list.
     */
    private List<Context> getDisplayContexts(boolean lastUsedOnly) {
        List<Context> displayContexts = new ArrayList<>();
        if (!lastUsedOnly) {
            mApp.getWindowProcessController().getDisplayContextsWithErrorDialogs(displayContexts);
        }
        // If there is no foreground window display, fallback to last used display.
        if (displayContexts.isEmpty() || lastUsedOnly) {
            displayContexts.add(mService.mWmInternal != null
                    ? mService.mWmInternal.getTopFocusedDisplayUiContext()
                    : mService.mUiContext);
        }
        return displayContexts;
    }

    ErrorDialogController(ProcessRecord app) {
        mApp = app;
        mService = app.mService;
        mProcLock = mService.mProcLock;
    }
}
