1 /*
2  * Copyright (C) 2020 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 
17 package android.server.wm;
18 
19 import static android.server.wm.WindowMetricsTestHelper.assertMetricsMatchesLayout;
20 import static android.server.wm.WindowMetricsTestHelper.assertMetricsValidity;
21 import static android.view.Display.DEFAULT_DISPLAY;
22 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
23 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
25 
26 import android.content.Context;
27 import android.graphics.PixelFormat;
28 import android.graphics.Point;
29 import android.graphics.Rect;
30 import android.hardware.display.DisplayManager;
31 import android.platform.test.annotations.Presubmit;
32 import android.server.wm.WindowMetricsTestHelper.OnLayoutChangeListener;
33 import android.view.Display;
34 import android.view.View;
35 import android.view.WindowManager;
36 import android.view.WindowMetrics;
37 
38 import androidx.test.core.app.ApplicationProvider;
39 import androidx.test.platform.app.InstrumentationRegistry;
40 
41 import org.junit.Test;
42 
43 /**
44  * Tests that verify the behavior of {@link WindowMetrics} and {@link android.app.WindowContext}
45  * APIs
46  *
47  * Build/Install/Run:
48  *     atest CtsWindowManagerDeviceTestCases:WindowMetricsWindowContextTests
49  */
50 @Presubmit
51 public class WindowMetricsWindowContextTests extends WindowManagerTestBase {
52     @Test
testMetricsMatchesLayoutOnWindowContext()53     public void testMetricsMatchesLayoutOnWindowContext() {
54         createAllowSystemAlertWindowAppOpSession();
55         final WindowContextTestSession mWindowContextSession =
56                 mObjectTracker.manage(new WindowContextTestSession());
57 
58         mWindowContextSession.assertWindowContextMetricsMatchesLayout();
59     }
60 
61     @Test
testMetricsMatchesDisplayAreaOnWindowContext()62     public void testMetricsMatchesDisplayAreaOnWindowContext() {
63         createAllowSystemAlertWindowAppOpSession();
64         final WindowContextTestSession mWindowContextSession =
65                 mObjectTracker.manage(new WindowContextTestSession());
66 
67         mWindowContextSession.assertWindowContextMetricsMatchesDisplayArea();
68     }
69 
70     private class WindowContextTestSession implements AutoCloseable {
71         private static final String TEST_WINDOW_NAME = "WindowMetricsTests";
72         private View mView;
73         private final Context mWindowContext;
74         private final WindowManager mWm;
75         private final OnLayoutChangeListener mListener = new OnLayoutChangeListener();
76 
WindowContextTestSession()77         private WindowContextTestSession() {
78             final Context appContext = ApplicationProvider.getApplicationContext();
79             final Display display = appContext.getSystemService(DisplayManager.class)
80                     .getDisplay(DEFAULT_DISPLAY);
81             mWindowContext = appContext.createDisplayContext(display)
82                     .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
83 
84             mWm = mWindowContext.getSystemService(WindowManager.class);
85 
86             InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
87                 mView = new View(mWindowContext);
88                 mView.addOnLayoutChangeListener(mListener);
89                 final WindowManager.LayoutParams params = getFullscreenOverlayAttributes();
90                 mWm.addView(mView, params);
91             });
92         }
93 
assertWindowContextMetricsMatchesLayout()94         private void assertWindowContextMetricsMatchesLayout() {
95             mListener.waitForLayout();
96 
97             final WindowMetrics currentMetrics = mWm.getCurrentWindowMetrics();
98             final WindowMetrics maxMetrics = mWm.getMaximumWindowMetrics();
99 
100             assertMetricsMatchesLayout(currentMetrics, maxMetrics,
101                     mListener.getLayoutBounds(), mListener.getLayoutInsets());
102         }
103 
104         /**
105          * Verifies two scenarios for a {@link android.window.WindowContext}.
106          * <ul>
107          *     <li>{@link WindowManager#getCurrentWindowMetrics()} matches
108          *     {@link Display#getSize(Point)}</li>
109          *     <li>{@link WindowManager#getMaximumWindowMetrics()} and
110          *     {@link Display#getSize(Point)} either matches DisplayArea bounds, or matches
111          *     {@link WindowManager#getCurrentWindowMetrics()} if sandboxing is applied.</li>
112          * </ul>
113          */
assertWindowContextMetricsMatchesDisplayArea()114         private void assertWindowContextMetricsMatchesDisplayArea() {
115             mWmState.computeState();
116             WindowManagerState.DisplayArea da = mWmState.getDisplayArea(TEST_WINDOW_NAME);
117             final Rect daBounds = da.mFullConfiguration.windowConfiguration.getBounds();
118             assertMetricsValidity(mWindowContext, daBounds);
119         }
120 
121         @Override
close()122         public void close() throws Exception {
123             InstrumentationRegistry.getInstrumentation().runOnMainSync(()
124                     -> mWm.removeViewImmediate(mView));
125             mView.removeOnLayoutChangeListener(mListener);
126         }
127 
getFullscreenOverlayAttributes()128         private WindowManager.LayoutParams getFullscreenOverlayAttributes() {
129             final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
130                     MATCH_PARENT, MATCH_PARENT, TYPE_APPLICATION_OVERLAY, 0,
131                     PixelFormat.TRANSLUCENT);
132             // Used for obtain the attached DisplayArea.
133             params.setTitle(TEST_WINDOW_NAME);
134             params.setFitInsetsTypes(0 /* types */);
135             params.setFitInsetsIgnoringVisibility(true);
136             params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
137             return params;
138         }
139     }
140 }
141