/*
 * Copyright (C) 2019 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 android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.TaskStackListener;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;

import androidx.test.filters.MediumTest;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * Tests for Size Compatibility mode.
 *
 * Build/Install/Run:
 *  atest WmTests:SizeCompatTests
 */
@MediumTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class SizeCompatTests extends ActivityTestsBase {
    private ActivityStack mStack;
    private Task mTask;
    private ActivityRecord mActivity;

    private void setUpApp(ActivityDisplay display) {
        mStack = new StackBuilder(mRootActivityContainer).setDisplay(display).build();
        mTask = mStack.getChildAt(0);
        mActivity = mTask.getTopNonFinishingActivity();
    }

    private void ensureActivityConfiguration() {
        mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
    }

    @Test
    public void testRestartProcessIfVisible() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
        doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity);
        mActivity.visible = true;
        mActivity.setSavedState(null /* savedState */);
        mActivity.setState(ActivityStack.ActivityState.RESUMED, "testRestart");
        prepareUnresizable(1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);

        final Rect originalOverrideBounds = new Rect(mActivity.getBounds());
        resizeDisplay(mStack.getDisplay(), 600, 1200);
        // The visible activity should recompute configuration according to the last parent bounds.
        mService.restartActivityProcessIfVisible(mActivity.appToken);

        assertEquals(ActivityStack.ActivityState.RESTARTING_PROCESS, mActivity.getState());
        assertNotEquals(originalOverrideBounds, mActivity.getBounds());
    }

    @Test
    public void testKeepBoundsWhenChangingFromFreeformToFullscreen() {
        removeGlobalMinSizeRestriction();
        // create freeform display and a freeform app
        ActivityDisplay display = new TestActivityDisplay.Builder(mService, 2000, 1000)
                .setCanRotate(false)
                .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM).build();
        setUpApp(display);

        // Put app window into freeform and then make it a compat app.
        mTask.setBounds(100, 100, 400, 600);
        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);

        final Rect bounds = new Rect(mActivity.getBounds());
        final int density = mActivity.getConfiguration().densityDpi;

        // change display configuration to fullscreen
        Configuration c = new Configuration(display.getRequestedOverrideConfiguration());
        c.windowConfiguration.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
        display.onRequestedOverrideConfigurationChanged(c);

        // check if dimensions stay the same
        assertTrue(mActivity.inSizeCompatMode());
        assertEquals(bounds.width(), mActivity.getBounds().width());
        assertEquals(bounds.height(), mActivity.getBounds().height());
        assertEquals(density, mActivity.getConfiguration().densityDpi);
    }

    @Test
    public void testFixedAspectRatioBoundsWithDecor() {
        final int decorHeight = 200; // e.g. The device has cutout.
        setUpApp(new TestActivityDisplay.Builder(mService, 600, 800)
                .setNotch(decorHeight).build());

        mActivity.info.minAspectRatio = mActivity.info.maxAspectRatio = 1;
        prepareUnresizable(-1f, SCREEN_ORIENTATION_UNSPECIFIED);

        // The parent configuration doesn't change since the first resolved configuration, so the
        // activity shouldn't be in the size compatibility mode.
        assertFalse(mActivity.inSizeCompatMode());

        final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
        // Ensure the app bounds keep the declared aspect ratio.
        assertEquals(appBounds.width(), appBounds.height());
        // The decor height should be a part of the effective bounds.
        assertEquals(mActivity.getBounds().height(), appBounds.height() + decorHeight);

        mTask.getConfiguration().windowConfiguration.setRotation(ROTATION_90);
        mActivity.onConfigurationChanged(mTask.getConfiguration());
        // After changing orientation, the aspect ratio should be the same.
        assertEquals(appBounds.width(), appBounds.height());
        // The decor height will be included in width.
        assertEquals(mActivity.getBounds().width(), appBounds.width() + decorHeight);
    }

    @Test
    public void testFixedScreenConfigurationWhenMovingToDisplay() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());

        // Make a new less-tall display with lower density
        final ActivityDisplay newDisplay =
                new TestActivityDisplay.Builder(mService, 1000, 2000)
                        .setDensityDpi(200).build();

        mActivity = new ActivityBuilder(mService)
                .setTask(mTask)
                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
                .setMaxAspectRatio(1.5f)
                .build();
        mActivity.visible = true;

        final Rect originalBounds = new Rect(mActivity.getBounds());
        final int originalDpi = mActivity.getConfiguration().densityDpi;

        // Move the non-resizable activity to the new display.
        mStack.reparent(newDisplay.mDisplayContent, true /* onTop */);

        assertEquals(originalBounds.width(), mActivity.getBounds().width());
        assertEquals(originalBounds.height(), mActivity.getBounds().height());
        assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
        assertTrue(mActivity.inSizeCompatMode());
    }

    @Test
    public void testFixedScreenBoundsWhenDisplaySizeChanged() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
        prepareUnresizable(-1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(mActivity.inSizeCompatMode());

        final Rect origBounds = new Rect(mActivity.getBounds());

        // Change the size of current display.
        resizeDisplay(mStack.getDisplay(), 1000, 2000);
        ensureActivityConfiguration();

        assertEquals(origBounds.width(), mActivity.getWindowConfiguration().getBounds().width());
        assertEquals(origBounds.height(), mActivity.getWindowConfiguration().getBounds().height());
        assertTrue(mActivity.inSizeCompatMode());

        // Change display size to a different orientation
        resizeDisplay(mStack.getDisplay(), 2000, 1000);
        ensureActivityConfiguration();
        assertEquals(origBounds.width(), mActivity.getWindowConfiguration().getBounds().width());
        assertEquals(origBounds.height(), mActivity.getWindowConfiguration().getBounds().height());
    }

    @Test
    public void testLetterboxFullscreenBounds() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());

        // Fill out required fields on default display since WM-side is mocked out
        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
        assertFalse(mActivity.inSizeCompatMode());
        assertTrue(mActivity.getBounds().width() > mActivity.getBounds().height());
    }

    @Test
    public void testMoveToDifferentOrientDisplay() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());

        final ActivityDisplay newDisplay =
                new TestActivityDisplay.Builder(mService, 2000, 1000)
                        .setCanRotate(false).build();

        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(mActivity.inSizeCompatMode());

        final Rect origBounds = new Rect(mActivity.getBounds());

        // Move the non-resizable activity to the new display.
        mStack.reparent(newDisplay.mDisplayContent, true /* onTop */);
        ensureActivityConfiguration();
        assertEquals(origBounds.width(), mActivity.getWindowConfiguration().getBounds().width());
        assertEquals(origBounds.height(), mActivity.getWindowConfiguration().getBounds().height());
        assertTrue(mActivity.inSizeCompatMode());
    }

    @Test
    public void testFixedOrientRotateCutoutDisplay() {
        // Create a display with a notch/cutout
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).setNotch(60).build());
        prepareUnresizable(1.4f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);

        final Rect origBounds = new Rect(mActivity.getBounds());
        final Rect origAppBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());

        // Rotate the display
        Configuration c = new Configuration();
        mStack.getDisplay().mDisplayContent.getDisplayRotation().setRotation(ROTATION_270);
        mStack.getDisplay().mDisplayContent.computeScreenConfiguration(c);
        mStack.getDisplay().onRequestedOverrideConfigurationChanged(c);

        // Make sure the app size is the same
        assertEquals(ROTATION_270, mStack.getWindowConfiguration().getRotation());
        assertEquals(origBounds.width(), mActivity.getWindowConfiguration().getBounds().width());
        assertEquals(origBounds.height(), mActivity.getWindowConfiguration().getBounds().height());
        assertEquals(origAppBounds.width(),
                mActivity.getWindowConfiguration().getAppBounds().width());
        assertEquals(origAppBounds.height(),
                mActivity.getWindowConfiguration().getAppBounds().height());
    }

    @Test
    public void testFixedAspOrientChangeOrient() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());

        prepareUnresizable(1.4f /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
        assertTrue(mActivity.inSizeCompatMode());

        final Rect originalBounds = new Rect(mActivity.getBounds());
        final Rect originalAppBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());

        // Change the fixed orientation
        mActivity.mOrientation = SCREEN_ORIENTATION_PORTRAIT;
        mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
        // TaskRecord's configuration actually depends on the activity config right now for
        // pillarboxing.
        mActivity.getTask().onRequestedOverrideConfigurationChanged(
                mActivity.getTask().getRequestedOverrideConfiguration());

        assertEquals(originalBounds.width(), mActivity.getBounds().height());
        assertEquals(originalBounds.height(), mActivity.getBounds().width());
        assertEquals(originalAppBounds.width(),
                mActivity.getWindowConfiguration().getAppBounds().height());
        assertEquals(originalAppBounds.height(),
                mActivity.getWindowConfiguration().getAppBounds().width());
    }

    @Test
    public void testFixedScreenLayoutSizeBits() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
        final int fixedScreenLayout = Configuration.SCREENLAYOUT_LONG_NO
                | Configuration.SCREENLAYOUT_SIZE_NORMAL;
        final int layoutMask = Configuration.SCREENLAYOUT_LONG_MASK
                | Configuration.SCREENLAYOUT_SIZE_MASK
                | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK;
        Configuration c = new Configuration(mTask.getRequestedOverrideConfiguration());
        c.screenLayout = fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR;
        mTask.onRequestedOverrideConfigurationChanged(c);
        prepareUnresizable(1.5f, SCREEN_ORIENTATION_UNSPECIFIED);

        // The initial configuration should inherit from parent.
        assertEquals(fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR,
                mActivity.getConfiguration().screenLayout & layoutMask);

        mTask.getConfiguration().screenLayout = Configuration.SCREENLAYOUT_LAYOUTDIR_RTL
                | Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_LARGE;
        mActivity.onConfigurationChanged(mTask.getConfiguration());

        // The size and aspect ratio bits don't change, but the layout direction should be updated.
        assertEquals(fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_RTL,
                mActivity.getConfiguration().screenLayout & layoutMask);
    }

    @Test
    public void testResetNonVisibleActivity() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2500).build());
        final ActivityDisplay display = mStack.getDisplay();
        spyOn(display);

        prepareUnresizable(1.5f, SCREEN_ORIENTATION_UNSPECIFIED);
        mActivity.setState(STOPPED, "testSizeCompatMode");
        mActivity.visible = false;
        mActivity.app.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
        // Make the parent bounds to be different so the activity is in size compatibility mode.
        mTask.getWindowConfiguration().setAppBounds(new Rect(0, 0, 600, 1200));

        // Simulate the display changes orientation.
        when(display.getLastOverrideConfigurationChanges()).thenReturn(
                ActivityInfo.CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION
                        | ActivityInfo.CONFIG_WINDOW_CONFIGURATION);
        mActivity.onConfigurationChanged(mTask.getConfiguration());
        when(display.getLastOverrideConfigurationChanges()).thenCallRealMethod();
        // The override configuration should not change so it is still in size compatibility mode.
        assertTrue(mActivity.inSizeCompatMode());

        // Change display density
        final DisplayContent displayContent = mStack.getDisplay().mDisplayContent;
        displayContent.mBaseDisplayDensity = (int) (0.7f * displayContent.mBaseDisplayDensity);
        final Configuration c = new Configuration();
        displayContent.computeScreenConfiguration(c);
        mService.mAmInternal = mock(ActivityManagerInternal.class);
        mStack.getDisplay().onRequestedOverrideConfigurationChanged(c);

        // The override configuration should be reset and the activity's process will be killed.
        assertFalse(mActivity.inSizeCompatMode());
        verify(mActivity).restartProcessIfVisible();
        mLockRule.runWithScissors(mService.mH, () -> { }, TimeUnit.SECONDS.toMillis(3));
        verify(mService.mAmInternal).killProcess(
                eq(mActivity.app.mName), eq(mActivity.app.mUid), anyString());
    }

    /**
     * Ensures that {@link TaskStackListener} can receive callback about the activity in size
     * compatibility mode.
     */
    @Test
    public void testHandleActivitySizeCompatMode() {
        setUpApp(new TestActivityDisplay.Builder(mService, 1000, 2000).build());
        ActivityRecord activity = mActivity;
        activity.setState(ActivityStack.ActivityState.RESUMED, "testHandleActivitySizeCompatMode");
        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        ensureActivityConfiguration();
        assertFalse(mActivity.inSizeCompatMode());

        final ArrayList<IBinder> compatTokens = new ArrayList<>();
        mService.getTaskChangeNotificationController().registerTaskStackListener(
                new TaskStackListener() {
                    @Override
                    public void onSizeCompatModeActivityChanged(int displayId,
                            IBinder activityToken) {
                        compatTokens.add(activityToken);
                    }
                });

        // Resize the display so that the activity exercises size-compat mode.
        resizeDisplay(mStack.getDisplay(), 1000, 2500);

        // Expect the exact token when the activity is in size compatibility mode.
        assertEquals(1, compatTokens.size());
        assertEquals(activity.appToken, compatTokens.get(0));

        compatTokens.clear();
        // Make the activity resizable again by restarting it
        activity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
        activity.visible = true;
        activity.restartProcessIfVisible();
        // The full lifecycle isn't hooked up so manually set state to resumed
        activity.setState(ActivityStack.ActivityState.RESUMED, "testHandleActivitySizeCompatMode");
        mStack.getDisplay().handleActivitySizeCompatModeIfNeeded(activity);

        // Expect null token when switching to non-size-compat mode activity.
        assertEquals(1, compatTokens.size());
        assertEquals(null, compatTokens.get(0));
    }

    /**
     * Setup {@link #mActivity} as a size-compat-mode-able activity with fixed aspect and/or
     * orientation.
     */
    private void prepareUnresizable(float maxAspect, int screenOrientation) {
        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
        mActivity.visible = true;
        if (maxAspect >= 0) {
            mActivity.info.maxAspectRatio = maxAspect;
        }
        if (screenOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
            mActivity.mOrientation = screenOrientation;
            mActivity.info.screenOrientation = screenOrientation;
            // TaskRecord's configuration actually depends on the activity config right now for
            // pillarboxing.
            mActivity.getTask().onRequestedOverrideConfigurationChanged(
                    mActivity.getTask().getRequestedOverrideConfiguration());
        }
        ensureActivityConfiguration();
    }

    private void resizeDisplay(ActivityDisplay display, int width, int height) {
        final DisplayContent displayContent = display.mDisplayContent;
        displayContent.mBaseDisplayWidth = width;
        displayContent.mBaseDisplayHeight = height;
        Configuration c = new Configuration();
        displayContent.computeScreenConfiguration(c);
        display.onRequestedOverrideConfigurationChanged(c);
    }
}
