/*
 * 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 android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.server.wm.WindowManagerState.STATE_PAUSED;
import static android.server.wm.WindowMetricsTestHelper.assertBoundsMatchDisplay;
import static android.server.wm.WindowMetricsTestHelper.getBoundsExcludingNavigationBarAndCutout;
import static android.server.wm.WindowMetricsTestHelper.maxWindowBoundsSandboxed;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import android.app.Activity;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.server.wm.WindowMetricsTestHelper.OnLayoutChangeListener;
import android.view.Display;
import android.view.WindowManager;
import android.view.WindowMetrics;

import androidx.test.filters.FlakyTest;

import org.junit.Test;
import java.util.function.Supplier;

/**
 * Tests that verify the behavior of {@link WindowMetrics} APIs on {@link Activity activities}.
 *
 * Build/Install/Run:
 *     atest CtsWindowManagerDeviceTestCases:WindowMetricsActivityTests
 */
@Presubmit
public class WindowMetricsActivityTests extends WindowManagerTestBase {
    private static final Rect WINDOW_BOUNDS = new Rect(100, 100, 400, 400);
    private static final Rect RESIZED_WINDOW_BOUNDS = new Rect(100, 100, 900, 900);
    private static final int MOVE_OFFSET = 100;

    @Test
    public void testMetricsMatchesLayoutOnActivityOnCreate() {
        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);
        final OnLayoutChangeListener listener = activity.mListener;

        listener.waitForLayout();

        WindowMetricsTestHelper.assertMetricsMatchesLayout(activity.mOnCreateCurrentMetrics,
                activity.mOnCreateMaximumMetrics, listener.getLayoutBounds(),
                listener.getLayoutInsets());
    }

    @Test
    public void testMetricsMatchesDisplayAreaOnActivity() {
        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsValidity(activity);
    }

    @Test
    @FlakyTest(bugId = 188207199)
    public void testMetricsMatchesActivityBoundsOnNonresizableActivity() {
        assumeTrue("Skipping test: no rotation support", supportsRotation());

        final MinAspectRatioActivity activity = startActivityInWindowingMode(
                MinAspectRatioActivity.class, WINDOWING_MODE_FULLSCREEN);
        mWmState.computeState(activity.getComponentName());

        assertMetricsValidityForNonresizableActivity(activity);
    }

    @Test
    public void testMetricsMatchesLayoutOnPipActivity() {
        assumeTrue(supportsPip());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsMatchesLayout(activity);

        activity.enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
        waitForEnterPipAnimationComplete(activity.getComponentName());

        assertMetricsMatchesLayout(activity);
    }

    @Test
    public void testMetricsMatchesDisplayAreaOnPipActivity() {
        assumeTrue(supportsPip());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsValidity(activity);

        activity.enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
        waitForEnterPipAnimationComplete(activity.getComponentName());

        assertMetricsValidity(activity);
    }

    /**
     * Waits until the picture-in-picture animation has finished.
     */
    private void waitForEnterPipAnimationComplete(ComponentName activityName) {
        waitForEnterPip(activityName);
        mWmState.waitForWithAmState(wmState -> {
            WindowManagerState.Task task = wmState.getTaskByActivity(activityName);
            if (task == null) {
                return false;
            }
            WindowManagerState.Activity activity = task.getActivity(activityName);
            return activity.getWindowingMode() == WINDOWING_MODE_PINNED
                    && activity.getState().equals(STATE_PAUSED);
        }, "checking activity windowing mode");
    }

    /**
     * Waits until the given activity has entered picture-in-picture mode (allowing for the
     * subsequent animation to start).
     */
    private void waitForEnterPip(ComponentName activityName) {
        mWmState.waitForWithAmState(wmState -> {
            WindowManagerState.Task task = wmState.getTaskByActivity(activityName);
            return task != null && task.getWindowingMode() == WINDOWING_MODE_PINNED;
        }, "checking task windowing mode");
    }

    @Test
    public void testMetricsMatchesLayoutOnSplitActivity() {
        assumeTrue(supportsSplitScreenMultiWindow());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsMatchesLayout(activity);

        mWmState.computeState(activity.getComponentName());
        putActivityInPrimarySplit(activity.getComponentName());

        mWmState.computeState(activity.getComponentName());
        assertTrue(mWmState.getActivity(activity.getComponentName()).getWindowingMode()
                == WINDOWING_MODE_MULTI_WINDOW);

        assertMetricsMatchesLayout(activity);
    }

    @Test
    public void testMetricsMatchesDisplayAreaOnSplitActivity() {
        assumeTrue(supportsSplitScreenMultiWindow());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsValidity(activity);

        mWmState.computeState(activity.getComponentName());
        putActivityInPrimarySplit(activity.getComponentName());

        mWmState.computeState(activity.getComponentName());
        assertTrue(mWmState.getActivity(activity.getComponentName()).getWindowingMode()
                == WINDOWING_MODE_MULTI_WINDOW);

        assertMetricsValidity(activity);
    }

    @Test
    public void testMetricsMatchesLayoutOnFreeformActivity() {
        assumeTrue(supportsFreeform());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsMatchesLayout(activity);

        launchActivity(new ComponentName(mTargetContext, MetricsActivity.class),
                WINDOWING_MODE_FREEFORM);

        // Resize the freeform activity.
        resizeActivityTask(activity.getComponentName(), WINDOW_BOUNDS.left, WINDOW_BOUNDS.top,
                WINDOW_BOUNDS.right, WINDOW_BOUNDS.bottom);

        assertMetricsMatchesLayout(activity);

        // Resize again.
        resizeActivityTask(activity.getComponentName(), RESIZED_WINDOW_BOUNDS.left,
                RESIZED_WINDOW_BOUNDS.top, RESIZED_WINDOW_BOUNDS.right,
                RESIZED_WINDOW_BOUNDS.bottom);

        assertMetricsMatchesLayout(activity);

        // Move the activity.
        resizeActivityTask(activity.getComponentName(), MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.left,
                MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.top, MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.right,
                MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.bottom);

        assertMetricsMatchesLayout(activity);
    }

    @Test
    public void testMetricsMatchesDisplayAreaOnFreeformActivity() {
        assumeTrue(supportsFreeform());

        final MetricsActivity activity = startActivityInWindowingMode(MetricsActivity.class,
                WINDOWING_MODE_FULLSCREEN);

        assertMetricsValidity(activity);

        launchActivity(new ComponentName(mTargetContext, MetricsActivity.class),
                WINDOWING_MODE_FREEFORM);

        // Resize the freeform activity.
        resizeActivityTask(activity.getComponentName(), WINDOW_BOUNDS.left, WINDOW_BOUNDS.top,
                WINDOW_BOUNDS.right, WINDOW_BOUNDS.bottom);

        assertMetricsValidity(activity);

        // Resize again.
        resizeActivityTask(activity.getComponentName(), RESIZED_WINDOW_BOUNDS.left,
                RESIZED_WINDOW_BOUNDS.top, RESIZED_WINDOW_BOUNDS.right,
                RESIZED_WINDOW_BOUNDS.bottom);

        assertMetricsValidity(activity);

        // Move the activity.
        resizeActivityTask(activity.getComponentName(), MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.left,
                MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.top, MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.right,
                MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.bottom);

        assertMetricsValidity(activity);
    }

    private static void assertMetricsMatchesLayout(MetricsActivity activity) {
        final OnLayoutChangeListener listener = activity.mListener;
        listener.waitForLayout();

        final Supplier<WindowMetrics> currentMetrics =
                () -> activity.getWindowManager().getCurrentWindowMetrics();
        final Supplier<WindowMetrics> maxMetrics =
                () -> activity.getWindowManager().getMaximumWindowMetrics();

        Condition.waitFor(new Condition<>("WindowMetrics must match layout metrics",
                () -> currentMetrics.get().getBounds().equals(listener.getLayoutBounds()))
                .setRetryIntervalMs(500).setRetryLimit(10)
                .setOnFailure(unused -> fail("WindowMetrics must match layout metrics. Layout"
                        + "bounds is" + listener.getLayoutBounds() + ", while current window"
                        + "metrics is " + currentMetrics.get().getBounds())));

        final boolean isFreeForm = activity.getResources().getConfiguration().windowConfiguration
                .getWindowingMode() == WINDOWING_MODE_FREEFORM;
        WindowMetricsTestHelper.assertMetricsMatchesLayout(currentMetrics.get(), maxMetrics.get(),
                listener.getLayoutBounds(), listener.getLayoutInsets(), isFreeForm);
    }

    /**
     * Verifies two scenarios for an {@link Activity}. If the activity is freeform, then the bounds
     * should not include insets for navigation bar and cutout area.
     * <ul>
     *     <li>{@link WindowManager#getCurrentWindowMetrics()} matches
     *     {@link Display#getSize(Point)}</li>
     *     <li>{@link WindowManager#getMaximumWindowMetrics()} and {@link Display#getSize(Point)}
     *     either matches DisplayArea bounds which the {@link Activity} is attached to, or matches
     *     {@link WindowManager#getCurrentWindowMetrics()} if sandboxing is applied.</li>
     * </ul>
     */
    private void assertMetricsValidity(Activity activity) {
        mWmState.computeState(activity.getComponentName());
        WindowMetricsTestHelper.assertMetricsValidity(activity,
                getTaskDisplayAreaBounds(activity.getComponentName()));
    }

    /**
     * Verifies two scenarios for a non-resizable {@link Activity}. Similar to
     * {@link #assertMetricsValidity(Activity)}, verifies the values of window metrics against
     * Display size. {@link WindowManager#getMaximumWindowMetrics()} must match activity bounds
     * if the activity is sandboxed.
     *
     * App bounds calculation of a nonresizable activity depends on the orientation of the display
     * and the app, and the display and activity bounds. Directly compare maximum WindowMetrics
     * against the value used for sandboxing, since other ways of accessing activity bounds may
     * have different insets applied.
     *
     * @param activity the activity under test
     */
    private void assertMetricsValidityForNonresizableActivity(Activity activity) {
        ComponentName activityName = activity.getComponentName();
        mWmState.computeState(activityName);
        WindowManagerState.Activity activityContainer = mWmState.getActivity(activityName);
        final boolean boundsShouldIncludeInsets =
                activity.getResources().getConfiguration().windowConfiguration
                        .getWindowingMode() == WINDOWING_MODE_FREEFORM
                        || activityContainer.inSizeCompatMode();
        final WindowManager windowManager = activity.getWindowManager();
        final WindowMetrics currentMetrics = windowManager.getCurrentWindowMetrics();
        final Rect currentBounds = boundsShouldIncludeInsets ? currentMetrics.getBounds()
                : getBoundsExcludingNavigationBarAndCutout(currentMetrics);
        final Rect maxBounds = windowManager.getMaximumWindowMetrics().getBounds();
        final Display display = activity.getDisplay();

        assertBoundsMatchDisplay(maxBounds, currentBounds, display);

        // Max window bounds should match either DisplayArea bounds, or activity bounds if it is
        // sandboxed.
        final Rect displayAreaBounds = getTaskDisplayAreaBounds(activityName);
        final Rect activityBounds =
                activityContainer.mFullConfiguration.windowConfiguration.getBounds();
        if (maxWindowBoundsSandboxed(displayAreaBounds, maxBounds)) {
            // Max window bounds are sandboxed, so max window bounds should match activity bounds.
            assertEquals("Maximum window metrics of a non-resizable activity matches "
                    + "activity bounds, when sandboxed", activityBounds, maxBounds);
        } else {
            // Max window bounds are not sandboxed, so max window bounds should match display area
            // bounds.
            assertEquals("Display area bounds must match max window size", displayAreaBounds,
                    maxBounds);
        }
    }

    private Rect getTaskDisplayAreaBounds(ComponentName activityName) {
        WindowManagerState.DisplayArea tda = mWmState.getTaskDisplayArea(activityName);
        return tda.mFullConfiguration.windowConfiguration.getBounds();
    }

    public static class MetricsActivity extends FocusableActivity {
        private WindowMetrics mOnCreateMaximumMetrics;
        private WindowMetrics mOnCreateCurrentMetrics;
        private final OnLayoutChangeListener mListener = new OnLayoutChangeListener();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mOnCreateCurrentMetrics = getWindowManager().getCurrentWindowMetrics();
            mOnCreateMaximumMetrics = getWindowManager().getMaximumWindowMetrics();
            getWindow().getDecorView().addOnLayoutChangeListener(mListener);

            // Always extend the cutout areas because layout doesn't get the waterfall cutout.
            final WindowManager.LayoutParams attrs = getWindow().getAttributes();
            attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
            getWindow().setAttributes(attrs);
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            getWindow().getDecorView().removeOnLayoutChangeListener(mListener);
        }
    }

    public static class MinAspectRatioActivity extends MetricsActivity {
    }
}
