Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3a0627f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes If8232b90,I3176837e

* changes:
  Deobfuscate computeFrameLw parameters.
  Begin series of computeFrame unit tests
parents fedb6603 43521764
Loading
Loading
Loading
Loading
+27 −26
Original line number Diff line number Diff line
@@ -731,8 +731,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    @Override
    public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
            Rect osf) {
    public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
            Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
            Rect outsetFrame) {
        if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
            // This window is being replaced and either already got information that it's being
            // removed or we are still waiting for some information. Because of this we don't
@@ -768,10 +769,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final int layoutYDiff;
        if (fullscreenTask || layoutInParentFrame()) {
            // We use the parent frame as the containing frame for fullscreen and child windows
            mContainingFrame.set(pf);
            mDisplayFrame.set(df);
            layoutDisplayFrame = df;
            layoutContainingFrame = pf;
            mContainingFrame.set(parentFrame);
            mDisplayFrame.set(displayFrame);
            layoutDisplayFrame = displayFrame;
            layoutContainingFrame = parentFrame;
            layoutXDiff = 0;
            layoutYDiff = 0;
        } else {
@@ -787,15 +788,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            final WindowState imeWin = mService.mInputMethodWindow;
            // IME is up and obscuring this window. Adjust the window position so it is visible.
            if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
                    if (windowsAreFloating && mContainingFrame.bottom > cf.bottom) {
                    if (windowsAreFloating && mContainingFrame.bottom > contentFrame.bottom) {
                        // In freeform we want to move the top up directly.
                        // TODO: Investigate why this is cf not pf.
                        mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
                    } else if (mContainingFrame.bottom > pf.bottom) {
                        // TODO: Investigate why this is contentFrame not parentFrame.
                        mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
                    } else if (mContainingFrame.bottom > parentFrame.bottom) {
                        // But in docked we want to behave like fullscreen
                        // and behave as if the task were given smaller bounds
                        // for the purposes of layout.
                        mContainingFrame.bottom = pf.bottom;
                        mContainingFrame.bottom = parentFrame.bottom;
                    }
            }

@@ -804,7 +805,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                // if it wasn't set already. No need to intersect it with the (visible)
                // "content frame" since it is allowed to be outside the visible desktop.
                if (mContainingFrame.isEmpty()) {
                    mContainingFrame.set(cf);
                    mContainingFrame.set(contentFrame);
                }
            }
            mDisplayFrame.set(mContainingFrame);
@@ -812,22 +813,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
            layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
            mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
            subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect);
            subtractInsets(mDisplayFrame, layoutContainingFrame, displayFrame, mTmpRect);
            if (!layoutInParentFrame()) {
                subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect);
                subtractInsets(mInsetFrame, layoutContainingFrame, pf, mTmpRect);
                subtractInsets(mContainingFrame, layoutContainingFrame, parentFrame, mTmpRect);
                subtractInsets(mInsetFrame, layoutContainingFrame, parentFrame, mTmpRect);
            }
            layoutDisplayFrame = df;
            layoutDisplayFrame = displayFrame;
            layoutDisplayFrame.intersect(layoutContainingFrame);
        }

        final int pw = mContainingFrame.width();
        final int ph = mContainingFrame.height();

        if (!mParentFrame.equals(pf)) {
        if (!mParentFrame.equals(parentFrame)) {
            //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame
            //        + " to " + pf);
            mParentFrame.set(pf);
            //        + " to " + parentFrame);
            mParentFrame.set(parentFrame);
            mContentChanged = true;
        }
        if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
@@ -836,14 +837,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            mContentChanged = true;
        }

        mOverscanFrame.set(of);
        mContentFrame.set(cf);
        mVisibleFrame.set(vf);
        mDecorFrame.set(dcf);
        mStableFrame.set(sf);
        final boolean hasOutsets = osf != null;
        mOverscanFrame.set(overscanFrame);
        mContentFrame.set(contentFrame);
        mVisibleFrame.set(visibleFrame);
        mDecorFrame.set(decorFrame);
        mStableFrame.set(stableFrame);
        final boolean hasOutsets = outsetFrame != null;
        if (hasOutsets) {
            mOutsetFrame.set(osf);
            mOutsetFrame.set(outsetFrame);
        }

        final int fw = mFrame.width();
+189 −0
Original line number Diff line number Diff line
/*
 * 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.content.Context;
import android.graphics.Rect;
import android.os.Binder;
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.Gravity;
import android.view.IWindow;
import android.view.WindowManager;

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

/**
 * 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 {

    private static WindowManagerService sWm = null;
    private WindowToken mWindowToken;
    private final IWindow mIWindow = new TestIWindow();

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

        @Override
        Task getTask() {
            return mTask;
        }
    };

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

    TaskStack mStubStack;

    @Before
    public void setUp() throws Exception {
        final Context context = InstrumentationRegistry.getTargetContext();
        sWm = TestWindowManagerPolicy.getWindowManagerService(context);
        mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
                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 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);
    }

    private WindowState 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);
    }
}