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 android.view;
18
19import static android.view.DisplayCutout.NO_CUTOUT;
20import static android.view.DisplayCutout.fromSpec;
21
22import static org.hamcrest.Matchers.not;
23import static org.hamcrest.Matchers.sameInstance;
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertFalse;
26import static org.junit.Assert.assertNotEquals;
27import static org.junit.Assert.assertThat;
28import static org.junit.Assert.assertTrue;
29
30import android.graphics.Rect;
31import android.os.Parcel;
32import android.platform.test.annotations.Presubmit;
33import android.support.test.filters.SmallTest;
34import android.support.test.runner.AndroidJUnit4;
35import android.view.DisplayCutout.ParcelableWrapper;
36
37import org.junit.Test;
38import org.junit.runner.RunWith;
39
40import java.util.Arrays;
41
42@RunWith(AndroidJUnit4.class)
43@SmallTest
44@Presubmit
45public class DisplayCutoutTest {
46
47    /** This is not a consistent cutout. Useful for verifying insets in one go though. */
48    final DisplayCutout mCutoutNumbers = new DisplayCutout(
49            new Rect(1, 2, 3, 4),
50            Arrays.asList(new Rect(5, 6, 7, 8)));
51
52    final DisplayCutout mCutoutTop = createCutoutTop();
53
54    @Test
55    public void hasCutout() throws Exception {
56        assertTrue(NO_CUTOUT.isEmpty());
57        assertFalse(mCutoutTop.isEmpty());
58    }
59
60    @Test
61    public void getSafeInsets() throws Exception {
62        assertEquals(1, mCutoutNumbers.getSafeInsetLeft());
63        assertEquals(2, mCutoutNumbers.getSafeInsetTop());
64        assertEquals(3, mCutoutNumbers.getSafeInsetRight());
65        assertEquals(4, mCutoutNumbers.getSafeInsetBottom());
66
67        assertEquals(new Rect(1, 2, 3, 4), mCutoutNumbers.getSafeInsets());
68    }
69
70    @Test
71    public void getBoundingRect() throws Exception {
72        assertEquals(new Rect(50, 0, 75, 100), mCutoutTop.getBounds().getBounds());
73    }
74
75    @Test
76    public void testHashCode() throws Exception {
77        assertEquals(mCutoutTop.hashCode(), createCutoutTop().hashCode());
78        assertNotEquals(mCutoutTop.hashCode(), mCutoutNumbers.hashCode());
79    }
80
81    @Test
82    public void testEquals() throws Exception {
83        assertEquals(mCutoutTop, createCutoutTop());
84        assertNotEquals(mCutoutTop, mCutoutNumbers);
85    }
86
87    @Test
88    public void testToString() throws Exception {
89        assertFalse(mCutoutTop.toString().isEmpty());
90        assertFalse(mCutoutNumbers.toString().isEmpty());
91    }
92
93    @Test
94    public void inset_immutable() throws Exception {
95        DisplayCutout cutout = mCutoutTop.inset(1, 2, 3, 4);
96
97        assertEquals("original instance must not be mutated", createCutoutTop(), mCutoutTop);
98    }
99
100    @Test
101    public void inset_insets_withLeftCutout() throws Exception {
102        DisplayCutout cutout = createCutoutWithInsets(100, 0, 0, 0).inset(1, 2, 3, 4);
103
104        assertEquals(cutout.getSafeInsetLeft(), 99);
105        assertEquals(cutout.getSafeInsetTop(), 0);
106        assertEquals(cutout.getSafeInsetRight(), 0);
107        assertEquals(cutout.getSafeInsetBottom(), 0);
108    }
109
110    @Test
111    public void inset_insets_withTopCutout() throws Exception {
112        DisplayCutout cutout = mCutoutTop.inset(1, 2, 3, 4);
113
114        assertEquals(cutout.getSafeInsetLeft(), 0);
115        assertEquals(cutout.getSafeInsetTop(), 98);
116        assertEquals(cutout.getSafeInsetRight(), 0);
117        assertEquals(cutout.getSafeInsetBottom(), 0);
118    }
119
120    @Test
121    public void inset_insets_withRightCutout() throws Exception {
122        DisplayCutout cutout = createCutoutWithInsets(0, 0, 100, 0).inset(1, 2, 3, 4);
123
124        assertEquals(cutout.getSafeInsetLeft(), 0);
125        assertEquals(cutout.getSafeInsetTop(), 0);
126        assertEquals(cutout.getSafeInsetRight(), 97);
127        assertEquals(cutout.getSafeInsetBottom(), 0);
128    }
129
130    @Test
131    public void inset_insets_withBottomCutout() throws Exception {
132        DisplayCutout cutout = createCutoutWithInsets(0, 0, 0, 100).inset(1, 2, 3, 4);
133
134        assertEquals(cutout.getSafeInsetLeft(), 0);
135        assertEquals(cutout.getSafeInsetTop(), 0);
136        assertEquals(cutout.getSafeInsetRight(), 0);
137        assertEquals(cutout.getSafeInsetBottom(), 96);
138    }
139
140    @Test
141    public void inset_insets_consumeInset() throws Exception {
142        DisplayCutout cutout = mCutoutTop.inset(0, 1000, 0, 0);
143
144        assertEquals(cutout.getSafeInsetLeft(), 0);
145        assertEquals(cutout.getSafeInsetTop(), 0);
146        assertEquals(cutout.getSafeInsetRight(), 0);
147        assertEquals(cutout.getSafeInsetBottom(), 0);
148
149        assertTrue(cutout.isEmpty());
150    }
151
152    @Test
153    public void inset_bounds() throws Exception {
154        DisplayCutout cutout = mCutoutTop.inset(1, 2, 3, 4);
155
156        assertEquals(new Rect(49, -2, 74, 98), cutout.getBounds().getBounds());
157    }
158
159    @Test
160    public void fromBoundingPolygon() throws Exception {
161        assertEquals(
162                new Rect(50, 0, 75, 100),
163                DisplayCutout.fromBoundingRect(50, 0, 75, 100).getBounds().getBounds());
164    }
165
166    @Test
167    public void parcel_unparcel_regular() {
168        Parcel p = Parcel.obtain();
169
170        new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0);
171        int posAfterWrite = p.dataPosition();
172
173        p.setDataPosition(0);
174
175        assertEquals(mCutoutTop, ParcelableWrapper.CREATOR.createFromParcel(p).get());
176        assertEquals(posAfterWrite, p.dataPosition());
177    }
178
179    @Test
180    public void parcel_unparcel_withFrame() {
181        Parcel p = Parcel.obtain();
182
183        new ParcelableWrapper(mCutoutNumbers).writeToParcel(p, 0);
184        int posAfterWrite = p.dataPosition();
185
186        p.setDataPosition(0);
187
188        assertEquals(mCutoutNumbers, ParcelableWrapper.CREATOR.createFromParcel(p).get());
189        assertEquals(posAfterWrite, p.dataPosition());
190    }
191
192    @Test
193    public void fromSpec_caches() {
194        DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f);
195        assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), sameInstance(cached));
196    }
197
198    @Test
199    public void fromSpec_wontCacheIfSpecChanges() {
200        DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f);
201        assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
202    }
203
204    @Test
205    public void fromSpec_wontCacheIfScreenWidthChanges() {
206        DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f);
207        assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
208    }
209
210    @Test
211    public void fromSpec_wontCacheIfScreenHeightChanges() {
212        DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f);
213        assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
214    }
215
216    @Test
217    public void fromSpec_wontCacheIfDensityChanges() {
218        DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f);
219        assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
220    }
221
222    @Test
223    public void parcel_unparcel_nocutout() {
224        Parcel p = Parcel.obtain();
225
226        new ParcelableWrapper(NO_CUTOUT).writeToParcel(p, 0);
227        int posAfterWrite = p.dataPosition();
228
229        p.setDataPosition(0);
230
231        assertEquals(NO_CUTOUT, ParcelableWrapper.CREATOR.createFromParcel(p).get());
232        assertEquals(posAfterWrite, p.dataPosition());
233    }
234
235    @Test
236    public void parcel_unparcel_inplace() {
237        Parcel p = Parcel.obtain();
238
239        new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0);
240        int posAfterWrite = p.dataPosition();
241
242        p.setDataPosition(0);
243
244        ParcelableWrapper wrapper = new ParcelableWrapper();
245        wrapper.readFromParcel(p);
246
247        assertEquals(mCutoutTop, wrapper.get());
248        assertEquals(posAfterWrite, p.dataPosition());
249    }
250
251    @Test
252    public void wrapper_hashcode() throws Exception {
253        assertEquals(new ParcelableWrapper(mCutoutTop).hashCode(),
254                new ParcelableWrapper(createCutoutTop()).hashCode());
255        assertNotEquals(new ParcelableWrapper(mCutoutTop).hashCode(),
256                new ParcelableWrapper(mCutoutNumbers).hashCode());
257    }
258
259    @Test
260    public void wrapper_equals() throws Exception {
261        assertEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(createCutoutTop()));
262        assertNotEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(mCutoutNumbers));
263    }
264
265    private static DisplayCutout createCutoutTop() {
266        return createCutoutWithInsets(0, 100, 0, 0);
267    }
268
269    private static DisplayCutout createCutoutWithInsets(int left, int top, int right, int bottom) {
270        return new DisplayCutout(
271                new Rect(left, top, right, bottom),
272                Arrays.asList(new Rect(50, 0, 75, 100)));
273    }
274}
275