blob: 30665b56c8dc91ed49f4cd094bcc4646786e3b6b [file] [log] [blame]
Yohei Yukawad0a66b22018-01-10 13:19:54 -08001/*
2 * Copyright (C) 2018 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.policy;
18
19import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
20import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
21import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
22import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
23import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
24import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
25import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
26import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
27import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
28import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
29import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
30import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
Matthew Ng62c78462018-04-09 14:43:21 -070031import static android.view.WindowManager.DOCKED_BOTTOM;
32import static android.view.WindowManager.DOCKED_LEFT;
33import static android.view.WindowManager.DOCKED_RIGHT;
34import static android.view.WindowManager.DOCKED_TOP;
Yohei Yukawad0a66b22018-01-10 13:19:54 -080035
Matthew Ng62c78462018-04-09 14:43:21 -070036import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
Yohei Yukawad0a66b22018-01-10 13:19:54 -080037import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
38import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
39
40import static org.junit.Assert.assertEquals;
Matthew Ng62c78462018-04-09 14:43:21 -070041import static org.junit.Assert.assertFalse;
Yohei Yukawad0a66b22018-01-10 13:19:54 -080042import static org.junit.Assert.assertNull;
Matthew Ng62c78462018-04-09 14:43:21 -070043import static org.junit.Assert.assertTrue;
Yohei Yukawad0a66b22018-01-10 13:19:54 -080044
45import android.graphics.PixelFormat;
46import android.platform.test.annotations.Presubmit;
47import android.support.test.filters.SmallTest;
48import android.support.test.runner.AndroidJUnit4;
49import android.view.WindowManager;
50
51import org.junit.Test;
52import org.junit.runner.RunWith;
53
54@RunWith(AndroidJUnit4.class)
55@SmallTest
56@Presubmit
57public class PhoneWindowManagerTest {
58
59 private static FakeWindowState createOpaqueFullscreen(boolean hasLightNavBar) {
60 final FakeWindowState state = new FakeWindowState();
61 state.attrs = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT,
62 TYPE_BASE_APPLICATION,
63 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
64 PixelFormat.OPAQUE);
65 state.attrs.subtreeSystemUiVisibility =
66 hasLightNavBar ? SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0;
67 return state;
68 }
69
70 private static FakeWindowState createDimmingDialogWindow(boolean canBeImTarget) {
71 final FakeWindowState state = new FakeWindowState();
72 state.attrs = new WindowManager.LayoutParams(WRAP_CONTENT, WRAP_CONTENT,
73 TYPE_APPLICATION,
74 FLAG_DIM_BEHIND | (canBeImTarget ? 0 : FLAG_ALT_FOCUSABLE_IM),
75 PixelFormat.TRANSLUCENT);
76 state.isDimming = true;
77 return state;
78 }
79
80 private static FakeWindowState createInputMethodWindow(boolean visible, boolean drawNavBar,
81 boolean hasLightNavBar) {
82 final FakeWindowState state = new FakeWindowState();
83 state.attrs = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT,
84 TYPE_INPUT_METHOD,
85 FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN
86 | (drawNavBar ? FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS : 0),
87 PixelFormat.TRANSPARENT);
88 state.attrs.subtreeSystemUiVisibility =
89 hasLightNavBar ? SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0;
90 state.visible = visible;
91 state.policyVisible = visible;
92 return state;
93 }
94
95
96 @Test
97 public void testChooseNavigationColorWindowLw() throws Exception {
98 final FakeWindowState opaque = createOpaqueFullscreen(false);
99
100 final FakeWindowState dimmingImTarget = createDimmingDialogWindow(true);
101 final FakeWindowState dimmingNonImTarget = createDimmingDialogWindow(false);
102
103 final FakeWindowState visibleIme = createInputMethodWindow(true, true, false);
104 final FakeWindowState invisibleIme = createInputMethodWindow(false, true, false);
105 final FakeWindowState imeNonDrawNavBar = createInputMethodWindow(true, false, false);
106
107 // If everything is null, return null
108 assertNull(null, PhoneWindowManager.chooseNavigationColorWindowLw(
109 null, null, null, NAV_BAR_BOTTOM));
110
111 assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
112 opaque, opaque, null, NAV_BAR_BOTTOM));
113 assertEquals(dimmingImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
114 opaque, dimmingImTarget, null, NAV_BAR_BOTTOM));
115 assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
116 opaque, dimmingNonImTarget, null, NAV_BAR_BOTTOM));
117
118 assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
119 null, null, visibleIme, NAV_BAR_BOTTOM));
120 assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
121 null, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM));
Yohei Yukawa217844e2018-01-10 13:19:59 -0800122 assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800123 null, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM));
124 assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
125 opaque, opaque, visibleIme, NAV_BAR_BOTTOM));
126 assertEquals(visibleIme, PhoneWindowManager.chooseNavigationColorWindowLw(
127 opaque, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM));
Yohei Yukawa217844e2018-01-10 13:19:59 -0800128 assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800129 opaque, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM));
130
131 assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
132 opaque, opaque, invisibleIme, NAV_BAR_BOTTOM));
133 assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
134 opaque, opaque, invisibleIme, NAV_BAR_BOTTOM));
135 assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
136 opaque, opaque, visibleIme, NAV_BAR_RIGHT));
137
138 // Only IME windows that have FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS should be navigation color
Yohei Yukawa217844e2018-01-10 13:19:59 -0800139 // window.
140 assertEquals(opaque, PhoneWindowManager.chooseNavigationColorWindowLw(
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800141 opaque, opaque, imeNonDrawNavBar, NAV_BAR_BOTTOM));
Yohei Yukawa217844e2018-01-10 13:19:59 -0800142 assertEquals(dimmingImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800143 opaque, dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
Yohei Yukawa217844e2018-01-10 13:19:59 -0800144 assertEquals(dimmingNonImTarget, PhoneWindowManager.chooseNavigationColorWindowLw(
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800145 opaque, dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM));
146 }
147
148 @Test
149 public void testUpdateLightNavigationBarLw() throws Exception {
150 final FakeWindowState opaqueDarkNavBar = createOpaqueFullscreen(false);
151 final FakeWindowState opaqueLightNavBar = createOpaqueFullscreen(true);
152
153 final FakeWindowState dimming = createDimmingDialogWindow(false);
154
155 final FakeWindowState imeDrawDarkNavBar = createInputMethodWindow(true,true, false);
156 final FakeWindowState imeDrawLightNavBar = createInputMethodWindow(true,true, true);
157
158 assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
159 PhoneWindowManager.updateLightNavigationBarLw(
160 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, null, null,
161 null, null));
162
163 // Opaque top fullscreen window overrides SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR flag.
164 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
165 0, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar));
166 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
167 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueDarkNavBar, opaqueDarkNavBar, null,
168 opaqueDarkNavBar));
169 assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
170 PhoneWindowManager.updateLightNavigationBarLw(0, opaqueLightNavBar,
171 opaqueLightNavBar, null, opaqueLightNavBar));
172 assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
173 PhoneWindowManager.updateLightNavigationBarLw(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
174 opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar));
175
176 // Dimming window clears SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.
177 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
178 0, opaqueDarkNavBar, dimming, null, dimming));
179 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
180 0, opaqueLightNavBar, dimming, null, dimming));
181 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
182 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueDarkNavBar, dimming, null, dimming));
183 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
184 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, dimming, null, dimming));
185 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
186 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, dimming, imeDrawLightNavBar,
187 dimming));
188
189 // IME window clears SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
190 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
191 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, null, null, imeDrawDarkNavBar,
192 imeDrawDarkNavBar));
193
194 // Even if the top fullscreen has SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, IME window wins.
195 assertEquals(0, PhoneWindowManager.updateLightNavigationBarLw(
196 SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, opaqueLightNavBar, opaqueLightNavBar,
197 imeDrawDarkNavBar, imeDrawDarkNavBar));
198
Yohei Yukawa217844e2018-01-10 13:19:59 -0800199 // IME window should be able to use SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.
200 assertEquals(SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
201 PhoneWindowManager.updateLightNavigationBarLw(0, opaqueDarkNavBar,
202 opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar));
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800203 }
Matthew Ng62c78462018-04-09 14:43:21 -0700204
205 @Test
206 public void testIsDockSideAllowedDockTop() throws Exception {
207 // Docked top is always allowed
208 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_TOP, DOCKED_LEFT, NAV_BAR_BOTTOM,
209 true /* navigationBarCanMove */));
210 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_TOP, DOCKED_LEFT, NAV_BAR_BOTTOM,
211 false /* navigationBarCanMove */));
212 }
213
214 @Test
215 public void testIsDockSideAllowedDockBottom() throws Exception {
216 // Cannot dock bottom
217 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_BOTTOM, DOCKED_LEFT, NAV_BAR_BOTTOM,
218 true /* navigationBarCanMove */));
219 }
220
221 @Test
222 public void testIsDockSideAllowedNavigationBarMovable() throws Exception {
223 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, NAV_BAR_BOTTOM,
224 true /* navigationBarCanMove */));
225 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, NAV_BAR_LEFT,
226 true /* navigationBarCanMove */));
227 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, NAV_BAR_RIGHT,
228 true /* navigationBarCanMove */));
229 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, NAV_BAR_BOTTOM,
230 true /* navigationBarCanMove */));
231 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, NAV_BAR_RIGHT,
232 true /* navigationBarCanMove */));
233 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, NAV_BAR_LEFT,
234 true /* navigationBarCanMove */));
235 }
236
237 @Test
238 public void testIsDockSideAllowedNavigationBarNotMovable() throws Exception {
239 // Navigation bar is not movable such as tablets
240 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, NAV_BAR_BOTTOM,
241 false /* navigationBarCanMove */));
242 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_TOP, NAV_BAR_BOTTOM,
243 false /* navigationBarCanMove */));
244 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_LEFT, DOCKED_RIGHT, NAV_BAR_BOTTOM,
245 false /* navigationBarCanMove */));
246 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, NAV_BAR_BOTTOM,
247 false /* navigationBarCanMove */));
248 assertFalse(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_TOP, NAV_BAR_BOTTOM,
249 false /* navigationBarCanMove */));
250 assertTrue(PhoneWindowManager.isDockSideAllowed(DOCKED_RIGHT, DOCKED_RIGHT, NAV_BAR_BOTTOM,
251 false /* navigationBarCanMove */));
252 }
Yohei Yukawad0a66b22018-01-10 13:19:54 -0800253}