1/*
2 * Copyright (C) 2016 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 org.junit.Before;
20import org.junit.Ignore;
21import org.junit.Test;
22import org.junit.runner.RunWith;
23
24import android.graphics.Rect;
25import android.support.test.filters.SmallTest;
26import android.support.test.runner.AndroidJUnit4;
27import android.util.DisplayMetrics;
28import android.util.Log;
29import android.view.Display;
30
31import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
32import static com.android.server.wm.WindowManagerService.dipToPixel;
33import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
34import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
35import static org.junit.Assert.assertEquals;
36import static org.junit.Assert.assertTrue;
37
38/**
39 * Tests for the {@link TaskPositioner} class.
40 *
41 * runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
42 */
43@SmallTest
44@RunWith(AndroidJUnit4.class)
45public class TaskPositionerTests extends WindowTestsBase {
46
47    private final boolean DEBUGGING = false;
48    private final String TAG = "TaskPositionerTest";
49
50    private final static int MOUSE_DELTA_X = 5;
51    private final static int MOUSE_DELTA_Y = 5;
52
53    private int mMinVisibleWidth;
54    private int mMinVisibleHeight;
55    private TaskPositioner mPositioner;
56
57    @Before
58    public void setUp() throws Exception {
59        super.setUp();
60        final Display display = mDisplayContent.getDisplay();
61        final DisplayMetrics dm = new DisplayMetrics();
62        display.getMetrics(dm);
63
64        // This should be the same calculation as the TaskPositioner uses.
65        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
66        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
67
68        mPositioner = new TaskPositioner(sWm);
69        mPositioner.register(display);
70    }
71
72    /**
73     * This tests that free resizing will allow to change the orientation as well
74     * as does some basic tests (e.g. dragging in Y only will keep X stable).
75     */
76    @Test
77    @Ignore
78    public void testBasicFreeWindowResizing() throws Exception {
79        final Rect r = new Rect(100, 220, 700, 520);
80        final int midY = (r.top + r.bottom) / 2;
81
82        // Start a drag resize starting upper left.
83        mPositioner.startDrag(true /*resizing*/,
84                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
85        assertBoundsEquals(r, mPositioner.getWindowDragBounds());
86
87        // Drag to a good landscape size.
88        mPositioner.resizeDrag(0.0f, 0.0f);
89        assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
90                mPositioner.getWindowDragBounds());
91
92        // Drag to a good portrait size.
93        mPositioner.resizeDrag(400.0f, 0.0f);
94        assertBoundsEquals(new Rect(400 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
95                mPositioner.getWindowDragBounds());
96
97        // Drag to a too small size for the width.
98        mPositioner.resizeDrag(2000.0f, r.top);
99        assertBoundsEquals(
100                new Rect(r.right - mMinVisibleWidth, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
101                mPositioner.getWindowDragBounds());
102
103        // Drag to a too small size for the height.
104        mPositioner.resizeDrag(r.left, 2000.0f);
105        assertBoundsEquals(
106                new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
107                mPositioner.getWindowDragBounds());
108
109        // Start a drag resize left and see that only the left coord changes..
110        mPositioner.startDrag(true /*resizing*/,
111                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
112
113        // Drag to the left.
114        mPositioner.resizeDrag(0.0f, midY);
115        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
116                mPositioner.getWindowDragBounds());
117
118        // Drag to the right.
119        mPositioner.resizeDrag(200.0f, midY);
120        assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
121                mPositioner.getWindowDragBounds());
122
123        // Drag to the top
124        mPositioner.resizeDrag(r.left, 0.0f);
125        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
126                mPositioner.getWindowDragBounds());
127
128        // Drag to the bottom
129        mPositioner.resizeDrag(r.left, 1000.0f);
130        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
131                mPositioner.getWindowDragBounds());
132    }
133
134    /**
135     * This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
136     */
137    @Test
138    @Ignore
139    public void testFreeWindowResizingTestAllEdges() throws Exception {
140        final Rect r = new Rect(100, 220, 700, 520);
141        final int midX = (r.left + r.right) / 2;
142        final int midY = (r.top + r.bottom) / 2;
143
144        // Drag upper left.
145        mPositioner.startDrag(true /*resizing*/,
146                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
147        mPositioner.resizeDrag(0.0f, 0.0f);
148        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
149        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
150        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
151        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
152
153        // Drag upper.
154        mPositioner.startDrag(true /*resizing*/,
155                false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
156        mPositioner.resizeDrag(0.0f, 0.0f);
157        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
158        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
159        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
160        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
161
162        // Drag upper right.
163        mPositioner.startDrag(true /*resizing*/,
164                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
165        mPositioner.resizeDrag(r.right + 100, 0.0f);
166        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
167        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
168        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
169        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
170
171        // Drag right.
172        mPositioner.startDrag(true /*resizing*/,
173                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY, r);
174        mPositioner.resizeDrag(r.right + 100, 0.0f);
175        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
176        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
177        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
178        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
179
180        // Drag bottom right.
181        mPositioner.startDrag(true /*resizing*/,
182                false /*preserveOrientation*/,
183                r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
184        mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
185        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
186        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
187        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
188        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
189
190        // Drag bottom.
191        mPositioner.startDrag(true /*resizing*/,
192                false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y, r);
193        mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
194        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
195        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
196        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
197        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
198
199        // Drag bottom left.
200        mPositioner.startDrag(true /*resizing*/,
201                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
202        mPositioner.resizeDrag(0.0f, r.bottom + 100);
203        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
204        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
205        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
206        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
207
208        // Drag left.
209        mPositioner.startDrag(true /*resizing*/,
210                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX, r);
211        mPositioner.resizeDrag(0.0f, r.bottom + 100);
212        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
213        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
214        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
215        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
216    }
217
218    /**
219     * This tests that a constrained landscape window will keep the aspect and do the
220     * right things upon resizing when dragged from the top left corner.
221     */
222    @Test
223    @Ignore
224    public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
225        final Rect r = new Rect(100, 220, 700, 520);
226
227        mPositioner.startDrag(true /*resizing*/,
228                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
229        assertBoundsEquals(r, mPositioner.getWindowDragBounds());
230
231        // Drag to a good landscape size.
232        mPositioner.resizeDrag(0.0f, 0.0f);
233        assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
234                mPositioner.getWindowDragBounds());
235
236        // Drag to a good portrait size.
237        mPositioner.resizeDrag(400.0f, 0.0f);
238        int width = Math.round((float) (r.bottom - MOUSE_DELTA_Y) * MIN_ASPECT);
239        assertBoundsEquals(new Rect(r.right - width, MOUSE_DELTA_Y, r.right, r.bottom),
240                mPositioner.getWindowDragBounds());
241
242        // Drag to a too small size for the width.
243        mPositioner.resizeDrag(2000.0f, r.top);
244        final int w = mMinVisibleWidth;
245        final int h = Math.round(w / MIN_ASPECT);
246        assertBoundsEquals(new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
247                mPositioner.getWindowDragBounds());
248
249        // Drag to a too small size for the height.
250        mPositioner.resizeDrag(r.left, 2000.0f);
251        assertBoundsEquals(
252                new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
253                mPositioner.getWindowDragBounds());
254    }
255
256    /**
257     * This tests that a constrained landscape window will keep the aspect and do the
258     * right things upon resizing when dragged from the left corner.
259     */
260    @Test
261    @Ignore
262    public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
263        final Rect r = new Rect(100, 220, 700, 520);
264        final int midY = (r.top + r.bottom) / 2;
265
266        mPositioner.startDrag(true /*resizing*/,
267                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
268
269        // Drag to the left.
270        mPositioner.resizeDrag(0.0f, midY);
271        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
272                mPositioner.getWindowDragBounds());
273
274        // Drag to the right.
275        mPositioner.resizeDrag(200.0f, midY);
276        assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
277                mPositioner.getWindowDragBounds());
278
279        // Drag all the way to the right and see the height also shrinking.
280        mPositioner.resizeDrag(2000.0f, midY);
281        final int w = mMinVisibleWidth;
282        final int h = Math.round((float)w / MIN_ASPECT);
283        assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
284                mPositioner.getWindowDragBounds());
285
286        // Drag to the top.
287        mPositioner.resizeDrag(r.left, 0.0f);
288        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
289                mPositioner.getWindowDragBounds());
290
291        // Drag to the bottom.
292        mPositioner.resizeDrag(r.left, 1000.0f);
293        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
294                mPositioner.getWindowDragBounds());
295    }
296
297    /**
298     * This tests that a constrained landscape window will keep the aspect and do the
299     * right things upon resizing when dragged from the top corner.
300     */
301    @Test
302    @Ignore
303    public void testLandscapePreservedWindowResizingDragTop() throws Exception {
304        final Rect r = new Rect(100, 220, 700, 520);
305        final int midX = (r.left + r.right) / 2;
306
307        mPositioner.startDrag(true /*resizing*/,
308                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
309
310        // Drag to the left (no change).
311        mPositioner.resizeDrag(0.0f, r.top);
312        assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
313                mPositioner.getWindowDragBounds());
314
315        // Drag to the right (no change).
316        mPositioner.resizeDrag(2000.0f, r.top);
317        assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
318                mPositioner.getWindowDragBounds());
319
320        // Drag to the top.
321        mPositioner.resizeDrag(300.0f, 0.0f);
322        int h = r.bottom - MOUSE_DELTA_Y;
323        int w = Math.max(r.right - r.left, Math.round(h * MIN_ASPECT));
324        assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
325                mPositioner.getWindowDragBounds());
326
327        // Drag to the bottom.
328        mPositioner.resizeDrag(r.left, 1000.0f);
329        h = mMinVisibleHeight;
330        assertBoundsEquals(new Rect(r.left, r.bottom - h, r.right, r.bottom),
331                mPositioner.getWindowDragBounds());
332    }
333
334    /**
335     * This tests that a constrained portrait window will keep the aspect and do the
336     * right things upon resizing when dragged from the top left corner.
337     */
338    @Test
339    @Ignore
340    public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
341        final Rect r = new Rect(330, 100, 630, 600);
342
343        mPositioner.startDrag(true /*resizing*/,
344                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
345        assertBoundsEquals(r, mPositioner.getWindowDragBounds());
346
347        // Drag to a good landscape size.
348        mPositioner.resizeDrag(0.0f, 0.0f);
349        int height = Math.round((float) (r.right - MOUSE_DELTA_X) * MIN_ASPECT);
350        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.bottom - height, r.right, r.bottom),
351                mPositioner.getWindowDragBounds());
352
353        // Drag to a good portrait size.
354        mPositioner.resizeDrag(500.0f, 0.0f);
355        assertBoundsEquals(new Rect(500 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
356                mPositioner.getWindowDragBounds());
357
358        // Drag to a too small size for the height and the the width shrinking.
359        mPositioner.resizeDrag(r.left + MOUSE_DELTA_X, 2000.0f);
360        final int w = Math.max(mMinVisibleWidth, Math.round(mMinVisibleHeight / MIN_ASPECT));
361        final int h = Math.max(mMinVisibleHeight, Math.round(w * MIN_ASPECT));
362        assertBoundsEquals(
363                new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
364                mPositioner.getWindowDragBounds());
365    }
366
367    /**
368     * This tests that a constrained portrait window will keep the aspect and do the
369     * right things upon resizing when dragged from the left corner.
370     */
371    @Test
372    @Ignore
373    public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
374        final Rect r = new Rect(330, 100, 630, 600);
375        final int midY = (r.top + r.bottom) / 2;
376
377        mPositioner.startDrag(true /*resizing*/,
378                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
379
380        // Drag to the left.
381        mPositioner.resizeDrag(0.0f, midY);
382        int w = r.right - MOUSE_DELTA_X;
383        int h = Math.round(w * MIN_ASPECT);
384        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.top + h),
385                mPositioner.getWindowDragBounds());
386
387        // Drag to the right.
388        mPositioner.resizeDrag(450.0f, midY);
389        assertBoundsEquals(new Rect(450 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
390                mPositioner.getWindowDragBounds());
391
392        // Drag all the way to the right.
393        mPositioner.resizeDrag(2000.0f, midY);
394        w = mMinVisibleWidth;
395        h = Math.max(Math.round((float)w * MIN_ASPECT), r.height());
396        assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
397                mPositioner.getWindowDragBounds());
398
399        // Drag to the top.
400        mPositioner.resizeDrag(r.left, 0.0f);
401        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
402                mPositioner.getWindowDragBounds());
403
404        // Drag to the bottom.
405        mPositioner.resizeDrag(r.left, 1000.0f);
406        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
407                mPositioner.getWindowDragBounds());
408    }
409
410    /**
411     * This tests that a constrained portrait window will keep the aspect and do the
412     * right things upon resizing when dragged from the top corner.
413     */
414    @Test
415    @Ignore
416    public void testPortraitPreservedWindowResizingDragTop() throws Exception {
417        final Rect r = new Rect(330, 100, 630, 600);
418        final int midX = (r.left + r.right) / 2;
419
420        mPositioner.startDrag(true /*resizing*/,
421                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
422
423        // Drag to the left (no change).
424        mPositioner.resizeDrag(0.0f, r.top);
425        assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
426                mPositioner.getWindowDragBounds());
427
428        // Drag to the right (no change).
429        mPositioner.resizeDrag(2000.0f, r.top);
430        assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
431                mPositioner.getWindowDragBounds());
432
433        // Drag to the top.
434        mPositioner.resizeDrag(300.0f, 0.0f);
435        int h = r.bottom - MOUSE_DELTA_Y;
436        int w = Math.min(r.width(), Math.round(h / MIN_ASPECT));
437        assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
438                mPositioner.getWindowDragBounds());
439
440        // Drag to the bottom.
441        mPositioner.resizeDrag(r.left, 1000.0f);
442        h = Math.max(mMinVisibleHeight, Math.round(mMinVisibleWidth * MIN_ASPECT));
443        w = Math.round(h / MIN_ASPECT);
444        assertBoundsEquals(new Rect(r.left, r.bottom - h, r.left + w, r.bottom),
445                mPositioner.getWindowDragBounds());
446    }
447
448    private void assertBoundsEquals(Rect expected, Rect actual) {
449        if (DEBUGGING) {
450            if (!expected.equals(actual)) {
451                Log.e(TAG, "rect(" + actual.toString() + ") != isRect(" + actual.toString()
452                        + ") " + Log.getStackTraceString(new Throwable()));
453            }
454        }
455        assertEquals(expected.left, actual.left);
456        assertEquals(expected.right, actual.right);
457        assertEquals(expected.top, actual.top);
458        assertEquals(expected.bottom, actual.bottom);
459    }
460}
461