blob: 1b3272572db04156768ef5e6b98a338ec3d47916 [file] [log] [blame]
Jorim Jaggib6030952018-10-23 18:31:52 +02001/*
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 android.view;
18
Adrian Roos021f4a72020-06-05 17:06:07 +020019import static android.view.InsetsController.ANIMATION_TYPE_NONE;
20import static android.view.InsetsController.ANIMATION_TYPE_USER;
21import static android.view.InsetsState.ITYPE_IME;
Tiger Huang332793b2019-10-29 23:21:27 +080022import static android.view.InsetsState.ITYPE_STATUS_BAR;
Jorim Jaggi3182ef12020-01-30 00:16:18 +010023import static android.view.WindowInsets.Type.statusBars;
Diego Velaa586fa32020-04-03 14:26:51 -070024
Jorim Jaggi3182ef12020-01-30 00:16:18 +010025import static junit.framework.Assert.assertEquals;
Tarandeep Singh92d2dd32019-08-07 14:45:01 -070026import static junit.framework.TestCase.assertFalse;
27import static junit.framework.TestCase.assertTrue;
28
Jorim Jaggib6030952018-10-23 18:31:52 +020029import static org.mockito.ArgumentMatchers.eq;
Adrian Roos021f4a72020-06-05 17:06:07 +020030import static org.mockito.Mockito.mock;
Jorim Jaggib6030952018-10-23 18:31:52 +020031import static org.mockito.Mockito.reset;
32import static org.mockito.Mockito.verify;
33import static org.mockito.Mockito.verifyZeroInteractions;
34
Tarandeep Singh5c071ef2019-03-18 15:57:53 -070035import android.app.Instrumentation;
36import android.content.Context;
Tarandeep Singh215929b2019-01-11 18:24:37 -080037import android.graphics.Point;
Adrian Roos021f4a72020-06-05 17:06:07 +020038import android.graphics.Rect;
Jorim Jaggib6030952018-10-23 18:31:52 +020039import android.platform.test.annotations.Presubmit;
Jorim Jaggib6030952018-10-23 18:31:52 +020040import android.view.SurfaceControl.Transaction;
Tarandeep Singh5c071ef2019-03-18 15:57:53 -070041import android.view.WindowManager.BadTokenException;
42import android.view.WindowManager.LayoutParams;
43import android.widget.TextView;
Jorim Jaggib6030952018-10-23 18:31:52 +020044
Diego Velaa586fa32020-04-03 14:26:51 -070045import androidx.test.ext.junit.runners.AndroidJUnit4;
46import androidx.test.platform.app.InstrumentationRegistry;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090047
Jorim Jaggib6030952018-10-23 18:31:52 +020048import org.junit.Before;
49import org.junit.Test;
50import org.junit.runner.RunWith;
51import org.mockito.Mock;
Tarandeep Singh92d2dd32019-08-07 14:45:01 -070052import org.mockito.Mockito;
Jorim Jaggib6030952018-10-23 18:31:52 +020053import org.mockito.MockitoAnnotations;
54
Tadashi G. Takaoka82eb7a52019-03-26 18:22:01 +090055/**
56 * Tests for {@link InsetsSourceConsumer}.
57 *
58 * <p>Build/Install/Run:
59 * atest FrameworksCoreTests:InsetsSourceConsumerTest
60 *
61 * <p>This test class is a part of Window Manager Service tests and specified in
62 * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
63 */
Jorim Jaggib6030952018-10-23 18:31:52 +020064@Presubmit
Jorim Jaggib6030952018-10-23 18:31:52 +020065@RunWith(AndroidJUnit4.class)
66public class InsetsSourceConsumerTest {
67
68 private InsetsSourceConsumer mConsumer;
69
70 private SurfaceSession mSession = new SurfaceSession();
71 private SurfaceControl mLeash;
72 @Mock Transaction mMockTransaction;
Tarandeep Singh92d2dd32019-08-07 14:45:01 -070073 private InsetsSource mSpyInsetsSource;
Jorim Jaggib6030952018-10-23 18:31:52 +020074
75 @Before
76 public void setup() {
77 MockitoAnnotations.initMocks(this);
78 mLeash = new SurfaceControl.Builder(mSession)
79 .setName("testSurface")
80 .build();
Tarandeep Singh5c071ef2019-03-18 15:57:53 -070081 final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
82 instrumentation.runOnMainSync(() -> {
83 final Context context = instrumentation.getTargetContext();
84 // cannot mock ViewRootImpl since it's final.
Andrii Kulian5877c7d2020-01-29 16:57:32 -080085 final ViewRootImpl viewRootImpl = new ViewRootImpl(context,
86 context.getDisplayNoVerify());
Tarandeep Singh5c071ef2019-03-18 15:57:53 -070087 try {
88 viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
89 } catch (BadTokenException e) {
90 // activity isn't running, lets ignore BadTokenException.
91 }
Tarandeep Singh92d2dd32019-08-07 14:45:01 -070092 InsetsState state = new InsetsState();
Tiger Huang332793b2019-10-29 23:21:27 +080093 mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR));
Tarandeep Singh92d2dd32019-08-07 14:45:01 -070094 state.addSource(mSpyInsetsSource);
95
Tiger Huang332793b2019-10-29 23:21:27 +080096 mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, state,
Jorim Jaggibf87c152020-04-22 17:18:25 +020097 () -> mMockTransaction,
98 new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl)));
Tarandeep Singh5c071ef2019-03-18 15:57:53 -070099 });
100 instrumentation.waitForIdleSync();
101
Jorim Jaggi3182ef12020-01-30 00:16:18 +0100102 mConsumer.setControl(new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point()),
103 new int[1], new int[1]);
Jorim Jaggib6030952018-10-23 18:31:52 +0200104 }
105
106 @Test
107 public void testHide() {
Jorim Jaggi3182ef12020-01-30 00:16:18 +0100108 InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
109 mConsumer.hide();
110 assertFalse("Consumer should not be visible", mConsumer.isRequestedVisible());
111 verify(mSpyInsetsSource).setVisible(eq(false));
112 });
113
Jorim Jaggib6030952018-10-23 18:31:52 +0200114 }
115
116 @Test
117 public void testShow() {
Jorim Jaggi3182ef12020-01-30 00:16:18 +0100118 InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
119 // Insets source starts out visible
120 mConsumer.hide();
121 mConsumer.show(false /* fromIme */);
122 assertTrue("Consumer should be visible", mConsumer.isRequestedVisible());
123 verify(mSpyInsetsSource).setVisible(eq(false));
124 verify(mSpyInsetsSource).setVisible(eq(true));
125 });
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +0100126
Jorim Jaggib6030952018-10-23 18:31:52 +0200127 }
128
129 @Test
Adrian Roos021f4a72020-06-05 17:06:07 +0200130 public void testPendingStates() {
131 InsetsState state = new InsetsState();
132 InsetsController controller = mock(InsetsController.class);
133 InsetsSourceConsumer consumer = new InsetsSourceConsumer(
134 ITYPE_IME, state, null, controller);
135
Adrian Roos021f4a72020-06-05 17:06:07 +0200136 InsetsSource source = new InsetsSource(ITYPE_IME);
137 source.setFrame(0, 1, 2, 3);
Tiger Huang618dbe022020-06-19 00:12:55 +0800138 consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_NONE);
Adrian Roos021f4a72020-06-05 17:06:07 +0200139
140 // While we're animating, updates are delayed
141 source.setFrame(4, 5, 6, 7);
Tiger Huang618dbe022020-06-19 00:12:55 +0800142 consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
Adrian Roos021f4a72020-06-05 17:06:07 +0200143 assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame());
144
145 // Finish the animation, now the pending frame should be applied
Adrian Roos021f4a72020-06-05 17:06:07 +0200146 assertTrue(consumer.notifyAnimationFinished());
147 assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
148
Adrian Roos021f4a72020-06-05 17:06:07 +0200149 // Animating again, updates are delayed
150 source.setFrame(8, 9, 10, 11);
Tiger Huang618dbe022020-06-19 00:12:55 +0800151 consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
Adrian Roos021f4a72020-06-05 17:06:07 +0200152 assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
153
154 // Updating with the current frame triggers a different code path, verify this clears
155 // the pending 8, 9, 10, 11 frame:
156 source.setFrame(4, 5, 6, 7);
Tiger Huang618dbe022020-06-19 00:12:55 +0800157 consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
Adrian Roos021f4a72020-06-05 17:06:07 +0200158
Adrian Roos021f4a72020-06-05 17:06:07 +0200159 assertFalse(consumer.notifyAnimationFinished());
160 assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
161 }
162
163 @Test
Jorim Jaggib6030952018-10-23 18:31:52 +0200164 public void testRestore() {
Jorim Jaggi3182ef12020-01-30 00:16:18 +0100165 InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
166 mConsumer.setControl(null, new int[1], new int[1]);
167 reset(mMockTransaction);
168 mConsumer.hide();
169 verifyZeroInteractions(mMockTransaction);
170 int[] hideTypes = new int[1];
171 mConsumer.setControl(new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point()),
172 new int[1], hideTypes);
173 assertEquals(statusBars(), hideTypes[0]);
174 });
Jorim Jaggib6030952018-10-23 18:31:52 +0200175 }
176}