• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package android.app.cts;
17 
18 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
19 
20 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertNotEquals;
24 import static org.junit.Assert.assertNotNull;
25 
26 import android.app.ActivityOptions;
27 import android.app.UiAutomation;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.content.res.Configuration;
32 
33 import androidx.test.ext.junit.rules.ActivityScenarioRule;
34 import androidx.test.filters.SmallTest;
35 
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.rules.ExternalResource;
39 import org.junit.rules.RuleChain;
40 import org.junit.rules.TestRule;
41 
42 import java.util.concurrent.Future;
43 import java.util.function.Function;
44 
45 /**
46  * Tests the {@link android.view.ContextThemeWrapper#applyOverrideConfiguration(Configuration)}
47  * method and how it affects the Activity's resources and lifecycle callbacks.
48  */
49 public class ApplyOverrideConfigurationTest {
50     private static ActivityScenarioRule<ApplyOverrideConfigurationActivity>
getActivityScenarioRule()51             getActivityScenarioRule() {
52         final ActivityOptions options = ActivityOptions.makeBasic();
53         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
54 
55         final Intent intent = new Intent(
56                 getInstrumentation().getTargetContext(), ApplyOverrideConfigurationActivity.class);
57         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
58         return new ActivityScenarioRule<>(intent, options.toBundle());
59     }
60 
61     private final ActivityScenarioRule<ApplyOverrideConfigurationActivity> mActivityScenarioRule =
62             getActivityScenarioRule();
63 
64     @Rule
65     public TestRule mRule = RuleChain.outerRule(new ExternalResource() {
66         @Override
67         protected void before() {
68             getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
69         }
70 
71         @Override
72         protected void after() {
73             getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
74         }
75     }).around(mActivityScenarioRule);
76 
onActivity(Function<ApplyOverrideConfigurationActivity, R> func)77     private <R> R onActivity(Function<ApplyOverrideConfigurationActivity, R> func) {
78         Object[] result = new Object[1];
79         mActivityScenarioRule.getScenario().onActivity(activity -> {
80             result[0] = func.apply(activity);
81         });
82         return (R) result[0];
83     }
84 
85     @SmallTest
86     @Test
testOverriddenConfigurationIsPassedIntoCallback()87     public void testOverriddenConfigurationIsPassedIntoCallback() throws Exception {
88         // This test instruments display rotation; disable it on devices that do not
89         // support auto-rotation.
90 
91         if (!onActivity(ApplyOverrideConfigurationTest::isRotationSupported)) {
92             return;
93         }
94 
95         final Configuration originalConfig =
96                 onActivity(activity -> activity.getResources().getConfiguration());
97         assertEquals(ApplyOverrideConfigurationActivity.OVERRIDE_SMALLEST_WIDTH,
98                 originalConfig.smallestScreenWidthDp);
99 
100         final Future<Configuration> callbackConfigurationFuture = onActivity(
101                 ApplyOverrideConfigurationActivity::watchForSingleOnConfigurationChangedCallback);
102         getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_90);
103         final Configuration callbackConfig = callbackConfigurationFuture.get();
104         assertNotNull(callbackConfig);
105 
106         final Configuration newConfig = onActivity(
107                 activity -> activity.getResources().getConfiguration());
108         assertNotEquals(originalConfig.orientation, newConfig.orientation);
109         assertEquals(ApplyOverrideConfigurationActivity.OVERRIDE_SMALLEST_WIDTH,
110                 newConfig.smallestScreenWidthDp);
111         assertEquals(newConfig, callbackConfig);
112     }
113 
114     /**
115      * Gets whether the device supports rotation. In general such a
116      * device has both portrait and landscape features.
117      *
118      * @param context Context for accessing system resources.
119      * @return Whether the device supports rotation.
120      */
isRotationSupported(Context context)121     public static boolean isRotationSupported(Context context) {
122         PackageManager pm = context.getPackageManager();
123         return pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
124                 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
125                 && !isVrHeadset(context);
126     }
127 
128     /**
129      * Gets whether the DUT is a vr headset.
130      *
131      * @param context Context for accessing system resources.
132      * @return Whether the device is a vr headset.
133      */
isVrHeadset(Context context)134     public static boolean isVrHeadset(Context context) {
135         return (context.getResources().getConfiguration().uiMode
136                 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
137     }
138 }
139