1 /*
2  * Copyright (C) 2010 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.app.stubs;
18 
19 import static org.junit.Assert.assertTrue;
20 
21 import android.app.Activity;
22 import android.content.pm.ActivityInfo;
23 import android.content.res.Resources;
24 import android.graphics.Rect;
25 
26 import java.util.concurrent.CountDownLatch;
27 import java.util.concurrent.TimeUnit;
28 import java.util.concurrent.atomic.AtomicReference;
29 
30 public class OrientationTestUtils {
31     /**
32      * Change the activity's orientation to something different and then switch back. This is used
33      * to trigger {@link Activity#onConfigurationChanged(android.content.res.Configuration)}.
34      *
35      * @param activity whose orientation will be changed and restored
36      */
toggleOrientation(Activity activity)37     public static void toggleOrientation(Activity activity) {
38         final int[] orientations = getOrientations(activity);
39         activity.setRequestedOrientation(orientations[1]);
40         activity.setRequestedOrientation(orientations[0]);
41     }
42 
43     /**
44      * Switches the device's orientation from landscape to portrait or portrait to landscape.
45      *
46      * @param activity whose orientation will be changed
47      * @return original orientation
48      */
switchOrientation(final Activity activity)49     public static void switchOrientation(final Activity activity) {
50         final int[] orientations = getOrientations(activity);
51         activity.setRequestedOrientation(orientations[1]);
52     }
53 
54     /**
55      * Returns window orientation and toggled orientation.
56      * @param activity context to get the window info
57      * @return The first element is original orientation and the second element is toggled
58      *     orientation.
59      */
getOrientations(final Activity activity)60     private static int[] getOrientations(final Activity activity) {
61         // Check the display dimension to get the current device orientation.
62         final Rect bounds = activity.getWindowManager().getCurrentWindowMetrics().getBounds();
63         final int originalOrientation = bounds.width() > bounds.height()
64                 ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
65                 : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
66         final int newOrientation = originalOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
67                 ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
68                 : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
69         return new int[] { originalOrientation, newOrientation };
70     }
71 
72     /** Checks whether the window dimension is close to square. */
isCloseToSquareBounds(final Activity activity)73     public static boolean isCloseToSquareBounds(final Activity activity) {
74         final Resources resources = activity.getResources();
75         final float closeToSquareMaxAspectRatio;
76         try {
77             closeToSquareMaxAspectRatio = resources.getFloat(resources.getIdentifier(
78                     "config_closeToSquareDisplayMaxAspectRatio", "dimen", "android"));
79         } catch (Resources.NotFoundException e) {
80             // Assume device is not close to square.
81             return false;
82         }
83         final Rect bounds = activity.getWindowManager().getCurrentWindowMetrics().getBounds();
84         final int w = bounds.width();
85         final int h = bounds.height();
86         final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
87         return aspectRatio <= closeToSquareMaxAspectRatio;
88     }
89 
90     /**
91      * Observer used in stub activities to wait for some event.
92      */
93     public static class Observer {
94         private static final int TIMEOUT_SEC = 3;
95         private final AtomicReference<CountDownLatch> mLatch = new AtomicReference();
96 
97         /**
98          * Starts observing event.
99          * The returned CountDownLatch will get activated when onObserved is invoked after this
100          * call. The method cannot be called multiple times unless reset() is invoked.
101          * @return CountDownLatch will get activated when onObserved is invoked after this call.
102          */
startObserving()103         public void startObserving() {
104             final CountDownLatch latch = new CountDownLatch(1);
105             assertTrue(mLatch.compareAndSet(null, latch));
106         }
107 
108         /**
109          * Waits until onObserved is invoked.
110          */
await()111         public void await() throws InterruptedException {
112             try {
113                 assertTrue(mLatch.get().await(TIMEOUT_SEC, TimeUnit.SECONDS));
114             } finally {
115                 mLatch.set(null);
116             }
117         }
118 
119         /**
120          * Notifies an event is observed.
121          * If this method is invoked after startObserving, the returned CountDownLatch will get
122          * activated. Otherwise it does nothing.
123          */
onObserved()124         public void onObserved() {
125             final CountDownLatch latch = mLatch.get();
126             if (latch != null) {
127                 latch.countDown();
128             }
129         }
130     }
131 }
132