1 /*
2  * Copyright (C) 2018 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 com.android.internal.policy;
18 
19 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
20 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
21 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
22 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
24 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
25 
26 import static org.hamcrest.Matchers.is;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertThat;
29 import static org.junit.Assert.assertTrue;
30 
31 import android.app.Instrumentation;
32 import android.content.Context;
33 import android.graphics.Color;
34 import android.graphics.drawable.ColorDrawable;
35 import android.graphics.drawable.Drawable;
36 import android.os.Binder;
37 import android.platform.test.annotations.Presubmit;
38 import android.platform.test.annotations.RequiresFlagsEnabled;
39 import android.platform.test.flag.junit.CheckFlagsRule;
40 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
41 import android.view.ActionMode;
42 import android.view.ContextThemeWrapper;
43 import android.view.ViewRootImpl;
44 import android.view.WindowManager;
45 
46 import androidx.test.InstrumentationRegistry;
47 import androidx.test.filters.SmallTest;
48 import androidx.test.runner.AndroidJUnit4;
49 
50 import com.android.frameworks.coretests.R;
51 
52 import org.junit.Before;
53 import org.junit.Rule;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 
57 /**
58  * Tests {@link PhoneWindow}'s {@link ActionMode} related methods.
59  */
60 @SmallTest
61 @Presubmit
62 @RunWith(AndroidJUnit4.class)
63 public final class PhoneWindowTest {
64 
65     private PhoneWindow mPhoneWindow;
66     private Context mContext;
67 
68     private static Instrumentation sInstrumentation =
69             InstrumentationRegistry.getInstrumentation();
70 
71     @Rule
72     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
73 
74     @Before
setUp()75     public void setUp() throws Exception {
76         mContext = InstrumentationRegistry.getContext();
77     }
78 
79     @Test
layoutInDisplayCutoutMode_unset()80     public void layoutInDisplayCutoutMode_unset() throws Exception {
81         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeUnset);
82         installDecor();
83 
84         assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
85                 is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
86     }
87 
88     @Test
layoutInDisplayCutoutMode_default()89     public void layoutInDisplayCutoutMode_default() throws Exception {
90         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeDefault);
91         installDecor();
92 
93         assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
94                 is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
95     }
96 
97     @Test
layoutInDisplayCutoutMode_shortEdges()98     public void layoutInDisplayCutoutMode_shortEdges() throws Exception {
99         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeShortEdges);
100         installDecor();
101 
102         assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
103                 is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES));
104     }
105 
106     @Test
layoutInDisplayCutoutMode_never()107     public void layoutInDisplayCutoutMode_never() throws Exception {
108         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeNever);
109         installDecor();
110 
111         assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
112                 is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER));
113     }
114 
115     @Test
layoutInDisplayCutoutMode_always()116     public void layoutInDisplayCutoutMode_always() throws Exception {
117         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeAlways);
118         installDecor();
119 
120         assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
121                 is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS));
122     }
123 
124     @Test
testWindowBackground_colorLiteral()125     public void testWindowBackground_colorLiteral() {
126         createPhoneWindowWithTheme(R.style.WindowBackgroundColorLiteral);
127         installDecor();
128 
129         Drawable backgroundDrawable = mPhoneWindow.getDecorView().getBackground();
130         assertThat(backgroundDrawable instanceof ColorDrawable, is(true));
131 
132         ColorDrawable colorDrawable = (ColorDrawable) backgroundDrawable;
133         assertThat(colorDrawable.getColor(), is(Color.GREEN));
134     }
135 
136     @Test
testWindowBackgroundFallback_colorLiteral()137     public void testWindowBackgroundFallback_colorLiteral() {
138         createPhoneWindowWithTheme(R.style.WindowBackgroundFallbackColorLiteral);
139         installDecor();
140 
141         DecorView decorView = (DecorView) mPhoneWindow.getDecorView();
142         Drawable fallbackDrawable = decorView.getBackgroundFallback();
143 
144         assertThat(fallbackDrawable instanceof ColorDrawable, is(true));
145 
146         ColorDrawable colorDrawable = (ColorDrawable) fallbackDrawable;
147         assertThat(colorDrawable.getColor(), is(Color.BLUE));
148     }
149 
150     @Test
testWindowBackgroundFallbackWithExplicitBackgroundSet_colorLiteral()151     public void testWindowBackgroundFallbackWithExplicitBackgroundSet_colorLiteral() {
152         createPhoneWindowWithTheme(R.style.WindowBackgroundFallbackColorLiteral);
153         // set background before decorView is created
154         mPhoneWindow.setBackgroundDrawable(new ColorDrawable(Color.CYAN));
155         installDecor();
156         // clear background so that fallback is used
157         mPhoneWindow.setBackgroundDrawable(null);
158 
159         DecorView decorView = (DecorView) mPhoneWindow.getDecorView();
160         Drawable fallbackDrawable = decorView.getBackgroundFallback();
161 
162         assertThat(fallbackDrawable instanceof ColorDrawable, is(true));
163 
164         ColorDrawable colorDrawable = (ColorDrawable) fallbackDrawable;
165         assertThat(colorDrawable.getColor(), is(Color.BLUE));
166     }
167 
168     @Test
169     @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
testWindowFrameRateHint_disabled()170     public void testWindowFrameRateHint_disabled() {
171         createPhoneWindowWithTheme(R.style.IsFrameRatePowerSavingsBalancedDisabled);
172         installDecor();
173 
174         DecorView decorView = (DecorView) mPhoneWindow.getDecorView();
175 
176         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
177         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
178         wmlp.setFrameRatePowerSavingsBalanced(
179                     mPhoneWindow.getAttributes().isFrameRatePowerSavingsBalanced());
180         sInstrumentation.runOnMainSync(() -> {
181             WindowManager wm = mContext.getSystemService(WindowManager.class);
182             wm.addView(decorView, wmlp);
183         });
184         sInstrumentation.waitForIdleSync();
185 
186         ViewRootImpl viewRootImpl = decorView.getViewRootImpl();
187         assertFalse(viewRootImpl.isFrameRatePowerSavingsBalanced());
188     }
189 
190     @Test
191     @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
testWindowFrameRateHint_enabled()192     public void testWindowFrameRateHint_enabled() {
193         createPhoneWindowWithTheme(R.style.IsFrameRatePowerSavingsBalancedEnabled);
194         installDecor();
195 
196         DecorView decorView = (DecorView) mPhoneWindow.getDecorView();
197 
198         WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
199         wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
200         wmlp.setFrameRatePowerSavingsBalanced(
201                 mPhoneWindow.getAttributes().isFrameRatePowerSavingsBalanced());
202         sInstrumentation.runOnMainSync(() -> {
203             WindowManager wm = mContext.getSystemService(WindowManager.class);
204             wm.addView(decorView, wmlp);
205         });
206         sInstrumentation.waitForIdleSync();
207 
208         ViewRootImpl viewRootImpl = decorView.getViewRootImpl();
209         assertTrue(viewRootImpl.isFrameRatePowerSavingsBalanced());
210     }
211 
createPhoneWindowWithTheme(int theme)212     private void createPhoneWindowWithTheme(int theme) {
213         mPhoneWindow = new PhoneWindow(new ContextThemeWrapper(mContext, theme));
214     }
215 
installDecor()216     private void installDecor() {
217         mPhoneWindow.getDecorView();
218     }
219 }