/*
 * Copyright (C) 2022 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.wm;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Slog;
import android.view.IDisplayChangeWindowCallback;
import android.window.DisplayAreaInfo;
import android.window.WindowContainerTransaction;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;

import java.util.ArrayList;
import java.util.List;

/**
 * A helper class, a wrapper around {@link android.view.IDisplayChangeWindowController} to perform
 * a synchronous display change in other parts (e.g. in the Shell) and continue the process
 * in the system server. It handles timeouts and multiple requests.
 * We have an instance of this controller for each display.
 */
public class RemoteDisplayChangeController {

    private static final String TAG = "RemoteDisplayChangeController";
    private static final String REMOTE_DISPLAY_CHANGE_TRACE_TAG = "RemoteDisplayChange";

    private static final int REMOTE_DISPLAY_CHANGE_TIMEOUT_MS = 800;

    private final WindowManagerService mService;
    private final DisplayContent mDisplayContent;

    private final Runnable mTimeoutRunnable = this::onContinueTimedOut;

    // all remote changes that haven't finished yet.
    private final List<ContinueRemoteDisplayChangeCallback> mCallbacks = new ArrayList<>();

    RemoteDisplayChangeController(@NonNull DisplayContent displayContent) {
        mService = displayContent.mWmService;
        mDisplayContent = displayContent;
    }

    /**
     * A Remote change is when we are waiting for some registered (remote)
     * {@link IDisplayChangeWindowController} to calculate and return some hierarchy operations
     *  to perform in sync with the display change.
     */
    public boolean isWaitingForRemoteDisplayChange() {
        return !mCallbacks.isEmpty();
    }

    /**
     * Starts remote display change
     * @param fromRotation rotation before the change
     * @param toRotation rotation after the change
     * @param newDisplayAreaInfo display area info after change
     * @param callback that will be called after completing remote display change
     * @return true if the change successfully started, false otherwise
     */
    public boolean performRemoteDisplayChange(
            int fromRotation, int toRotation,
            @Nullable DisplayAreaInfo newDisplayAreaInfo,
            ContinueRemoteDisplayChangeCallback callback) {
        if (mService.mDisplayChangeController == null) {
            return false;
        }
        mCallbacks.add(callback);

        if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
            Trace.beginAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
        }

        if (newDisplayAreaInfo != null) {
            ProtoLog.v(WM_DEBUG_CONFIGURATION,
                    "Starting remote display change: "
                            + "from [rot = %d], "
                            + "to [%dx%d, rot = %d]",
                    fromRotation,
                    newDisplayAreaInfo.configuration.windowConfiguration
                            .getMaxBounds().width(),
                    newDisplayAreaInfo.configuration.windowConfiguration
                            .getMaxBounds().height(),
                    toRotation);
        }

        final IDisplayChangeWindowCallback remoteCallback = createCallback(callback);
        try {
            mService.mH.removeCallbacks(mTimeoutRunnable);
            mService.mH.postDelayed(mTimeoutRunnable, REMOTE_DISPLAY_CHANGE_TIMEOUT_MS);
            mService.mDisplayChangeController.onDisplayChange(mDisplayContent.mDisplayId,
                    fromRotation, toRotation, newDisplayAreaInfo, remoteCallback);
            return true;
        } catch (RemoteException e) {
            Slog.e(TAG, "Exception while dispatching remote display-change", e);
            mCallbacks.remove(callback);
            return false;
        }
    }

    private void onContinueTimedOut() {
        Slog.e(TAG, "RemoteDisplayChange timed-out, UI might get messed-up after this.");
        // timed-out, so run all continue callbacks and clear the list
        synchronized (mService.mGlobalLock) {
            for (int i = 0; i < mCallbacks.size(); ++i) {
                final ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i);
                if (i == mCallbacks.size() - 1) {
                    // Clear all callbacks before calling the last one, so that if the callback
                    // itself calls {@link #isWaitingForRemoteDisplayChange()}, it will get
                    // {@code false}. After all, there is nothing pending after this one.
                    mCallbacks.clear();
                }
                callback.onContinueRemoteDisplayChange(null /* transaction */);

                if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                    Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
                }
            }
            onCompleted();
        }
    }

    /** Called when all remote callbacks are done. */
    private void onCompleted() {
        // Because DisplayContent#sendNewConfiguration() will be skipped if there are pending remote
        // changes, check again when all remote callbacks are done. E.g. callback X is done but
        // there is a pending callback Y so its invocation is skipped, and when the callback Y is
        // done, it doesn't call sendNewConfiguration().
        if (mDisplayContent.mWaitingForConfig) {
            mDisplayContent.sendNewConfiguration();
        }
    }

    @VisibleForTesting
    void continueDisplayChange(@NonNull ContinueRemoteDisplayChangeCallback callback,
            @Nullable WindowContainerTransaction transaction) {
        synchronized (mService.mGlobalLock) {
            int idx = mCallbacks.indexOf(callback);
            if (idx < 0) {
                // already called this callback or a more-recent one (eg. via timeout)
                return;
            }
            for (int i = 0; i < idx; ++i) {
                // Expect remote callbacks in order. If they don't come in order, then force
                // ordering by continuing everything up until this one with empty transactions.
                ContinueRemoteDisplayChangeCallback currentCallback = mCallbacks.get(i);
                currentCallback.onContinueRemoteDisplayChange(null /* transaction */);

                if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                    Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG,
                            currentCallback.hashCode());
                }
            }
            // The "toIndex" is exclusive, so it needs +1 to clear the current calling callback.
            mCallbacks.subList(0, idx + 1).clear();
            final boolean completed = mCallbacks.isEmpty();
            if (completed) {
                mService.mH.removeCallbacks(mTimeoutRunnable);
            }
            callback.onContinueRemoteDisplayChange(transaction);
            if (completed) {
                onCompleted();
            }

            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                Trace.endAsyncSection(REMOTE_DISPLAY_CHANGE_TRACE_TAG, callback.hashCode());
            }
        }
    }

    private IDisplayChangeWindowCallback createCallback(
            @NonNull ContinueRemoteDisplayChangeCallback callback) {
        return new IDisplayChangeWindowCallback.Stub() {
                    @Override
                    public void continueDisplayChange(WindowContainerTransaction t) {
                        synchronized (mService.mGlobalLock) {
                            if (!mCallbacks.contains(callback)) {
                                // already ran this callback or a more-recent one.
                                return;
                            }
                            mService.mH.post(() -> RemoteDisplayChangeController.this
                                    .continueDisplayChange(callback, t));
                        }
                    }
                };
    }

    /**
     * Callback interface to handle continuation of the remote display change
     */
    public interface ContinueRemoteDisplayChangeCallback {
        /**
         * This method is called when the remote display change has been applied
         * @param transaction window changes collected by the remote display change
         */
        void onContinueRemoteDisplayChange(@Nullable WindowContainerTransaction transaction);
    }
}
