blob: fa6154efe13e88a817cebd8564da1744adf43243 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.app.cts;
import android.app.stubs.MetaDataMaxAspectRatioActivity;
import com.android.appSdk25.Sdk25MaxAspectRatioActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.app.Activity;
import android.app.stubs.MaxAspectRatioActivity;
import android.app.stubs.MaxAspectRatioResizeableActivity;
import android.app.stubs.MaxAspectRatioUnsetActivity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import com.android.compatibility.common.util.PollingCheck;
import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static org.junit.Assert.fail;
/**
* Build: mmma -j32 cts/tests/app
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AspectRatioTests
*/
@RunWith(AndroidJUnit4.class)
public class AspectRatioTests {
private static final String TAG = "AspectRatioTests";
// The max. aspect ratio the test activities are using.
private static final float MAX_ASPECT_RATIO = 1.0f;
// Max supported aspect ratio for pre-O apps.
private static final float MAX_PRE_O_ASPECT_RATIO = 1.86f;
// The minimum supported device aspect ratio.
private static final float MIN_DEVICE_ASPECT_RATIO = 1.333f;
// The minimum supported device aspect ratio for watches.
private static final float MIN_WATCH_DEVICE_ASPECT_RATIO = 1.0f;
@Rule
public ActivityTestRule<MaxAspectRatioActivity> mMaxAspectRatioActivity =
new ActivityTestRule<>(MaxAspectRatioActivity.class,
false /* initialTouchMode */, false /* launchActivity */);
@Rule
public ActivityTestRule<MaxAspectRatioResizeableActivity> mMaxAspectRatioResizeableActivity =
new ActivityTestRule<>(MaxAspectRatioResizeableActivity.class,
false /* initialTouchMode */, false /* launchActivity */);
@Rule
public ActivityTestRule<MetaDataMaxAspectRatioActivity> mMetaDataMaxAspectRatioActivity =
new ActivityTestRule<>(MetaDataMaxAspectRatioActivity.class,
false /* initialTouchMode */, false /* launchActivity */);
@Rule
public ActivityTestRule<MaxAspectRatioUnsetActivity> mMaxAspectRatioUnsetActivity =
new ActivityTestRule<>(MaxAspectRatioUnsetActivity.class,
false /* initialTouchMode */, false /* launchActivity */);
// TODO: Can't use this to start an activity in a different process...sigh.
@Rule
public ActivityTestRule<Sdk25MaxAspectRatioActivity> mSdk25MaxAspectRatioActivity =
new ActivityTestRule<>(Sdk25MaxAspectRatioActivity.class, "com.android.appSdk25",
268435456, false /* initialTouchMode */, false /* launchActivity */);
private interface AssertAspectRatioCallback {
void assertAspectRatio(float actual);
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
finishActivity(mMaxAspectRatioActivity);
finishActivity(mMaxAspectRatioResizeableActivity);
finishActivity(mSdk25MaxAspectRatioActivity);
finishActivity(mMaxAspectRatioUnsetActivity);
finishActivity(mMetaDataMaxAspectRatioActivity);
}
@Test
@Presubmit
public void testDeviceAspectRatio() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
final DisplayMetrics metrics = new DisplayMetrics();
display.getRealMetrics(metrics);
float longSide = Math.max(metrics.widthPixels, metrics.heightPixels);
float shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
float deviceAspectRatio = longSide / shortSide;
float expectedMinAspectRatio = context.getPackageManager().hasSystemFeature(FEATURE_WATCH)
? MIN_WATCH_DEVICE_ASPECT_RATIO : MIN_DEVICE_ASPECT_RATIO;
if (deviceAspectRatio < expectedMinAspectRatio) {
fail("deviceAspectRatio=" + deviceAspectRatio
+ " is less than expectedMinAspectRatio=" + expectedMinAspectRatio);
}
}
@Test
@Presubmit
public void testMaxAspectRatio() throws Exception {
runTest(launchActivity(mMaxAspectRatioActivity),
actual -> {
if (MAX_ASPECT_RATIO >= actual) return;
fail("actual=" + actual + " is greater than expected=" + MAX_ASPECT_RATIO);
});
}
@Test
@Presubmit
public void testMetaDataMaxAspectRatio() throws Exception {
runTest(launchActivity(mMetaDataMaxAspectRatioActivity),
actual -> {
if (MAX_ASPECT_RATIO >= actual) return;
fail("actual=" + actual + " is greater than expected=" + MAX_ASPECT_RATIO);
});
}
@Test
// TODO: Currently 10% flaky so not part of pre-submit for now
public void testMaxAspectRatioResizeableActivity() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final float expected = getAspectRatio(context);
final Activity testActivity = launchActivity(mMaxAspectRatioResizeableActivity);
PollingCheck.waitFor(testActivity::hasWindowFocus);
Display testDisplay = testActivity.findViewById(android.R.id.content).getDisplay();
// TODO(b/69982434): Fix DisplayManager NPE when getting display from Instrumentation
// context, then can use DisplayManager to get the aspect ratio of the correct display.
if (testDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) {
return;
}
// Since this activity is resizeable, its aspect ratio shouldn't be less than the device's
runTest(testActivity,
actual -> {
if (aspectRatioEqual(expected, actual) || expected < actual) return;
fail("actual=" + actual + " is less than expected=" + expected);
});
}
@Test
@Presubmit
public void testMaxAspectRatioUnsetActivity() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
final float expected = getAspectRatio(context);
// Since this activity didn't set an aspect ratio, its aspect ratio shouldn't be less than
// the device's
runTest(launchActivity(mMaxAspectRatioUnsetActivity),
actual -> {
if (aspectRatioEqual(expected, actual) || expected < actual) return;
fail("actual=" + actual + " is less than expected=" + expected);
});
}
@Test
// TODO(b/35810513): Can't use rule to start an activity in a different process. Need a
// different way to make this test happen...host side? Sigh...
@Ignore
public void testMaxAspectRatioPreOActivity() throws Exception {
runTest(launchActivity(mSdk25MaxAspectRatioActivity),
actual -> {
if (MAX_PRE_O_ASPECT_RATIO >= actual) return;
fail("actual=" + actual + " is greater than expected=" + MAX_PRE_O_ASPECT_RATIO);
});
}
private void runTest(Activity activity, AssertAspectRatioCallback callback) {
callback.assertAspectRatio(getAspectRatio(activity));
// TODO(b/35810513): All this rotation stuff doesn't really work yet. Need to make sure
// context is updated correctly here. Also, what does it mean to be holding a reference to
// this activity if changing the orientation will cause a relaunch?
// activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
// waitForIdle();
// callback.assertAspectRatio(getAspectRatio(activity));
//
// activity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
// waitForIdle();
// callback.assertAspectRatio(getAspectRatio(activity));
}
private float getAspectRatio(Context context) {
final Display display =
((WindowManager) context.getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
final float longSide = Math.max(size.x, size.y);
final float shortSide = Math.min(size.x, size.y);
return longSide / shortSide;
}
private Activity launchActivity(ActivityTestRule activityRule) {
final Activity activity = activityRule.launchActivity(null);
waitForIdle();
return activity;
}
private void finishActivity(ActivityTestRule activityRule) {
final Activity activity = activityRule.getActivity();
if (activity != null) {
activity.finish();
}
}
private void waitForIdle() {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
private static boolean aspectRatioEqual(float a, float b) {
// Aspect ratios are considered equal if they ware within to significant digits.
float diff = Math.abs(a - b);
return diff < 0.01f;
}
}