1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
19import android.app.ActivityManager;
20import android.content.res.Configuration;
21import android.graphics.Rect;
22import android.view.DisplayInfo;
23import org.junit.Test;
24
25import android.platform.test.annotations.Presubmit;
26import android.support.test.filters.SmallTest;
27import android.support.test.runner.AndroidJUnit4;
28
29import static org.junit.Assert.assertEquals;
30import static org.junit.Assert.assertTrue;
31
32/**
33 * Test class to exercise logic related to {@link android.content.res.Configuration#appBounds}.
34 *
35 * Build/Install/Run:
36 *  bit FrameworksServicesTests:com.android.server.wm.AppBoundsTests
37 */
38@SmallTest
39@Presubmit
40@org.junit.runner.RunWith(AndroidJUnit4.class)
41public class AppBoundsTests extends WindowTestsBase {
42    private Rect mParentBounds;
43
44    @Override
45    public void setUp() throws Exception {
46        super.setUp();
47        mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
48    }
49
50    /**
51     * Ensures the configuration app bounds at the root level match the app dimensions.
52     */
53    @Test
54    public void testRootConfigurationBounds() throws Exception {
55        final DisplayInfo info = mDisplayContent.getDisplayInfo();
56        info.appWidth = 1024;
57        info.appHeight = 768;
58
59        final Configuration config = sWm.computeNewConfiguration(mDisplayContent.getDisplayId());
60        // The bounds should always be positioned in the top left.
61        assertEquals(config.appBounds.left, 0);
62        assertEquals(config.appBounds.top, 0);
63
64        // The bounds should equal the defined app width and height
65        assertEquals(config.appBounds.width(), info.appWidth);
66        assertEquals(config.appBounds.height(), info.appHeight);
67    }
68
69    /**
70     * Ensures that bounds are clipped to their parent.
71     */
72    @Test
73    public void testBoundsClipping() throws Exception {
74        final Rect shiftedBounds = new Rect(mParentBounds);
75        shiftedBounds.offset(10, 10);
76        final Rect expectedBounds = new Rect(mParentBounds);
77        expectedBounds.intersect(shiftedBounds);
78        testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds,
79                expectedBounds);
80    }
81
82    /**
83     * Ensures that empty bounds are not propagated to the configuration.
84     */
85    @Test
86    public void testEmptyBounds() throws Exception {
87        final Rect emptyBounds = new Rect();
88        testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds,
89                null /*ExpectedBounds*/);
90    }
91
92    /**
93     * Ensures that bounds on freeform stacks are not clipped.
94     */
95    @Test
96    public void testFreeFormBounds() throws Exception {
97        final Rect freeFormBounds = new Rect(mParentBounds);
98        freeFormBounds.offset(10, 10);
99        testStackBoundsConfiguration(ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID,
100                mParentBounds, freeFormBounds, freeFormBounds);
101    }
102
103    /**
104     * Ensures that fully contained bounds are not clipped.
105     */
106    @Test
107    public void testContainedBounds() throws Exception {
108        final Rect insetBounds = new Rect(mParentBounds);
109        insetBounds.inset(5, 5, 5, 5);
110        testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds);
111    }
112
113    /**
114     * Ensures that full screen free form bounds are clipped
115     */
116    @Test
117    public void testFullScreenFreeFormBounds() throws Exception {
118        final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth,
119                mDisplayInfo.logicalHeight);
120        testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds,
121                mParentBounds);
122    }
123
124
125    private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds,
126            Rect expectedConfigBounds) {
127        final StackWindowController stackController = stackId != null ?
128                createStackControllerOnStackOnDisplay(stackId, mDisplayContent)
129                : createStackControllerOnDisplay(mDisplayContent);
130
131        final Configuration parentConfig = mDisplayContent.getConfiguration();
132        parentConfig.setAppBounds(parentBounds);
133
134        final Configuration config = new Configuration();
135        stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/,
136                new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/,
137                false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig);
138        // Assert that both expected and actual are null or are equal to each other
139
140        assertTrue((expectedConfigBounds == null && config.appBounds == null)
141                || expectedConfigBounds.equals(config.appBounds));
142    }
143}
144