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