Home | History | Annotate | Download | only in cts
      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 
     17 package android.app.cts;
     18 
     19 import com.android.appSdk25.Sdk25MaxAspectRatioActivity;
     20 
     21 import org.junit.After;
     22 import org.junit.Before;
     23 import org.junit.Ignore;
     24 import org.junit.Rule;
     25 import org.junit.Test;
     26 import org.junit.runner.RunWith;
     27 
     28 import android.app.Activity;
     29 import android.app.stubs.MaxAspectRatioActivity;
     30 import android.app.stubs.MaxAspectRatioResizeableActivity;
     31 import android.app.stubs.MaxAspectRatioUnsetActivity;
     32 import android.content.Context;
     33 import android.content.res.Configuration;
     34 import android.graphics.Point;
     35 import android.platform.test.annotations.Presubmit;
     36 import android.support.test.InstrumentationRegistry;
     37 import android.support.test.rule.ActivityTestRule;
     38 import android.support.test.runner.AndroidJUnit4;
     39 import android.util.DisplayMetrics;
     40 import android.view.Display;
     41 import android.view.WindowManager;
     42 
     43 import static android.content.Context.WINDOW_SERVICE;
     44 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
     45 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
     46 import static android.content.pm.PackageManager.FEATURE_WATCH;
     47 import static org.junit.Assert.fail;
     48 
     49 /**
     50  * Build: mmma -j32 cts/tests/app
     51  * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AspectRatioTests
     52  */
     53 @RunWith(AndroidJUnit4.class)
     54 public class AspectRatioTests {
     55     private static final String TAG = "AspectRatioTests";
     56 
     57     // The max. aspect ratio the test activities are using.
     58     private static final float MAX_ASPECT_RATIO = 1.0f;
     59 
     60     // Max supported aspect ratio for pre-O apps.
     61     private static final float MAX_PRE_O_ASPECT_RATIO = 1.86f;
     62 
     63     // The minimum supported device aspect ratio.
     64     private static final float MIN_DEVICE_ASPECT_RATIO = 1.333f;
     65 
     66     // The minimum supported device aspect ratio for watches.
     67     private static final float MIN_WATCH_DEVICE_ASPECT_RATIO = 1.0f;
     68 
     69     @Rule
     70     public ActivityTestRule<MaxAspectRatioActivity> mMaxAspectRatioActivity =
     71             new ActivityTestRule<>(MaxAspectRatioActivity.class,
     72                     false /* initialTouchMode */, false /* launchActivity */);
     73 
     74     @Rule
     75     public ActivityTestRule<MaxAspectRatioResizeableActivity> mMaxAspectRatioResizeableActivity =
     76             new ActivityTestRule<>(MaxAspectRatioResizeableActivity.class,
     77                     false /* initialTouchMode */, false /* launchActivity */);
     78 
     79     @Rule
     80     public ActivityTestRule<MaxAspectRatioUnsetActivity> mMaxAspectRatioUnsetActivity =
     81             new ActivityTestRule<>(MaxAspectRatioUnsetActivity.class,
     82                     false /* initialTouchMode */, false /* launchActivity */);
     83 
     84     // TODO: Can't use this to start an activity in a different process...sigh.
     85     @Rule
     86     public ActivityTestRule<Sdk25MaxAspectRatioActivity> mSdk25MaxAspectRatioActivity =
     87             new ActivityTestRule<>(Sdk25MaxAspectRatioActivity.class, "com.android.appSdk25",
     88                     268435456, false /* initialTouchMode */, false /* launchActivity */);
     89 
     90     private interface AssertAspectRatioCallback {
     91         void assertAspectRatio(float actual);
     92     }
     93 
     94     @Before
     95     public void setUp() throws Exception {
     96 
     97     }
     98 
     99     @After
    100     public void tearDown() throws Exception {
    101         finishActivity(mMaxAspectRatioActivity);
    102         finishActivity(mMaxAspectRatioResizeableActivity);
    103         finishActivity(mSdk25MaxAspectRatioActivity);
    104         finishActivity(mMaxAspectRatioUnsetActivity);
    105     }
    106 
    107     @Test
    108     @Presubmit
    109     public void testDeviceAspectRatio() throws Exception {
    110         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
    111         final WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
    112         final Display display = wm.getDefaultDisplay();
    113         final DisplayMetrics metrics = new DisplayMetrics();
    114         display.getRealMetrics(metrics);
    115 
    116         float longSide = Math.max(metrics.widthPixels, metrics.heightPixels);
    117         float shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
    118         float deviceAspectRatio = longSide / shortSide;
    119         float expectedMinAspectRatio = context.getPackageManager().hasSystemFeature(FEATURE_WATCH)
    120                 ? MIN_WATCH_DEVICE_ASPECT_RATIO : MIN_DEVICE_ASPECT_RATIO;
    121 
    122         if (deviceAspectRatio < expectedMinAspectRatio) {
    123             fail("deviceAspectRatio=" + deviceAspectRatio
    124                     + " is less than expectedMinAspectRatio=" + expectedMinAspectRatio);
    125         }
    126     }
    127 
    128     @Test
    129     @Presubmit
    130     public void testMaxAspectRatio() throws Exception {
    131         runTest(launchActivity(mMaxAspectRatioActivity),
    132                 actual -> {
    133                     if (MAX_ASPECT_RATIO >= actual) return;
    134                     fail("actual=" + actual + " is greater than expected=" + MAX_ASPECT_RATIO);
    135                 });
    136     }
    137 
    138     @Test
    139     // TODO: Currently 10% flaky so not part of pre-submit for now
    140     public void testMaxAspectRatioResizeableActivity() throws Exception {
    141         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
    142         final float expected = getAspectRatio(context);
    143 
    144         // Since this activity is resizeable, its aspect ratio shouldn't be less than the device's
    145         runTest(launchActivity(mMaxAspectRatioResizeableActivity),
    146                 actual -> {
    147                     if (aspectRatioEqual(expected, actual) || expected < actual) return;
    148                     fail("actual=" + actual + " is less than expected=" + expected);
    149                 });
    150     }
    151 
    152     @Test
    153     @Presubmit
    154     public void testMaxAspectRatioUnsetActivity() throws Exception {
    155         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
    156         final float expected = getAspectRatio(context);
    157 
    158         // Since this activity didn't set an aspect ratio, its aspect ratio shouldn't be less than
    159         // the device's
    160         runTest(launchActivity(mMaxAspectRatioUnsetActivity),
    161                 actual -> {
    162                     if (aspectRatioEqual(expected, actual) || expected < actual) return;
    163                     fail("actual=" + actual + " is less than expected=" + expected);
    164                 });
    165     }
    166 
    167     @Test
    168     // TODO(b/35810513): Can't use rule to start an activity in a different process. Need a
    169     // different way to make this test happen...host side? Sigh...
    170     @Ignore
    171     public void testMaxAspectRatioPreOActivity() throws Exception {
    172         runTest(launchActivity(mSdk25MaxAspectRatioActivity),
    173                 actual -> {
    174                     if (MAX_PRE_O_ASPECT_RATIO >= actual) return;
    175                     fail("actual=" + actual + " is greater than expected=" + MAX_PRE_O_ASPECT_RATIO);
    176                 });
    177     }
    178 
    179     private void runTest(Activity activity, AssertAspectRatioCallback callback) {
    180         callback.assertAspectRatio(getAspectRatio(activity));
    181 
    182         // TODO(b/35810513): All this rotation stuff doesn't really work yet. Need to make sure
    183         // context is updated correctly here. Also, what does it mean to be holding a reference to
    184         // this activity if changing the orientation will cause a relaunch?
    185 //        activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
    186 //        waitForIdle();
    187 //        callback.assertAspectRatio(getAspectRatio(activity));
    188 //
    189 //        activity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
    190 //        waitForIdle();
    191 //        callback.assertAspectRatio(getAspectRatio(activity));
    192     }
    193 
    194     private float getAspectRatio(Context context) {
    195         final Display display =
    196                 ((WindowManager) context.getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
    197         final Point size = new Point();
    198         display.getSize(size);
    199         final float longSide = Math.max(size.x, size.y);
    200         final float shortSide = Math.min(size.x, size.y);
    201         return longSide / shortSide;
    202     }
    203 
    204     private Activity launchActivity(ActivityTestRule activityRule) {
    205         final Activity activity = activityRule.launchActivity(null);
    206         waitForIdle();
    207         return activity;
    208     }
    209 
    210     private void finishActivity(ActivityTestRule activityRule) {
    211         final Activity activity = activityRule.getActivity();
    212         if (activity != null) {
    213             activity.finish();
    214         }
    215     }
    216 
    217     private void waitForIdle() {
    218         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    219     }
    220 
    221     private static boolean aspectRatioEqual(float a, float b) {
    222         // Aspect ratios are considered equal if they ware within to significant digits.
    223         float diff = Math.abs(a - b);
    224         return diff < 0.01f;
    225     }
    226 }
    227