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