/*
 * Copyright (C) 2016 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 org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.app.ActivityManager.TaskDescription;
import android.content.Context;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindow;
import android.view.WindowManager;

import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.FILL_PARENT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
 *
 * Build/Install/Run: bit FrameworksServicesTests:com.android.server.wm.WindowFrameTests
 */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class WindowFrameTests extends WindowTestsBase {

    private WindowToken mWindowToken;
    private final IWindow mIWindow = new TestIWindow();

    class WindowStateWithTask extends WindowState {
        final Task mTask;
        boolean mDockedResizingForTest = false;
        WindowStateWithTask(WindowManager.LayoutParams attrs, Task t) {
            super(sWm, null, mIWindow, mWindowToken, null, 0, 0, attrs, 0, 0,
                    false /* ownerCanAddInternalSystemWindow */);
            mTask = t;
        }

        @Override
        Task getTask() {
            return mTask;
        }

        @Override
        boolean isDockedResizing() {
            return mDockedResizingForTest;
        }
    };

    class TaskWithBounds extends Task {
        final Rect mBounds;
        final Rect mInsetBounds = new Rect();
        boolean mFullscreenForTest = true;
        TaskWithBounds(Rect bounds) {
            super(0, mStubStack, 0, sWm, null, null, 0, false, false, new TaskDescription(), null);
            mBounds = bounds;
        }
        @Override
        void getBounds(Rect outBounds) {
            outBounds.set(mBounds);
        }
        @Override
        void getTempInsetBounds(Rect outBounds) {
            outBounds.set(mInsetBounds);
        }
        @Override
        boolean isFullscreen() {
            return mFullscreenForTest;
        }
    }

    TaskStack mStubStack;

    @Before
    public void setUp() throws Exception {
        super.setUp();

        // Just any non zero value.
        sWm.mSystemDecorLayer = 10000;

        mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
        mStubStack = new TaskStack(sWm, 0);
    }

    public void assertRect(Rect rect, int left, int top, int right, int bottom) {
        assertEquals(left, rect.left);
        assertEquals(top, rect.top);
        assertEquals(right, rect.right);
        assertEquals(bottom, rect.bottom);
    }

    @Test
    public void testLayoutInFullscreenTaskInsets() throws Exception {
        Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;

        final int bottomContentInset = 100;
        final int topContentInset = 50;
        final int bottomVisibleInset = 30;
        final int topVisibleInset = 70;
        final int leftStableInset = 20;
        final int rightStableInset = 90;

        // With no insets or system decor all the frames incoming from PhoneWindowManager
        // are identical.
        final Rect pf = new Rect(0, 0, 1000, 1000);
        final Rect df = pf;
        final Rect of = df;
        final Rect cf = new Rect(pf);
        // Produce some insets
        cf.top += 50;
        cf.bottom -= 100;
        final Rect vf = new Rect(pf);
        vf.top += topVisibleInset;
        vf.bottom -= bottomVisibleInset;
        final Rect sf = new Rect(pf);
        sf.left += leftStableInset;
        sf.right -= rightStableInset;

        final Rect dcf = pf;
        // When mFrame extends past cf, the content insets are
        // the difference between mFrame and ContentFrame. Visible
        // and stable frames work the same way.
        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
        assertRect(w.mFrame,0, 0, 1000, 1000);
        assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
        assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
        assertRect(w.mStableInsets, leftStableInset, 0, rightStableInset, 0);
        // The frames remain as passed in shrunk to the window frame
        assertTrue(cf.equals(w.getContentFrameLw()));
        assertTrue(vf.equals(w.getVisibleFrameLw()));
        assertTrue(sf.equals(w.getStableFrameLw()));
        // On the other hand mFrame doesn't extend past cf we won't get any insets
        w.mAttrs.x = 100;
        w.mAttrs.y = 100;
        w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
        w.mRequestedWidth = 100;
        w.mRequestedHeight = 100;
        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
        assertRect(w.mFrame, 100, 100, 200, 200);
        assertRect(w.mContentInsets, 0, 0, 0, 0);
        // In this case the frames are shrunk to the window frame.
        assertTrue(w.mFrame.equals(w.getContentFrameLw()));
        assertTrue(w.mFrame.equals(w.getVisibleFrameLw()));
        assertTrue(w.mFrame.equals(w.getStableFrameLw()));
    }

    @Test
    public void testLayoutInFullscreenTaskNoInsets() throws Exception {
        Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;

        // With no insets or system decor all the frames incoming from PhoneWindowManager
        // are identical.
        final Rect pf = new Rect(0, 0, 1000, 1000);

        // Here the window has FILL_PARENT, FILL_PARENT
        // so we expect it to fill the entire available frame.
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 0, 0, 1000, 1000);

        // It can select various widths and heights within the bounds.
        // Strangely the window attribute width is ignored for normal windows
        // and we use mRequestedWidth/mRequestedHeight
        w.mAttrs.width = 300;
        w.mAttrs.height = 300;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        // Explicit width and height without requested width/height
        // gets us nothing.
        assertRect(w.mFrame, 0, 0, 0, 0);

        w.mRequestedWidth = 300;
        w.mRequestedHeight = 300;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        // With requestedWidth/Height we can freely choose our size within the
        // parent bounds.
        assertRect(w.mFrame, 0, 0, 300, 300);

        // With FLAG_SCALED though, requestedWidth/height is used to control
        // the unscaled surface size, and mAttrs.width/height becomes the
        // layout controller.
        w.mAttrs.flags = WindowManager.LayoutParams.FLAG_SCALED;
        w.mRequestedHeight = -1;
        w.mRequestedWidth = -1;
        w.mAttrs.width = 100;
        w.mAttrs.height = 100;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 0, 0, 100, 100);
        w.mAttrs.flags = 0;

        // But sizes too large will be clipped to the containing frame
        w.mRequestedWidth = 1200;
        w.mRequestedHeight = 1200;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 0, 0, 1000, 1000);

        // Before they are clipped though windows will be shifted
        w.mAttrs.x = 300;
        w.mAttrs.y = 300;
        w.mRequestedWidth = 1000;
        w.mRequestedHeight = 1000;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 0, 0, 1000, 1000);

        // If there is room to move around in the parent frame the window will be shifted according
        // to gravity.
        w.mAttrs.x = 0;
        w.mAttrs.y = 0;
        w.mRequestedWidth = 300;
        w.mRequestedHeight = 300;
        w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 700, 0, 1000, 300);
        w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 700, 700, 1000, 1000);
        // Window specified  x and y are interpreted as offsets in the opposite
        // direction of gravity
        w.mAttrs.x = 100;
        w.mAttrs.y = 100;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
        assertRect(w.mFrame, 600, 600, 900, 900);
    }

    @Test
    public void testLayoutNonfullscreenTask() {
        final DisplayInfo displayInfo = sWm.getDefaultDisplayContentLocked().getDisplayInfo();
        final int logicalWidth = displayInfo.logicalWidth;
        final int logicalHeight = displayInfo.logicalHeight;

        final int taskLeft = logicalWidth / 4;
        final int taskTop = logicalHeight / 4;
        final int taskRight = logicalWidth / 4 * 3;
        final int taskBottom = logicalHeight / 4 * 3;
        final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
        TaskWithBounds task = new TaskWithBounds(taskBounds);
        task.mFullscreenForTest = false;
        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;

        final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null);
        // For non fullscreen tasks the containing frame is based off the
        // task bounds not the parent frame.
        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
        assertRect(w.mContentInsets, 0, 0, 0, 0);

        pf.set(0, 0, logicalWidth, logicalHeight);
        // We still produce insets against the containing frame the same way.
        final int cfRight = logicalWidth / 2;
        final int cfBottom = logicalHeight / 2;
        final Rect cf = new Rect(0, 0, cfRight, cfBottom);
        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
        int contentInsetRight = taskRight - cfRight;
        int contentInsetBottom = taskBottom - cfBottom;
        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
                taskBottom - contentInsetBottom);

        pf.set(0, 0, logicalWidth, logicalHeight);
        // However if we set temp inset bounds, the insets will be computed
        // as if our window was laid out there,  but it will be laid out according to
        // the task bounds.
        final int insetLeft = logicalWidth / 5;
        final int insetTop = logicalHeight / 5;
        final int insetRight = insetLeft + (taskRight - taskLeft);
        final int insetBottom = insetTop + (taskBottom - taskTop);
        task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
        contentInsetRight = insetRight - cfRight;
        contentInsetBottom = insetBottom - cfBottom;
        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
                taskBottom - contentInsetBottom);
    }

    @Test
    public void testCalculatePolicyCrop() {
        final WindowStateWithTask w = createWindow(
                new TaskWithBounds(null), FILL_PARENT, FILL_PARENT);
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;

        final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
        final int logicalWidth = displayInfo.logicalWidth;
        final int logicalHeight = displayInfo.logicalHeight;
        final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
        final Rect df = pf;
        final Rect of = df;
        final Rect cf = new Rect(pf);
        // Produce some insets
        cf.top += displayInfo.logicalWidth / 10;
        cf.bottom -= displayInfo.logicalWidth / 5;
        final Rect vf = cf;
        final Rect sf = vf;
        // We use a decor content frame with insets to produce cropping.
        Rect dcf = cf;

        final Rect policyCrop = new Rect();

        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
        w.calculatePolicyCrop(policyCrop);
        // If we were above system decor we wouldnt' get any cropping though
        w.mLayer = sWm.mSystemDecorLayer + 1;
        w.calculatePolicyCrop(policyCrop);
        assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
        w.mLayer = 1;
        dcf.setEmpty();
        // Likewise with no decor frame we would get no crop
        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
        w.calculatePolicyCrop(policyCrop);
        assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);

        // Now we set up a window which doesn't fill the entire decor frame.
        // Normally it would be cropped to it's frame but in the case of docked resizing
        // we need to account for the fact the windows surface will be made
        // fullscreen and thus also make the crop fullscreen.
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
        w.mAttrs.width = logicalWidth / 2;
        w.mAttrs.height = logicalHeight / 2;
        w.mRequestedWidth = logicalWidth / 2;
        w.mRequestedHeight = logicalHeight / 2;
        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);

        w.calculatePolicyCrop(policyCrop);
        // Normally the crop is shrunk from the decor frame
        // to the computed window frame.
        assertRect(policyCrop, 0, 0, logicalWidth / 2, logicalHeight / 2);

        w.mDockedResizingForTest = true;
        w.calculatePolicyCrop(policyCrop);
        // But if we are docked resizing it won't be, however we will still be
        // shrunk to the decor frame and the display.
        assertRect(policyCrop, 0, 0,
                Math.min(pf.width(), displayInfo.logicalWidth),
                Math.min(pf.height(), displayInfo.logicalHeight));
    }

    @Test
    public void testLayoutLetterboxedWindow() {
        // First verify task behavior in multi-window mode.
        final DisplayInfo displayInfo = sWm.getDefaultDisplayContentLocked().getDisplayInfo();
        final int logicalWidth = displayInfo.logicalWidth;
        final int logicalHeight = displayInfo.logicalHeight;

        final int taskLeft = logicalWidth / 5;
        final int taskTop = logicalHeight / 5;
        final int taskRight = logicalWidth / 4 * 3;
        final int taskBottom = logicalHeight / 4 * 3;
        final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
        TaskWithBounds task = new TaskWithBounds(taskBounds);
        task.mInsetBounds.set(taskLeft, taskTop, taskRight, taskBottom);
        task.mFullscreenForTest = false;
        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;

        final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
                pf /* contentFrame */, pf /* visibleFrame */, pf /* decorFrame */,
                pf /* stableFrame */, null /* outsetFrame */);
        // For non fullscreen tasks the containing frame is based off the
        // task bounds not the parent frame.
        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
        assertRect(w.mContentInsets, 0, 0, 0, 0);

        // Now simulate switch to fullscreen for letterboxed app.
        final int xInset = logicalWidth / 10;
        final int yInset = logicalWidth / 10;
        final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
        w.mAppToken.onOverrideConfigurationChanged(w.mAppToken.getOverrideConfiguration(), cf);
        pf.set(0, 0, logicalWidth, logicalHeight);
        task.mFullscreenForTest = true;

        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
                cf /* contentFrame */, cf /* visibleFrame */, pf /* decorFrame */,
                cf /* stableFrame */, null /* outsetFrame */);
        assertEquals(cf, w.mFrame);
        assertEquals(cf, w.getContentFrameLw());
        assertRect(w.mContentInsets, 0, 0, 0, 0);
    }

    private WindowStateWithTask createWindow(Task task, int width, int height) {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
        attrs.width = width;
        attrs.height = height;

        return new WindowStateWithTask(attrs, task);
    }
}
