1 /*
2  * Copyright (C) 2020 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.server.wm;
18 
19 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
20 import static android.server.wm.WindowManagerState.STATE_STOPPED;
21 import static android.server.wm.app.Components.TEST_ACTIVITY;
22 import static android.server.wm.app.Components.TEST_DREAM_SERVICE;
23 import static android.server.wm.app.Components.TEST_STUBBORN_DREAM_SERVICE;
24 import static android.server.wm.ComponentNameUtils.getWindowName;
25 
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertTrue;
28 import static android.view.Display.DEFAULT_DISPLAY;
29 
30 import static org.junit.Assume.assumeTrue;
31 
32 import android.app.DreamManager;
33 import android.content.ComponentName;
34 import android.platform.test.annotations.Presubmit;
35 import android.provider.Settings;
36 import android.server.wm.app.Components;
37 import android.view.Surface;
38 import android.content.res.Resources;
39 
40 import androidx.test.filters.FlakyTest;
41 
42 import com.android.compatibility.common.util.SystemUtil;
43 
44 import org.junit.After;
45 import org.junit.Before;
46 import org.junit.Test;
47 
48 @Presubmit
49 @FlakyTest(detail = "Promote once confirmed non-flaky")
50 public class DreamManagerServiceTests extends ActivityManagerTestBase {
51 
52     // Timeout after which the dream should have finished willingly
53     private static final long ACTIVITY_STOP_TIMEOUT = 3000;
54 
55     // Timeout after which the dream should have been forcefully stopped
56     private static final long ACTIVITY_FORCE_STOP_TIMEOUT = 6500;
57 
58     private ComponentName mDreamActivityName;
59 
60     private boolean mDefaultDreamServiceEnabled = true;
61 
getDreamActivityName(ComponentName dream)62     private static final ComponentName getDreamActivityName(ComponentName dream) {
63         return new ComponentName(dream.getPackageName(),
64                                  "android.service.dreams.DreamActivity");
65     }
66 
67     @Before
setup()68     public void setup() {
69         assumeTrue("Skipping test: no dream support", supportsDream());
70 
71         mDefaultDreamServiceEnabled =
72                 Settings.Secure.getInt(mContext.getContentResolver(),
73                                 "screensaver_enabled", 1) != 0;
74         if (!mDefaultDreamServiceEnabled) {
75             SystemUtil.runWithShellPermissionIdentity(() -> {
76                 Settings.Secure.putInt(mContext.getContentResolver(), "screensaver_enabled", 1);
77             });
78         }
79     }
80 
81     @After
reset()82     public void reset()  {
83         if (!mDefaultDreamServiceEnabled) {
84             SystemUtil.runWithShellPermissionIdentity(() -> {
85                 Settings.Secure.putInt(mContext.getContentResolver(), "screensaver_enabled", 0);
86             });
87         }
88     }
89 
startDream(ComponentName name)90     private void startDream(ComponentName name) {
91         DreamManager dreamer = mContext.getSystemService(DreamManager.class);
92         SystemUtil.runWithShellPermissionIdentity(() -> {
93             dreamer.startDream(name);
94         });
95     }
96 
stopDream()97     private void stopDream() {
98         DreamManager dreamer = mContext.getSystemService(DreamManager.class);
99         SystemUtil.runWithShellPermissionIdentity(() -> {
100             dreamer.stopDream();
101         });
102     }
103 
setActiveDream(ComponentName dream)104     private void setActiveDream(ComponentName dream) {
105         DreamManager dreamer = mContext.getSystemService(DreamManager.class);
106         SystemUtil.runWithShellPermissionIdentity(() -> {
107             dreamer.setActiveDream(dream);
108         });
109         mDreamActivityName = getDreamActivityName(dream);
110     }
111 
getIsDreaming()112     private boolean getIsDreaming() {
113         DreamManager dreamer = mContext.getSystemService(DreamManager.class);
114         return SystemUtil.runWithShellPermissionIdentity(() -> {
115             return dreamer.isDreaming();
116         });
117     }
118 
supportsDream()119     private boolean supportsDream() {
120         return mContext.getResources().getBoolean(
121                 Resources.getSystem().getIdentifier("config_dreamsSupported", "bool", "android"));
122     }
123 
assertDreamActivityGone()124     private void assertDreamActivityGone() {
125         mWmState.computeState();
126         assertTrue(!mWmState.containsWindow(getWindowName(mDreamActivityName))
127                    && !mWmState.containsActivity(mDreamActivityName));
128     }
129 
startFullscreenTestActivity()130     private void startFullscreenTestActivity() {
131         launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
132         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
133                 "Test activity should be the top resumed activity");
134         mWmState.assertVisibility(TEST_ACTIVITY, true);
135     }
136 
137     @Test
testStartAndStopDream()138     public void testStartAndStopDream() throws Exception {
139         startFullscreenTestActivity();
140         setActiveDream(TEST_DREAM_SERVICE);
141 
142         startDream(TEST_DREAM_SERVICE);
143         waitAndAssertTopResumedActivity(mDreamActivityName, DEFAULT_DISPLAY,
144                 "Dream activity should be the top resumed activity");
145         mWmState.waitForValidState(mWmState.getHomeActivityName());
146         mWmState.assertVisibility(mWmState.getHomeActivityName(), false);
147         mWmState.waitForValidState(TEST_ACTIVITY);
148         mWmState.assertVisibility(TEST_ACTIVITY, false);
149 
150         assertTrue(getIsDreaming());
151 
152         stopDream();
153         mWmState.waitAndAssertActivityRemoved(mDreamActivityName);
154 
155         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
156                 "Previous top activity should show when dream is stopped");
157     }
158 
159     @Test
testDreamServiceStopsTimely()160     public void testDreamServiceStopsTimely() throws Exception {
161         setActiveDream(TEST_DREAM_SERVICE);
162 
163         startDream(TEST_DREAM_SERVICE);
164         waitAndAssertTopResumedActivity(mDreamActivityName, DEFAULT_DISPLAY,
165                 "Dream activity should be the top resumed activity");
166         mWmState.waitForValidState(mWmState.getHomeActivityName());
167         mWmState.assertVisibility(mWmState.getHomeActivityName(), false);
168         assertTrue(getIsDreaming());
169 
170         stopDream();
171 
172         Thread.sleep(ACTIVITY_STOP_TIMEOUT);
173 
174         assertDreamActivityGone();
175         assertFalse(getIsDreaming());
176     }
177 
178     @Test
testForceStopStubbornDream()179     public void testForceStopStubbornDream() throws Exception {
180         startFullscreenTestActivity();
181         setActiveDream(TEST_STUBBORN_DREAM_SERVICE);
182 
183         startDream(TEST_STUBBORN_DREAM_SERVICE);
184         waitAndAssertTopResumedActivity(mDreamActivityName, DEFAULT_DISPLAY,
185                 "Dream activity should be the top resumed activity");
186         mWmState.waitForValidState(mWmState.getHomeActivityName());
187         mWmState.assertVisibility(mWmState.getHomeActivityName(), false);
188         mWmState.waitForValidState(TEST_ACTIVITY);
189         mWmState.assertVisibility(TEST_ACTIVITY, false);
190 
191         stopDream();
192 
193         Thread.sleep(ACTIVITY_FORCE_STOP_TIMEOUT);
194 
195         assertDreamActivityGone();
196         assertFalse(getIsDreaming());
197         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
198                 "Previous top activity should show when dream is stopped");
199     }
200 
201     @Test
testDreamNotFinishAfterRotation()202     public void testDreamNotFinishAfterRotation() {
203         assumeTrue("Skipping test: no rotation support", supportsRotation());
204 
205         final RotationSession rotationSession = createManagedRotationSession();
206         rotationSession.set(Surface.ROTATION_0);
207         setActiveDream(TEST_DREAM_SERVICE);
208         startDream(TEST_DREAM_SERVICE);
209         rotationSession.set(Surface.ROTATION_90);
210 
211         waitAndAssertTopResumedActivity(mDreamActivityName, DEFAULT_DISPLAY,
212                 "Dream activity should be the top resumed activity");
213     }
214 
215     @Test
testStartActivityDoesNotWakeAndIsNotResumed()216     public void testStartActivityDoesNotWakeAndIsNotResumed() {
217         try (DreamingState state = new DreamingState(TEST_DREAM_SERVICE)) {
218             launchActivity(Components.TEST_ACTIVITY);
219             mWmState.waitForActivityState(Components.TEST_ACTIVITY, STATE_STOPPED);
220             assertTrue(getIsDreaming());
221         }
222     }
223 
224     @Test
testStartTurnScreenOnActivityDoesWake()225     public void testStartTurnScreenOnActivityDoesWake() {
226         try (DreamingState state = new DreamingState(TEST_DREAM_SERVICE)) {
227             launchActivity(Components.TURN_SCREEN_ON_ACTIVITY);
228 
229             state.waitForDreamGone();
230             waitAndAssertTopResumedActivity(Components.TURN_SCREEN_ON_ACTIVITY,
231                     DEFAULT_DISPLAY, "TurnScreenOnActivity should resume through dream");
232         }
233     }
234 
235     @Test
testStartTurnScreenOnAttrActivityDoesWake()236     public void testStartTurnScreenOnAttrActivityDoesWake() {
237         try (DreamingState state = new DreamingState(TEST_DREAM_SERVICE)) {
238             launchActivity(Components.TURN_SCREEN_ON_ATTR_ACTIVITY);
239 
240             state.waitForDreamGone();
241             waitAndAssertTopResumedActivity(Components.TURN_SCREEN_ON_ATTR_ACTIVITY,
242                     DEFAULT_DISPLAY, "TurnScreenOnAttrActivity should resume through dream");
243         }
244     }
245 
246     @Test
testStartActivityOnKeyguardLocked()247     public void testStartActivityOnKeyguardLocked() {
248         assumeTrue(supportsLockScreen());
249 
250         final LockScreenSession lockScreenSession = createManagedLockScreenSession();
251         lockScreenSession.setLockCredential();
252         try (DreamingState state = new DreamingState(TEST_DREAM_SERVICE)) {
253             launchActivityNoWait(Components.TEST_ACTIVITY);
254             waitAndAssertActivityState(Components.TEST_ACTIVITY, STATE_STOPPED,
255                 "Activity must be started and stopped");
256             assertTrue(getIsDreaming());
257 
258             launchActivity(Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY);
259             state.waitForDreamGone();
260             waitAndAssertTopResumedActivity(Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY,
261                     DEFAULT_DISPLAY, "TurnScreenOnShowOnLockActivity should resume through dream");
262             assertFalse(getIsDreaming());
263         }
264     }
265 
266     private class DreamingState implements AutoCloseable {
DreamingState(ComponentName dream)267         public DreamingState(ComponentName dream) {
268             setActiveDream(dream);
269             startDream(dream);
270             waitAndAssertDreaming();
271         }
272 
273         @Override
close()274         public void close() {
275             stopDream();
276         }
277 
waitAndAssertDreaming()278         public void waitAndAssertDreaming() {
279             waitAndAssertTopResumedActivity(mDreamActivityName, DEFAULT_DISPLAY,
280                     "Dream activity should be the top resumed activity");
281             mWmState.waitForValidState(mWmState.getHomeActivityName());
282             mWmState.assertVisibility(mWmState.getHomeActivityName(), false);
283             assertTrue(getIsDreaming());
284         }
285 
waitForDreamGone()286         public void waitForDreamGone() {
287             mWmState.waitForDreamGone();
288             assertFalse(getIsDreaming());
289         }
290     }
291 }
292