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.server.wm;
18 
19 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
20 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
22 import static android.server.wm.ActivityManagerTestBase.isDisplayOn;
23 import static android.server.wm.StateLogger.logAlways;
24 import static android.view.Display.DEFAULT_DISPLAY;
25 
26 import static androidx.test.InstrumentationRegistry.getInstrumentation;
27 
28 import static org.junit.Assert.fail;
29 
30 import android.graphics.PixelFormat;
31 import android.hardware.display.DisplayManager;
32 import android.hardware.display.VirtualDisplay;
33 import android.media.ImageReader;
34 import android.os.SystemClock;
35 
36 import com.android.compatibility.common.util.SystemUtil;
37 
38 import java.util.function.Predicate;
39 
40 /**
41  * Helper class to create virtual display.
42  */
43 class VirtualDisplayHelper {
44 
45     private boolean mPublicDisplay = false;
46     private boolean mCanShowWithInsecureKeyguard = false;
47     private boolean mShowSystemDecorations = false;
48 
49     private static final String VIRTUAL_DISPLAY_NAME = "CtsVirtualDisplay";
50     /** See {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD}. */
51     private static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
52     /** See {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS}. */
53     private static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;
54 
55     private static final int DENSITY = 160;
56     static final int HEIGHT = 480;
57     static final int WIDTH = 800;
58 
59     private ImageReader mReader;
60     private VirtualDisplay mVirtualDisplay;
61     private boolean mCreated;
62 
setPublicDisplay(boolean publicDisplay)63     VirtualDisplayHelper setPublicDisplay(boolean publicDisplay) {
64         mPublicDisplay = publicDisplay;
65         return this;
66     }
67 
setCanShowWithInsecureKeyguard(boolean canShowWithInsecureKeyguard)68     VirtualDisplayHelper setCanShowWithInsecureKeyguard(boolean canShowWithInsecureKeyguard) {
69         mCanShowWithInsecureKeyguard = canShowWithInsecureKeyguard;
70         return this;
71     }
72 
setShowSystemDecorations(boolean showSystemDecorations)73     VirtualDisplayHelper setShowSystemDecorations(boolean showSystemDecorations) {
74         mShowSystemDecorations = showSystemDecorations;
75         return this;
76     }
77 
createAndWaitForDisplay()78     int createAndWaitForDisplay() {
79         SystemUtil.runWithShellPermissionIdentity(() -> {
80             createVirtualDisplay();
81             waitForDisplayState(mVirtualDisplay.getDisplay().getDisplayId() /* default */,
82                     true /* on */);
83             mCreated = true;
84         });
85         return mVirtualDisplay.getDisplay().getDisplayId();
86     }
87 
turnDisplayOff()88     void turnDisplayOff() {
89         SystemUtil.runWithShellPermissionIdentity(() -> {
90             mVirtualDisplay.setSurface(null);
91             waitForDisplayState(mVirtualDisplay.getDisplay().getDisplayId() /* displayId */,
92                     false /* on */);
93         });
94     }
95 
turnDisplayOn()96     void turnDisplayOn() {
97         SystemUtil.runWithShellPermissionIdentity(() -> {
98             mVirtualDisplay.setSurface(mReader.getSurface());
99             waitForDisplayState(mVirtualDisplay.getDisplay().getDisplayId() /* displayId */,
100                     true /* on */);
101         });
102     }
103 
releaseDisplay()104     void releaseDisplay() {
105         SystemUtil.runWithShellPermissionIdentity(() -> {
106             if (mCreated) {
107                 mVirtualDisplay.release();
108                 mReader.close();
109                 waitForDisplayCondition(mVirtualDisplay.getDisplay().getDisplayId() /* displayId */,
110                         onState -> onState != null && onState == false,
111                         "Waiting for virtual display destroy");
112             }
113             mCreated = false;
114         });
115     }
116 
createVirtualDisplay()117     private void createVirtualDisplay() {
118         mReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
119 
120         final DisplayManager displayManager = getInstrumentation()
121                 .getContext().getSystemService(DisplayManager.class);
122 
123         int flags = VIRTUAL_DISPLAY_FLAG_PRESENTATION | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
124 
125         if (mPublicDisplay) {
126             flags |= VIRTUAL_DISPLAY_FLAG_PUBLIC;
127         }
128         if (mCanShowWithInsecureKeyguard) {
129             flags |= VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
130         }
131         if (mShowSystemDecorations) {
132             flags |= VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
133         }
134 
135         logAlways("createVirtualDisplay: " + WIDTH + "x" + HEIGHT + ", dpi: " + DENSITY
136                 + ", publicDisplay=" + mPublicDisplay
137                 + ", canShowWithInsecureKeyguard=" + mCanShowWithInsecureKeyguard
138                 + ", showSystemDecorations=" + mShowSystemDecorations);
139 
140         mVirtualDisplay = displayManager.createVirtualDisplay(
141                 VIRTUAL_DISPLAY_NAME, WIDTH, HEIGHT, DENSITY, mReader.getSurface(), flags);
142     }
143 
waitForDefaultDisplayState(boolean wantOn)144     static void waitForDefaultDisplayState(boolean wantOn) {
145         waitForDisplayState(DEFAULT_DISPLAY /* default */, wantOn);
146     }
147 
waitForDisplayState(int displayId, boolean wantOn)148     private static void waitForDisplayState(int displayId, boolean wantOn) {
149         waitForDisplayCondition(displayId, state -> state != null && state == wantOn,
150                 "Waiting for " + ((displayId == DEFAULT_DISPLAY) ? "default" : "virtual")
151                         + " display "
152                         + (wantOn ? "on" : "off"));
153     }
154 
waitForDisplayCondition(int displayId, Predicate<Boolean> condition, String message)155     private static void waitForDisplayCondition(int displayId,
156             Predicate<Boolean> condition, String message) {
157         for (int retry = 1; retry <= 10; retry++) {
158             if (condition.test(isDisplayOn(displayId))) {
159                 return;
160             }
161             logAlways(message + "... retry=" + retry);
162             SystemClock.sleep(500);
163         }
164         fail(message + " failed");
165     }
166 }
167