• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.view.cts;
18 
19 import android.view.ContextThemeWrapper;
20 import android.view.cts.R;
21 
22 import android.app.Instrumentation;
23 import android.app.Presentation;
24 import android.content.Context;
25 import android.content.res.Configuration;
26 import android.content.res.TypedArray;
27 import android.cts.util.PollingCheck;
28 import android.graphics.Color;
29 import android.graphics.PixelFormat;
30 import android.graphics.drawable.ColorDrawable;
31 import android.graphics.drawable.Drawable;
32 import android.hardware.display.DisplayManager;
33 import android.hardware.display.VirtualDisplay;
34 import android.media.AudioManager;
35 import android.net.Uri;
36 import android.os.Bundle;
37 import android.os.Handler;
38 import android.os.SystemClock;
39 import android.test.ActivityInstrumentationTestCase2;
40 import android.test.UiThreadTest;
41 import android.util.DisplayMetrics;
42 import android.util.Log;
43 import android.view.ActionMode;
44 import android.view.Display;
45 import android.view.Gravity;
46 import android.view.InputDevice;
47 import android.view.InputQueue;
48 import android.view.KeyEvent;
49 import android.view.KeyboardShortcutGroup;
50 import android.view.LayoutInflater;
51 import android.view.Menu;
52 import android.view.MenuItem;
53 import android.view.MotionEvent;
54 import android.view.SearchEvent;
55 import android.view.Surface;
56 import android.view.SurfaceHolder;
57 import android.view.SurfaceView;
58 import android.view.View;
59 import android.view.ViewGroup;
60 import android.view.Window;
61 import android.view.WindowManager;
62 import android.view.accessibility.AccessibilityEvent;
63 import android.widget.Button;
64 import android.widget.TextView;
65 
66 import java.util.List;
67 import java.util.concurrent.Semaphore;
68 import java.util.concurrent.TimeUnit;
69 
70 public class WindowTest extends ActivityInstrumentationTestCase2<WindowCtsActivity> {
71     static final String TAG = "WindowTest";
72     private Window mWindow;
73     private Context mContext;
74     private Instrumentation mInstrumentation;
75     private WindowCtsActivity mActivity;
76     private SurfaceView surfaceView;
77 
78     private static final int VIEWGROUP_LAYOUT_HEIGHT = 100;
79     private static final int VIEWGROUP_LAYOUT_WIDTH = 200;
80 
81     // for testing setLocalFocus
82     private ProjectedPresentation mPresentation;
83     private VirtualDisplay mVirtualDisplay;
84 
WindowTest()85     public WindowTest() {
86         super("android.view.cts", WindowCtsActivity.class);
87     }
88 
89     @Override
setUp()90     protected void setUp() throws Exception {
91         super.setUp();
92         mInstrumentation = getInstrumentation();
93         mContext = mInstrumentation.getContext();
94         mActivity = getActivity();
95         mWindow = mActivity.getWindow();
96     }
97 
98     @Override
tearDown()99     protected void tearDown() throws Exception {
100         if (mActivity != null) {
101             mActivity.setFlagFalse();
102         }
103         super.tearDown();
104     }
105 
106     @UiThreadTest
testConstructor()107     public void testConstructor() throws Exception {
108         mWindow = new MockWindow(mContext);
109         assertSame(mContext, mWindow.getContext());
110     }
111 
112     /**
113      * Test flags related methods:
114      * 1. addFlags: add the given flag to WindowManager.LayoutParams.flags, if add more than one
115      *    in sequence, flags will be set to formerFlag | latterFlag.
116      * 2. setFlags: _1. set the flags of the window.
117      *              _2. test invocation of Window.Callback#onWindowAttributesChanged.
118      * 3. clearFlags: clear the flag bits as specified in flags.
119      */
testOpFlags()120    public void testOpFlags() throws Exception {
121         mWindow = new MockWindow(mContext);
122         final WindowManager.LayoutParams attrs = mWindow.getAttributes();
123         assertEquals(0, attrs.flags);
124 
125         mWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
126         assertEquals(WindowManager.LayoutParams.FLAG_FULLSCREEN, attrs.flags);
127 
128         mWindow.addFlags(WindowManager.LayoutParams.FLAG_DITHER);
129         assertEquals(WindowManager.LayoutParams.FLAG_FULLSCREEN
130                 | WindowManager.LayoutParams.FLAG_DITHER, attrs.flags);
131 
132         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
133         assertEquals(WindowManager.LayoutParams.FLAG_DITHER, attrs.flags);
134         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DITHER);
135         assertEquals(0, attrs.flags);
136 
137         MockWindowCallback callback = new MockWindowCallback();
138         mWindow.setCallback(callback);
139         assertFalse(callback.isOnWindowAttributesChangedCalled());
140         // mask == flag, no bit of flag need to be modified.
141         mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
142                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
143         assertEquals(WindowManager.LayoutParams.FLAG_FULLSCREEN, attrs.flags);
144 
145         // Test if the callback method is called by system
146         assertTrue(callback.isOnWindowAttributesChangedCalled());
147         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
148         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DITHER);
149     }
150 
testFindViewById()151     public void testFindViewById() throws Exception {
152         TextView v = (TextView) mWindow.findViewById(R.id.listview_window);
153         assertNotNull(v);
154         assertEquals(R.id.listview_window, v.getId());
155     }
156 
157     /**
158      * getAttributes: Retrieve the current window attributes associated with this panel.
159      *    Return is 1.the existing window attributes object.
160      *              2.a freshly created one if there is none.
161      * setAttributes: Specify custom window attributes.
162      *    Here we just set some parameters to test if it can set, and the window is just
163      *    available in this method. But it's not proper to setAttributes arbitrarily.
164      * setCallback: Set the Callback interface for this window. In Window.java,
165      *    there is just one method, onWindowAttributesChanged, used.
166      * getCallback: Return the current Callback interface for this window.
167      */
testAccessAttributes()168     public void testAccessAttributes() throws Exception {
169         mWindow = new MockWindow(mContext);
170 
171         // default attributes
172         WindowManager.LayoutParams attr = mWindow.getAttributes();
173         assertEquals(WindowManager.LayoutParams.MATCH_PARENT, attr.width);
174         assertEquals(WindowManager.LayoutParams.MATCH_PARENT, attr.height);
175         assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION, attr.type);
176         assertEquals(PixelFormat.OPAQUE, attr.format);
177 
178         int width = 200;
179         int height = 300;
180         WindowManager.LayoutParams param = new WindowManager.LayoutParams(width, height,
181                 WindowManager.LayoutParams.TYPE_BASE_APPLICATION,
182                 WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.RGBA_8888);
183         MockWindowCallback callback = new MockWindowCallback();
184         mWindow.setCallback(callback);
185         assertSame(callback, mWindow.getCallback());
186         assertFalse(callback.isOnWindowAttributesChangedCalled());
187         mWindow.setAttributes(param);
188         attr = mWindow.getAttributes();
189         assertEquals(width, attr.width);
190         assertEquals(height, attr.height);
191         assertEquals(WindowManager.LayoutParams.TYPE_BASE_APPLICATION, attr.type);
192         assertEquals(PixelFormat.RGBA_8888, attr.format);
193         assertEquals(WindowManager.LayoutParams.FLAG_DITHER, attr.flags);
194         assertTrue(callback.isOnWindowAttributesChangedCalled());
195     }
196 
197     /**
198      * If not set container, the DecorWindow operates as a top-level window, the mHasChildren of
199      * container is false;
200      * Otherwise, it will display itself meanwhile container's mHasChildren is true.
201      */
testAccessContainer()202     public void testAccessContainer() throws Exception {
203         mWindow = new MockWindow(mContext);
204         assertNull(mWindow.getContainer());
205         assertFalse(mWindow.hasChildren());
206 
207         MockWindow container = new MockWindow(mContext);
208         mWindow.setContainer(container);
209         assertSame(container, mWindow.getContainer());
210         assertTrue(container.hasChildren());
211     }
212 
213     /**
214      * addContentView: add an additional content view to the screen.
215      *    1.Added after any existing ones in the screen.
216      *    2.Existing views are NOT removed.
217      * getLayoutInflater: Quick access to the {@link LayoutInflater} instance that this Window
218      *    retrieved from its Context.
219      */
testAddContentView()220     public void testAddContentView() throws Throwable {
221         final ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(VIEWGROUP_LAYOUT_WIDTH,
222                 VIEWGROUP_LAYOUT_HEIGHT);
223         // The LayoutInflater instance will be inflated to a view and used by
224         // addContentView,
225         // id of this view should be same with inflated id.
226         final LayoutInflater inflater = mActivity.getLayoutInflater();
227         runTestOnUiThread(new Runnable() {
228             public void run() {
229                 TextView addedView = (TextView) mWindow.findViewById(R.id.listview_addwindow);
230                 assertNull(addedView);
231                 mWindow.addContentView(inflater.inflate(R.layout.windowstub_addlayout, null), lp);
232                 TextView view = (TextView) mWindow.findViewById(R.id.listview_window);
233                 addedView = (TextView) mWindow.findViewById(R.id.listview_addwindow);
234                 assertNotNull(view);
235                 assertNotNull(addedView);
236                 assertEquals(R.id.listview_window, view.getId());
237                 assertEquals(R.id.listview_addwindow, addedView.getId());
238             }
239         });
240         mInstrumentation.waitForIdleSync();
241     }
242 
testCloseAllPanels()243     public void testCloseAllPanels() throws Throwable {
244     }
245 
246     /**
247      * getCurrentFocus: Return the view in this Window that currently has focus, or null if
248      *                  there are none.
249      * The test will be:
250      * 1. Set focus view to null, get current focus, it should be null
251      * 2. Set listview_window as focus view, get it and compare.
252      */
testGetCurrentFocus()253     public void testGetCurrentFocus() throws Throwable {
254         runTestOnUiThread(new Runnable() {
255             public void run() {
256                 TextView v = (TextView) mWindow.findViewById(R.id.listview_window);
257                 v.clearFocus();
258                 assertNull(mWindow.getCurrentFocus());
259 
260                 v.setFocusable(true);
261                 assertTrue(v.isFocusable());
262                 assertTrue(v.requestFocus());
263                 View focus = mWindow.getCurrentFocus();
264                 assertNotNull(focus);
265                 assertEquals(R.id.listview_window, focus.getId());
266             }
267         });
268         mInstrumentation.waitForIdleSync();
269     }
270 
271     /**
272      * 1. getDecorView() retrieves the top-level window decor view, which contains the standard
273      *    window frame/decorations and the client's content inside of that, we should check the
274      *    primary components of this view which have no relationship concrete realization of Window.
275      *    Therefore we should check if the size of this view equals to the screen size and the
276      *    ontext is same as Window's context.
277      * 2. Return null if decor view is not created, else the same with detDecorView.
278      */
testDecorView()279     public void testDecorView() throws Exception {
280         mInstrumentation.waitForIdleSync();
281         View decor = mWindow.getDecorView();
282         assertNotNull(decor);
283         checkDecorView(decor);
284 
285         decor = mWindow.peekDecorView();
286         if (decor != null) {
287             checkDecorView(decor);
288         }
289     }
290 
checkDecorView(View decor)291     private void checkDecorView(View decor) {
292         DisplayMetrics dm = new DisplayMetrics();
293         mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
294         int screenWidth = dm.widthPixels;
295         int screenHeight = dm.heightPixels;
296         assertTrue(decor.getWidth() >= screenWidth);
297         assertTrue(decor.getHeight() >= screenHeight);
298         assertTrue(decor.getContext() instanceof ContextThemeWrapper);
299     }
300 
301     /**
302      * setVolumeControlStream: Suggests an audio stream whose volume should be changed by
303      *    the hardware volume controls.
304      * getVolumeControlStream: Gets the suggested audio stream whose volume should be changed by
305      *    the harwdare volume controls.
306      */
testAccessVolumeControlStream()307     public void testAccessVolumeControlStream() throws Exception {
308         // Default value is AudioManager.USE_DEFAULT_STREAM_TYPE, see javadoc of
309         // {@link Activity#setVolumeControlStream}.
310         assertEquals(AudioManager.USE_DEFAULT_STREAM_TYPE, mWindow.getVolumeControlStream());
311         mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
312         assertEquals(AudioManager.STREAM_MUSIC, mWindow.getVolumeControlStream());
313     }
314 
315     /**
316      * setWindowManager: Set the window manager for use by this Window.
317      * getWindowManager: Return the window manager allowing this Window to display its own
318      *    windows.
319      */
testAccessWindowManager()320     public void testAccessWindowManager() throws Exception {
321         mWindow = new MockWindow(getActivity());
322         WindowManager expected = (WindowManager) getActivity().getSystemService(
323                 Context.WINDOW_SERVICE);
324         assertNull(mWindow.getWindowManager());
325         mWindow.setWindowManager(expected, null, getName());
326         // No way to compare the expected and actual directly, they are
327         // different object
328         assertNotNull(mWindow.getWindowManager());
329     }
330 
331     /**
332      * Return the {@link android.R.styleable#Window} attributes from this
333      * window's theme. It's invisible.
334      */
testGetWindowStyle()335     public void testGetWindowStyle() throws Exception {
336         mWindow = new MockWindow(mContext);
337         final TypedArray windowStyle = mWindow.getWindowStyle();
338         // the windowStyle is obtained from
339         // com.android.internal.R.styleable.Window whose details
340         // are invisible for user.
341         assertNotNull(windowStyle);
342     }
343 
testIsActive()344     public void testIsActive() throws Exception {
345         MockWindow window = new MockWindow(mContext);
346         assertFalse(window.isActive());
347 
348         window.makeActive();
349         assertTrue(window.isActive());
350         assertTrue(window.mIsOnActiveCalled);
351     }
352 
353     /**
354      * isFloating: Return whether this window is being displayed with a floating style
355      * (based on the {@link android.R.attr#windowIsFloating} attribute in the style/theme).
356      */
testIsFloating()357     public void testIsFloating() throws Exception {
358         // Default system theme defined by themes.xml, the windowIsFloating is set false.
359         assertFalse(mWindow.isFloating());
360     }
361 
testPerformMethods()362     public void testPerformMethods() throws Exception {
363     }
364 
testKeepHierarchyState()365     public void testKeepHierarchyState() throws Exception {
366     }
367 
368     /**
369      * Change the background of this window to a custom Drawable.
370      * Setting the background to null will make the window be opaque(No way to get the window
371      *  attribute of PixelFormat to check if the window is opaque). To make the window
372      * transparent, you can use an empty drawable(eg. ColorDrawable with the color 0).
373      */
testSetBackgroundDrawable()374     public void testSetBackgroundDrawable() throws Throwable {
375         // DecorView holds the background
376         View decor = mWindow.getDecorView();
377         if (!mWindow.hasFeature(Window.FEATURE_SWIPE_TO_DISMISS)) {
378             assertEquals(PixelFormat.OPAQUE, decor.getBackground().getOpacity());
379         }
380         runTestOnUiThread(new Runnable() {
381             public void run() {
382                 // setBackgroundDrawableResource(int resId) has the same
383                 // functionality with
384                 // setBackgroundDrawable(Drawable drawable), just different in
385                 // parameter.
386                 mWindow.setBackgroundDrawableResource(R.drawable.faces);
387             }
388         });
389         mInstrumentation.waitForIdleSync();
390 
391         runTestOnUiThread(new Runnable() {
392             public void run() {
393                 ColorDrawable drawable = new ColorDrawable(0);
394                 mWindow.setBackgroundDrawable(drawable);
395             }
396         });
397         mInstrumentation.waitForIdleSync();
398         decor = mWindow.getDecorView();
399         // Color 0 with one alpha bit
400         assertEquals(PixelFormat.TRANSPARENT, decor.getBackground().getOpacity());
401 
402         runTestOnUiThread(new Runnable() {
403             public void run() {
404                 mWindow.setBackgroundDrawable(null);
405             }
406         });
407         mInstrumentation.waitForIdleSync();
408         decor = mWindow.getDecorView();
409         assertNull(decor.getBackground());
410     }
411 
testSetChild()412     public void testSetChild() throws Exception {
413     }
414 
415     /**
416      * setContentView(int): set the screen content from a layout resource.
417      * setContentView(View): set the screen content to an explicit view.
418      * setContentView(View, LayoutParams): Set the screen content to an explicit view.
419      *
420      * Note that calling this function "locks in" various characteristics
421      * of the window that can not, from this point forward, be changed: the
422      * features that have been requested with {@link #requestFeature(int)},
423      * and certain window flags as described in {@link #setFlags(int, int)}.
424      *   This functionality point is hard to test:
425      *   1. can't get the features requested because the getter is protected final.
426      *   2. certain window flags are not clear to concrete one.
427      */
testSetContentView()428     public void testSetContentView() throws Throwable {
429         final ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(VIEWGROUP_LAYOUT_WIDTH,
430                 VIEWGROUP_LAYOUT_HEIGHT);
431         final LayoutInflater inflate = mActivity.getLayoutInflater();
432 
433         runTestOnUiThread(new Runnable() {
434             public void run() {
435                 TextView view;
436                 View setView;
437                 // Test setContentView(int layoutResID)
438                 mWindow.setContentView(R.layout.windowstub_layout);
439                 view = (TextView) mWindow.findViewById(R.id.listview_window);
440                 assertNotNull(view);
441                 assertEquals(R.id.listview_window, view.getId());
442 
443                 // Test setContentView(View view)
444                 setView = inflate.inflate(R.layout.windowstub_addlayout, null);
445                 mWindow.setContentView(setView);
446                 view = (TextView) mWindow.findViewById(R.id.listview_addwindow);
447                 assertNotNull(view);
448                 assertEquals(R.id.listview_addwindow, view.getId());
449 
450                 // Test setContentView(View view, ViewGroup.LayoutParams params)
451                 setView = inflate.inflate(R.layout.windowstub_layout, null);
452                 mWindow.setContentView(setView, lp);
453                 assertEquals(VIEWGROUP_LAYOUT_WIDTH, setView.getLayoutParams().width);
454                 assertEquals(VIEWGROUP_LAYOUT_HEIGHT, setView.getLayoutParams().height);
455                 view = (TextView) mWindow.findViewById(R.id.listview_window);
456                 assertNotNull(view);
457                 assertEquals(R.id.listview_window, view.getId());
458             }
459         });
460         mInstrumentation.waitForIdleSync();
461     }
462 
463     /**
464      * setFeatureDrawable: Set an explicit Drawable value for feature of this window.
465      * setFeatureDrawableAlpha: Set a custom alpha value for the given drawale feature,
466      *    controlling how much the background is visible through it.
467      * setFeatureDrawableResource: Set the value for a drawable feature of this window, from
468      *    a resource identifier.
469      * setFeatureDrawableUri: Set the value for a drawable feature of this window, from a URI.
470      * setFeatureInt: Set the integer value for a feature.  The range of the value depends on
471      *    the feature being set.  For FEATURE_PROGRESSS, it should go from 0 to
472      *    10000. At 10000 the progress is complete and the indicator hidden
473      *
474      * the set views exist, and no getter way to check.
475      */
testSetFeature()476     public void testSetFeature() throws Throwable {
477     }
478 
testSetTitle()479     public void testSetTitle() throws Throwable {
480         final String title = "Android Window Test";
481         runTestOnUiThread(new Runnable() {
482             public void run() {
483                 mWindow.setTitle(title);
484                 mWindow.setTitleColor(Color.BLUE);
485             }
486         });
487         mInstrumentation.waitForIdleSync();
488         // No way to get title and title color
489     }
490 
491     /**
492      * These 3 methods: Used by custom windows, such as Dialog, to pass the key press event
493      * further down the view hierarchy. Application developers should not need to implement or
494      * call this.
495      */
testSuperDispatchEvent()496     public void testSuperDispatchEvent() throws Exception {
497     }
498 
499     /**
500      * takeKeyEvents: Request that key events come to this activity. Use this if your activity
501      * has no views with focus, but the activity still wants a chance to process key events.
502      */
testTakeKeyEvents()503     public void testTakeKeyEvents() throws Throwable {
504         runTestOnUiThread(new Runnable() {
505             public void run() {
506                 View v = mWindow.findViewById(R.id.listview_window);
507                 v.clearFocus();
508                 assertNull(mWindow.getCurrentFocus());
509                 mWindow.takeKeyEvents(false);
510             }
511         });
512         mInstrumentation.waitForIdleSync();
513         // sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
514         // assertFalse(mActivity.isOnKeyDownCalled());
515     }
516 
517     /**
518      * onConfigurationChanged: Should be called when the configuration is changed.
519      */
testOnConfigurationChanged()520     public void testOnConfigurationChanged() throws Exception {
521     }
522 
523     /**
524      * requestFeature: Enable extended screen features.
525      */
testRequestFeature()526     public void testRequestFeature() throws Exception {
527     }
528 
529     /**
530      * setDefaultWindowFormat: Set the format of window, as per the PixelFormat types. This
531      *    is the format that will be used unless the client specifies in explicit format with
532      *    setFormat().
533      * setFormat: Set the format of window, as per the PixelFormat types.
534      *            param format: The new window format (see PixelFormat).  Use
535      *                          PixelFormat.UNKNOWN to allow the Window to select
536      *                          the format.
537      */
testSetDefaultWindowFormat()538     public void testSetDefaultWindowFormat() throws Exception {
539         MockWindowCallback callback;
540         MockWindow window = new MockWindow(mContext);
541 
542         // mHaveWindowFormat will be true after set PixelFormat.OPAQUE and
543         // setDefaultWindowFormat is invalid
544         window.setFormat(PixelFormat.OPAQUE);
545         callback = new MockWindowCallback();
546         window.setCallback(callback);
547         assertFalse(callback.isOnWindowAttributesChangedCalled());
548         window.setDefaultWindowFormat(PixelFormat.JPEG);
549         assertEquals(PixelFormat.OPAQUE, window.getAttributes().format);
550         assertFalse(callback.isOnWindowAttributesChangedCalled());
551 
552         // mHaveWindowFormat will be false after set PixelFormat.UNKNOWN and
553         // setDefaultWindowFormat is valid
554         window.setFormat(PixelFormat.UNKNOWN);
555         callback = new MockWindowCallback();
556         window.setCallback(callback);
557         assertFalse(callback.isOnWindowAttributesChangedCalled());
558         window.setDefaultWindowFormat(PixelFormat.JPEG);
559         assertEquals(PixelFormat.JPEG, window.getAttributes().format);
560         assertTrue(callback.isOnWindowAttributesChangedCalled());
561     }
562 
563     /**
564      * Set the gravity of the window
565      */
testSetGravity()566     public void testSetGravity() throws Exception {
567         mWindow = new MockWindow(mContext);
568         WindowManager.LayoutParams attrs = mWindow.getAttributes();
569         assertEquals(0, attrs.gravity);
570 
571         MockWindowCallback callback = new MockWindowCallback();
572         mWindow.setCallback(callback);
573         assertFalse(callback.isOnWindowAttributesChangedCalled());
574         mWindow.setGravity(Gravity.TOP);
575         attrs = mWindow.getAttributes();
576         assertEquals(Gravity.TOP, attrs.gravity);
577         assertTrue(callback.isOnWindowAttributesChangedCalled());
578     }
579 
580     /**
581      * Set the width and height layout parameters of the window.
582      *    1.The default for both of these is MATCH_PARENT;
583      *    2.You can change them to WRAP_CONTENT to make a window that is not full-screen.
584      */
testSetLayout()585     public void testSetLayout() throws Exception {
586         mWindow = new MockWindow(mContext);
587         WindowManager.LayoutParams attrs = mWindow.getAttributes();
588         assertEquals(WindowManager.LayoutParams.MATCH_PARENT, attrs.width);
589         assertEquals(WindowManager.LayoutParams.MATCH_PARENT, attrs.height);
590 
591         MockWindowCallback callback = new MockWindowCallback();
592         mWindow.setCallback(callback);
593         assertFalse(callback.isOnWindowAttributesChangedCalled());
594         mWindow.setLayout(WindowManager.LayoutParams.WRAP_CONTENT,
595                 WindowManager.LayoutParams.WRAP_CONTENT);
596         attrs = mWindow.getAttributes();
597         assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, attrs.width);
598         assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, attrs.height);
599         assertTrue(callback.isOnWindowAttributesChangedCalled());
600     }
601 
602     /**
603      * Set the type of the window, as per the WindowManager.LayoutParams types.
604      */
testSetType()605     public void testSetType() throws Exception {
606         mWindow = new MockWindow(mContext);
607         WindowManager.LayoutParams attrs = mWindow.getAttributes();
608         assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION, attrs.type);
609 
610         MockWindowCallback callback = new MockWindowCallback();
611         mWindow.setCallback(callback);
612         assertFalse(callback.isOnWindowAttributesChangedCalled());
613         mWindow.setType(WindowManager.LayoutParams.TYPE_BASE_APPLICATION);
614         attrs = mWindow.getAttributes();
615         assertEquals(WindowManager.LayoutParams.TYPE_BASE_APPLICATION, mWindow.getAttributes().type);
616         assertTrue(callback.isOnWindowAttributesChangedCalled());
617     }
618 
619     /**
620      * Specify an explicit soft input mode to use for the window, as per
621      * WindowManager.LayoutParams#softInputMode.
622      *    1.Providing "unspecified" here will NOT override the input mode the window.
623      *    2.Providing "unspecified" here will override the input mode the window.
624      */
testSetSoftInputMode()625     public void testSetSoftInputMode() throws Exception {
626         mWindow = new MockWindow(mContext);
627         assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED,
628                 mWindow.getAttributes().softInputMode);
629         mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
630         assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
631                 mWindow.getAttributes().softInputMode);
632         mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED);
633         assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
634                 mWindow.getAttributes().softInputMode);
635     }
636 
637     /**
638      * Specify custom animations to use for the window, as per
639      * WindowManager.LayoutParams#windowAnimations.
640      *    1.Providing 0 here will NOT override the animations the window(But here we can't check
641      *    it because the getter is in WindowManagerService and is private)
642      *    2.Providing 0 here will override the animations the window.
643      */
testSetWindowAnimations()644     public void testSetWindowAnimations() throws Exception {
645         mWindow = new MockWindow(mContext);
646 
647         MockWindowCallback callback = new MockWindowCallback();
648         mWindow.setCallback(callback);
649         assertFalse(callback.isOnWindowAttributesChangedCalled());
650         mWindow.setWindowAnimations(R.anim.alpha);
651         WindowManager.LayoutParams attrs = mWindow.getAttributes();
652         assertEquals(R.anim.alpha, attrs.windowAnimations);
653         assertTrue(callback.isOnWindowAttributesChangedCalled());
654     }
655 
testFinalMethod()656     public void testFinalMethod() throws Exception {
657         // No way to test protected final method
658     }
659 
660     /**
661      * Test setLocalFocus together with injectInputEvent.
662      */
testSetLocalFocus()663     public void testSetLocalFocus() throws Throwable {
664         runTestOnUiThread(new Runnable() {
665             public void run() {
666                 surfaceView = new SurfaceView(mContext);
667             }
668         });
669         mInstrumentation.waitForIdleSync();
670 
671         final Semaphore waitingSemaphore = new Semaphore(0);
672         surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
673             @Override
674             public void surfaceCreated(SurfaceHolder holder) {
675             }
676 
677             @Override
678             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
679                 destroyPresentation();
680                 createPresentation(holder.getSurface(), width, height);
681                 waitingSemaphore.release();
682             }
683 
684             @Override
685             public void surfaceDestroyed(SurfaceHolder holder) {
686                 destroyPresentation();
687             }
688           });
689         runTestOnUiThread(new Runnable() {
690             public void run() {
691                 mWindow.setContentView(surfaceView);
692             }
693         });
694         mInstrumentation.waitForIdleSync();
695         assertTrue(waitingSemaphore.tryAcquire(5, TimeUnit.SECONDS));
696         assertNotNull(mVirtualDisplay);
697         assertNotNull(mPresentation);
698         new PollingCheck() {
699             @Override
700             protected boolean check() {
701                 return (mPresentation.button1 != null) && (mPresentation.button2 != null) &&
702                         (mPresentation.button3 != null) && mPresentation.ready;
703             }
704         }.run();
705         assertTrue(mPresentation.button1.isFocusable() && mPresentation.button2.isFocusable() &&
706                 mPresentation.button3.isFocusable());
707         // currently it is only for debugging
708         View.OnFocusChangeListener listener = new View.OnFocusChangeListener() {
709             @Override
710             public void onFocusChange(View v, boolean hasFocus) {
711                 Log.d(TAG, "view " + v + " focus " + hasFocus);
712             }
713         };
714 
715         // check key event focus
716         mPresentation.button1.setOnFocusChangeListener(listener);
717         mPresentation.button2.setOnFocusChangeListener(listener);
718         mPresentation.button3.setOnFocusChangeListener(listener);
719         final Window presentationWindow = mPresentation.getWindow();
720         presentationWindow.setLocalFocus(true, false);
721         new PollingCheck() {
722             @Override
723             protected boolean check() {
724                 return mPresentation.button1.hasWindowFocus();
725             }
726         }.run();
727         checkPresentationButtonFocus(true, false, false);
728         assertFalse(mPresentation.button1.isInTouchMode());
729         injectKeyEvent(presentationWindow, KeyEvent.KEYCODE_TAB);
730         checkPresentationButtonFocus(false, true, false);
731         injectKeyEvent(presentationWindow, KeyEvent.KEYCODE_TAB);
732         checkPresentationButtonFocus(false, false, true);
733 
734         // check touch input injection
735         presentationWindow.setLocalFocus(true, true);
736         new PollingCheck() {
737             @Override
738             protected boolean check() {
739                 return mPresentation.button1.isInTouchMode();
740             }
741         }.run();
742         View.OnClickListener clickListener = new View.OnClickListener() {
743             @Override
744             public void onClick(View v) {
745                 Log.d(TAG, "onClick " + v);
746                 if (v == mPresentation.button1) {
747                     waitingSemaphore.release();
748                 }
749             }
750         };
751         mPresentation.button1.setOnClickListener(clickListener);
752         mPresentation.button2.setOnClickListener(clickListener);
753         mPresentation.button3.setOnClickListener(clickListener);
754         injectTouchEvent(presentationWindow, mPresentation.button1.getX() +
755                 mPresentation.button1.getWidth() / 2,
756                 mPresentation.button1.getY() + mPresentation.button1.getHeight() / 2);
757         assertTrue(waitingSemaphore.tryAcquire(5, TimeUnit.SECONDS));
758 
759         destroyPresentation();
760     }
761 
checkPresentationButtonFocus(final boolean button1Focused, final boolean button2Focused, final boolean button3Focused)762     private void checkPresentationButtonFocus(final boolean button1Focused,
763             final boolean button2Focused, final boolean button3Focused) {
764         new PollingCheck() {
765             @Override
766             protected boolean check() {
767                 return (mPresentation.button1.isFocused() == button1Focused) &&
768                         (mPresentation.button2.isFocused() == button2Focused) &&
769                         (mPresentation.button3.isFocused() == button3Focused);
770             }
771         }.run();
772     }
773 
injectKeyEvent(Window window, int keyCode)774     private void injectKeyEvent(Window window, int keyCode) {
775         KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
776         window.injectInputEvent(downEvent);
777         KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
778         window.injectInputEvent(upEvent);
779     }
780 
injectTouchEvent(Window window, float x, float y)781     private void injectTouchEvent(Window window, float x, float y) {
782         Log.d(TAG, "injectTouchEvent " + x + "," + y);
783         long downTime = SystemClock.uptimeMillis();
784         MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
785                 x, y, 0);
786         downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
787         window.injectInputEvent(downEvent);
788         long upTime = SystemClock.uptimeMillis();
789         MotionEvent upEvent = MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP,
790                 x, y, 0);
791         upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
792         window.injectInputEvent(upEvent);
793     }
794 
createPresentation(final Surface surface, final int width, final int height)795     private void createPresentation(final Surface surface, final int width,
796             final int height) {
797         Context context = getInstrumentation().getTargetContext();
798         DisplayManager displayManager =
799                 (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
800         mVirtualDisplay = displayManager.createVirtualDisplay("localFocusTest",
801                 width, height, 300, surface, 0);
802         mPresentation = new ProjectedPresentation(
803                 context, mVirtualDisplay.getDisplay());
804         mPresentation.show();
805     }
806 
destroyPresentation()807     private void destroyPresentation() {
808         if (mPresentation != null) {
809             mPresentation.dismiss();
810         }
811         if (mVirtualDisplay != null) {
812             mVirtualDisplay.release();
813         }
814     }
815 
816     private class ProjectedPresentation extends Presentation {
817         public Button button1 = null;
818         public Button button2 = null;
819         public Button button3 = null;
820         public volatile boolean ready = false;
821 
ProjectedPresentation(Context outerContext, Display display)822         public ProjectedPresentation(Context outerContext, Display display) {
823             super(outerContext, display);
824             getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
825             getWindow().addFlags(WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE);
826         }
827 
828         @Override
onCreate(Bundle savedInstanceState)829         protected void onCreate(Bundle savedInstanceState) {
830             super.onCreate(savedInstanceState);
831             setContentView(R.layout.windowstub_presentation);
832             button1 = (Button) findViewById(R.id.presentation_button1);
833             button2 = (Button) findViewById(R.id.presentation_button2);
834             button3 = (Button) findViewById(R.id.presentation_button3);
835         }
836 
837         @Override
show()838         public void show() {
839             super.show();
840             new Handler().post(new Runnable() {
841 
842                 @Override
843                 public void run() {
844                     ready = true;
845                 }
846             });
847         }
848     }
849 
850     public class MockWindow extends Window {
851         public boolean mIsOnConfigurationChangedCalled = false;
852         public boolean mIsOnActiveCalled = false;
853 
MockWindow(Context context)854         public MockWindow(Context context) {
855             super(context);
856         }
857 
isFloating()858         public boolean isFloating() {
859             return false;
860         }
861 
setContentView(int layoutResID)862         public void setContentView(int layoutResID) {
863         }
864 
setContentView(View view)865         public void setContentView(View view) {
866         }
867 
setContentView(View view, ViewGroup.LayoutParams params)868         public void setContentView(View view, ViewGroup.LayoutParams params) {
869         }
870 
addContentView(View view, ViewGroup.LayoutParams params)871         public void addContentView(View view, ViewGroup.LayoutParams params) {
872         }
873 
clearContentView()874         public void clearContentView() {
875         }
876 
getCurrentFocus()877         public View getCurrentFocus() {
878             return null;
879         }
880 
getLayoutInflater()881         public LayoutInflater getLayoutInflater() {
882             return null;
883         }
884 
setTitle(CharSequence title)885         public void setTitle(CharSequence title) {
886         }
887 
setTitleColor(int textColor)888         public void setTitleColor(int textColor) {
889         }
890 
openPanel(int featureId, KeyEvent event)891         public void openPanel(int featureId, KeyEvent event) {
892         }
893 
closePanel(int featureId)894         public void closePanel(int featureId) {
895         }
896 
togglePanel(int featureId, KeyEvent event)897         public void togglePanel(int featureId, KeyEvent event) {
898         }
899 
invalidatePanelMenu(int featureId)900         public void invalidatePanelMenu(int featureId) {
901         }
902 
performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags)903         public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
904             return true;
905         }
906 
performPanelIdentifierAction(int featureId, int id, int flags)907         public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
908             return true;
909         }
910 
closeAllPanels()911         public void closeAllPanels() {
912         }
913 
performContextMenuIdentifierAction(int id, int flags)914         public boolean performContextMenuIdentifierAction(int id, int flags) {
915             return true;
916         }
917 
onConfigurationChanged(Configuration newConfig)918         public void onConfigurationChanged(Configuration newConfig) {
919             mIsOnConfigurationChangedCalled = true;
920         }
921 
setBackgroundDrawable(Drawable drawable)922         public void setBackgroundDrawable(Drawable drawable) {
923         }
924 
setFeatureDrawableResource(int featureId, int resId)925         public void setFeatureDrawableResource(int featureId, int resId) {
926         }
927 
setFeatureDrawableUri(int featureId, Uri uri)928         public void setFeatureDrawableUri(int featureId, Uri uri) {
929         }
930 
setFeatureDrawable(int featureId, Drawable drawable)931         public void setFeatureDrawable(int featureId, Drawable drawable) {
932         }
933 
setFeatureDrawableAlpha(int featureId, int alpha)934         public void setFeatureDrawableAlpha(int featureId, int alpha) {
935         }
936 
setFeatureInt(int featureId, int value)937         public void setFeatureInt(int featureId, int value) {
938         }
939 
takeKeyEvents(boolean get)940         public void takeKeyEvents(boolean get) {
941         }
942 
superDispatchKeyEvent(KeyEvent event)943         public boolean superDispatchKeyEvent(KeyEvent event) {
944             return true;
945         }
946 
superDispatchKeyShortcutEvent(KeyEvent event)947         public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
948             return false;
949         }
950 
superDispatchTouchEvent(MotionEvent event)951         public boolean superDispatchTouchEvent(MotionEvent event) {
952             return true;
953         }
954 
superDispatchTrackballEvent(MotionEvent event)955         public boolean superDispatchTrackballEvent(MotionEvent event) {
956             return true;
957         }
958 
superDispatchGenericMotionEvent(MotionEvent event)959         public boolean superDispatchGenericMotionEvent(MotionEvent event) {
960             return true;
961         }
962 
getDecorView()963         public View getDecorView() {
964             return null;
965         }
966 
alwaysReadCloseOnTouchAttr()967         public void alwaysReadCloseOnTouchAttr() {
968         }
969 
peekDecorView()970         public View peekDecorView() {
971             return null;
972         }
973 
saveHierarchyState()974         public Bundle saveHierarchyState() {
975             return null;
976         }
977 
restoreHierarchyState(Bundle savedInstanceState)978         public void restoreHierarchyState(Bundle savedInstanceState) {
979         }
980 
onActive()981         protected void onActive() {
982             mIsOnActiveCalled = true;
983         }
984 
setChildDrawable(int featureId, Drawable drawable)985         public void setChildDrawable(int featureId, Drawable drawable) {
986 
987         }
988 
setChildInt(int featureId, int value)989         public void setChildInt(int featureId, int value) {
990         }
991 
isShortcutKey(int keyCode, KeyEvent event)992         public boolean isShortcutKey(int keyCode, KeyEvent event) {
993             return false;
994         }
995 
setVolumeControlStream(int streamType)996         public void setVolumeControlStream(int streamType) {
997         }
998 
getVolumeControlStream()999         public int getVolumeControlStream() {
1000             return 0;
1001         }
1002 
setDefaultWindowFormatFake(int format)1003         public void setDefaultWindowFormatFake(int format) {
1004             super.setDefaultWindowFormat(format);
1005         }
1006 
1007         @Override
setDefaultWindowFormat(int format)1008         public void setDefaultWindowFormat(int format) {
1009             super.setDefaultWindowFormat(format);
1010         }
1011 
1012         @Override
takeSurface(SurfaceHolder.Callback2 callback)1013         public void takeSurface(SurfaceHolder.Callback2 callback) {
1014         }
1015 
1016         @Override
takeInputQueue(InputQueue.Callback callback)1017         public void takeInputQueue(InputQueue.Callback callback) {
1018         }
1019 
1020         @Override
setStatusBarColor(int color)1021         public void setStatusBarColor(int color) {
1022         }
1023 
1024         @Override
getStatusBarColor()1025         public int getStatusBarColor() {
1026             return 0;
1027         }
1028 
1029         @Override
setNavigationBarColor(int color)1030         public void setNavigationBarColor(int color) {
1031         }
1032 
1033         @Override
setDecorCaptionShade(int decorCaptionShade)1034         public void setDecorCaptionShade(int decorCaptionShade) {
1035 
1036         }
1037 
1038         @Override
setResizingCaptionDrawable(Drawable drawable)1039         public void setResizingCaptionDrawable(Drawable drawable) {
1040 
1041         }
1042 
1043         @Override
getNavigationBarColor()1044         public int getNavigationBarColor() {
1045             return 0;
1046         }
1047 
1048         @Override
onMultiWindowModeChanged()1049         public void onMultiWindowModeChanged() {
1050         }
1051 
1052         @Override
reportActivityRelaunched()1053         public void reportActivityRelaunched() {
1054         }
1055     }
1056 
1057     private class MockWindowCallback implements Window.Callback {
1058         private boolean mIsOnWindowAttributesChangedCalled;
1059         private boolean mIsOnPanelClosedCalled;
1060 
dispatchKeyEvent(KeyEvent event)1061         public boolean dispatchKeyEvent(KeyEvent event) {
1062             return true;
1063         }
1064 
dispatchKeyShortcutEvent(KeyEvent event)1065         public boolean dispatchKeyShortcutEvent(KeyEvent event) {
1066             return false;
1067         }
1068 
dispatchTouchEvent(MotionEvent event)1069         public boolean dispatchTouchEvent(MotionEvent event) {
1070             return true;
1071         }
1072 
dispatchTrackballEvent(MotionEvent event)1073         public boolean dispatchTrackballEvent(MotionEvent event) {
1074             return true;
1075         }
1076 
dispatchGenericMotionEvent(MotionEvent event)1077         public boolean dispatchGenericMotionEvent(MotionEvent event) {
1078             return true;
1079         }
1080 
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)1081         public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1082             return true;
1083         }
1084 
onCreatePanelView(int featureId)1085         public View onCreatePanelView(int featureId) {
1086             return null;
1087         }
1088 
onCreatePanelMenu(int featureId, Menu menu)1089         public boolean onCreatePanelMenu(int featureId, Menu menu) {
1090             return false;
1091         }
1092 
onPreparePanel(int featureId, View view, Menu menu)1093         public boolean onPreparePanel(int featureId, View view, Menu menu) {
1094             return false;
1095         }
1096 
onMenuOpened(int featureId, Menu menu)1097         public boolean onMenuOpened(int featureId, Menu menu) {
1098             return false;
1099         }
1100 
onMenuItemSelected(int featureId, MenuItem item)1101         public boolean onMenuItemSelected(int featureId, MenuItem item) {
1102             return true;
1103         }
1104 
onWindowAttributesChanged(WindowManager.LayoutParams attrs)1105         public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {
1106             mIsOnWindowAttributesChangedCalled = true;
1107         }
1108 
isOnWindowAttributesChangedCalled()1109         public boolean isOnWindowAttributesChangedCalled() {
1110             return mIsOnWindowAttributesChangedCalled;
1111         }
1112 
onContentChanged()1113         public void onContentChanged() {
1114         }
1115 
onWindowFocusChanged(boolean hasFocus)1116         public void onWindowFocusChanged(boolean hasFocus) {
1117         }
1118 
onDetachedFromWindow()1119         public void onDetachedFromWindow() {
1120         }
1121 
onAttachedToWindow()1122         public void onAttachedToWindow() {
1123         }
1124 
onPanelClosed(int featureId, Menu menu)1125         public void onPanelClosed(int featureId, Menu menu) {
1126             mIsOnPanelClosedCalled = true;
1127         }
1128 
isOnPanelClosedCalled()1129         public boolean isOnPanelClosedCalled() {
1130             return mIsOnPanelClosedCalled;
1131         }
1132 
onSearchRequested(SearchEvent searchEvent)1133         public boolean onSearchRequested(SearchEvent searchEvent) {
1134             return onSearchRequested();
1135         }
1136 
onSearchRequested()1137         public boolean onSearchRequested() {
1138             return false;
1139         }
1140 
onWindowStartingActionMode(ActionMode.Callback callback)1141         public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
1142             return null;
1143         }
1144 
onWindowStartingActionMode( ActionMode.Callback callback, int type)1145         public ActionMode onWindowStartingActionMode(
1146                 ActionMode.Callback callback, int type) {
1147             return null;
1148         }
1149 
onActionModeStarted(ActionMode mode)1150         public void onActionModeStarted(ActionMode mode) {
1151         }
1152 
onActionModeFinished(ActionMode mode)1153         public void onActionModeFinished(ActionMode mode) {
1154         }
1155 
onWindowDismissed()1156         public void onWindowDismissed() {
1157         }
1158     }
1159 }
1160