1c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonpackage com.android.server.vr; 2c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 33a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankarimport static android.view.Display.INVALID_DISPLAY; 43a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar 599493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankarimport android.app.ActivityManagerInternal; 62b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankarimport android.app.Vr2dDisplayProperties; 7c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.app.Service; 82f22da701b16f748abaeedd65be5ce5898abc824Santos Cordonimport android.content.BroadcastReceiver; 9c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.content.Context; 10c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.content.Intent; 112f22da701b16f748abaeedd65be5ce5898abc824Santos Cordonimport android.content.IntentFilter; 125a2ca72e389435b2419b64912af1d49a20b3cd35Daniel Nicoaraimport android.graphics.PixelFormat; 13c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.hardware.display.DisplayManager; 14c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.hardware.display.VirtualDisplay; 15975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordonimport android.media.ImageReader; 16c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.os.Build; 17c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.os.Handler; 18c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.os.IBinder; 19975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordonimport android.os.Message; 20c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.os.RemoteException; 21c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.os.ServiceManager; 22975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordonimport android.os.SystemProperties; 23975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordonimport android.service.vr.IPersistentVrStateCallbacks; 24c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.service.vr.IVrManager; 25c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport android.util.Log; 262f22da701b16f748abaeedd65be5ce5898abc824Santos Cordonimport android.view.Surface; 27c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 28c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordonimport com.android.server.vr.VrManagerService; 29c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 30c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon/** 31c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon * Creates a 2D Virtual Display while VR Mode is enabled. This display will be used to run and 32c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon * render 2D app within a VR experience. For example, bringing up the 2D calculator app in VR. 33c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon */ 342b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankarclass Vr2dDisplay { 352b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar private final static String TAG = "Vr2dDisplay"; 36c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private final static boolean DEBUG = false; 37c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 38c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon // TODO: Go over these values and figure out what is best 39cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar private int mVirtualDisplayHeight; 40cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar private int mVirtualDisplayWidth; 41cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar private int mVirtualDisplayDpi; 42975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000; 43b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon private final static String UNIQUE_DISPLAY_ID = "277f1a09-b88d-4d1e-8716-796f114d080b"; 44b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon private final static String DISPLAY_NAME = "VR 2D Display"; 45c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 462f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private final static String DEBUG_ACTION_SET_MODE = 472b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar "com.android.server.vr.Vr2dDisplay.SET_MODE"; 482f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private final static String DEBUG_EXTRA_MODE_ON = 492b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar "com.android.server.vr.Vr2dDisplay.EXTRA_MODE_ON"; 502f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private final static String DEBUG_ACTION_SET_SURFACE = 512b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar "com.android.server.vr.Vr2dDisplay.SET_SURFACE"; 522f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private final static String DEBUG_EXTRA_SURFACE = 532b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar "com.android.server.vr.Vr2dDisplay.EXTRA_SURFACE"; 542f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon 55cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar /** 56cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * The default width of the VR virtual display 57cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar */ 58cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int DEFAULT_VR_DISPLAY_WIDTH = 1400; 59cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 60cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar /** 61cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * The default height of the VR virtual display 62cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar */ 63cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int DEFAULT_VR_DISPLAY_HEIGHT = 1800; 64cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 65cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar /** 66cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * The default height of the VR virtual dpi. 67cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar */ 68cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int DEFAULT_VR_DISPLAY_DPI = 320; 69cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 70cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar /** 71cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * The minimum height, width and dpi of VR virtual display. 72cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar */ 73cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int MIN_VR_DISPLAY_WIDTH = 1; 74cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int MIN_VR_DISPLAY_HEIGHT = 1; 75cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar public static final int MIN_VR_DISPLAY_DPI = 1; 76cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 7799493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar private final ActivityManagerInternal mActivityManagerInternal; 78c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private final DisplayManager mDisplayManager; 79c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private final IVrManager mVrManager; 80975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private final Object mVdLock = new Object(); 81975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private final Handler mHandler = new Handler(); 82c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 83975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 84975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Callback implementation to receive changes to VrMode. 85975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon **/ 86975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private final IPersistentVrStateCallbacks mVrStateCallbacks = 87975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon new IPersistentVrStateCallbacks.Stub() { 88c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon @Override 89975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon public void onPersistentVrStateChanged(boolean enabled) { 90c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (enabled != mIsVrModeEnabled) { 91c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon mIsVrModeEnabled = enabled; 922f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon updateVirtualDisplay(); 93c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 94c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 95c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon }; 96c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 97c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private VirtualDisplay mVirtualDisplay; 982f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private Surface mSurface; 99975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private ImageReader mImageReader; 100975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private Runnable mStopVDRunnable; 101975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private boolean mIsVrModeOverrideEnabled; 102c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private boolean mIsVrModeEnabled; 103c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 1042b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar public Vr2dDisplay(DisplayManager displayManager, 10599493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar ActivityManagerInternal activityManagerInternal, IVrManager vrManager) { 106c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon mDisplayManager = displayManager; 10799493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar mActivityManagerInternal = activityManagerInternal; 108c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon mVrManager = vrManager; 109cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayWidth = DEFAULT_VR_DISPLAY_WIDTH; 110cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayHeight = DEFAULT_VR_DISPLAY_HEIGHT; 111cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayDpi = DEFAULT_VR_DISPLAY_DPI; 112c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 113c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 114c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon /** 115c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon * Initializes the compabilitiy display by listening to VR mode changes. 116c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon */ 1172f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon public void init(Context context) { 118c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon startVrModeListener(); 1192f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon startDebugOnlyBroadcastReceiver(context); 1202f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1212f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon 122975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 123975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Creates and Destroys the virtual display depending on the current state of VrMode. 124975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 1252f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private void updateVirtualDisplay() { 126975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (DEBUG) { 1275dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon Log.i(TAG, "isVrMode: " + mIsVrModeEnabled + ", override: " + mIsVrModeOverrideEnabled); 128975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 129975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon 1305dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon if (mIsVrModeEnabled || mIsVrModeOverrideEnabled) { 1312f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon // TODO: Consider not creating the display until ActivityManager needs one on 1322f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon // which to display a 2D application. 1335dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon startVirtualDisplay(); 1342f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } else { 1353a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar // Stop virtual display to test exit condition 1363a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar stopVirtualDisplay(); 1372f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1382f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1392f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon 140975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 141975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Creates a DEBUG-only BroadcastReceiver through which a test app can simulate VrMode and 142975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * set a custom Surface for the virtual display. This allows testing of the virtual display 143975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * without going into full 3D. 144975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * 145975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * @param context The context. 146975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 1472f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon private void startDebugOnlyBroadcastReceiver(Context context) { 1485dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon if (DEBUG) { 1492f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon IntentFilter intentFilter = new IntentFilter(DEBUG_ACTION_SET_MODE); 1502f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon intentFilter.addAction(DEBUG_ACTION_SET_SURFACE); 1512f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon 1522f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon context.registerReceiver(new BroadcastReceiver() { 1532f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon @Override 1542f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon public void onReceive(Context context, Intent intent) { 1552f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon final String action = intent.getAction(); 1562f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon if (DEBUG_ACTION_SET_MODE.equals(action)) { 157975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mIsVrModeOverrideEnabled = 1582f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon intent.getBooleanExtra(DEBUG_EXTRA_MODE_ON, false); 1592f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon updateVirtualDisplay(); 1602f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } else if (DEBUG_ACTION_SET_SURFACE.equals(action)) { 1612f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon if (mVirtualDisplay != null) { 162975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (intent.hasExtra(DEBUG_EXTRA_SURFACE)) { 163975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon setSurfaceLocked(intent.getParcelableExtra(DEBUG_EXTRA_SURFACE)); 1642f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1652f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } else { 1662f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon Log.w(TAG, "Cannot set the surface because the VD is null."); 1672f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1682f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1692f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 1702f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon }, intentFilter); 1712f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon } 172c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 173c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 174975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 175975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Starts listening to VrMode changes. 176975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 177c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private void startVrModeListener() { 178c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (mVrManager != null) { 179c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon try { 180975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mVrManager.registerPersistentVrStateListener(mVrStateCallbacks); 181c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } catch (RemoteException e) { 182c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon Log.e(TAG, "Could not register VR State listener.", e); 183c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 184c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 185c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 186c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 187975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 1882b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar * Sets the resolution and DPI of the Vr2d virtual display used to display 189cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * 2D applications in VR mode. 190cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * 191cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> 192cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * 193cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * @param compatDisplayProperties Properties of the virtual display for 2D applications 194cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar * in VR mode. 195cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar */ 1962b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar public void setVirtualDisplayProperties(Vr2dDisplayProperties compatDisplayProperties) { 197cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar synchronized(mVdLock) { 198cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar if (DEBUG) { 1995dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon Log.i(TAG, "VD setVirtualDisplayProperties: res = " 2005dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + compatDisplayProperties.getWidth() + "X" 2015dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + compatDisplayProperties.getHeight() + ", dpi = " 2025dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + compatDisplayProperties.getDpi()); 203cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar } 204cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 205cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar if (compatDisplayProperties.getWidth() < MIN_VR_DISPLAY_WIDTH || 206cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar compatDisplayProperties.getHeight() < MIN_VR_DISPLAY_HEIGHT || 207cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar compatDisplayProperties.getDpi() < MIN_VR_DISPLAY_DPI) { 208cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar throw new IllegalArgumentException ( 2095dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon "Illegal argument: height, width, dpi cannot be negative. res = " 2105dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + compatDisplayProperties.getWidth() + "X" 2115dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + compatDisplayProperties.getHeight() 2125dc6019bb423f662685b026e65779ebd8897c7c2Santos Cordon + ", dpi = " + compatDisplayProperties.getDpi()); 213cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar } 214cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 215cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayWidth = compatDisplayProperties.getWidth(); 216cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayHeight = compatDisplayProperties.getHeight(); 217cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayDpi = compatDisplayProperties.getDpi(); 218cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 219cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar if (mVirtualDisplay != null) { 220cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplay.resize(mVirtualDisplayWidth, mVirtualDisplayHeight, 221cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayDpi); 222cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar ImageReader oldImageReader = mImageReader; 223cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mImageReader = null; 224cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar startImageReader(); 225cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar oldImageReader.close(); 226cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar } 227cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar } 228cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar } 229cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar 230cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar /** 231975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Returns the virtual display ID if one currently exists, otherwise returns 232975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * {@link INVALID_DISPLAY_ID}. 233975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * 234975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * @return The virtual display ID. 235975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 2363a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar public int getVirtualDisplayId() { 237975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon synchronized(mVdLock) { 2383a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar if (mVirtualDisplay != null) { 2393a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar int virtualDisplayId = mVirtualDisplay.getDisplay().getDisplayId(); 2403a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar if (DEBUG) { 241cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar Log.i(TAG, "VD id: " + virtualDisplayId); 2423a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar } 2433a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar return virtualDisplayId; 2443a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar } 2453a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar } 2463a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar return INVALID_DISPLAY; 2473a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar } 2483a47ec2edd04546d82ba1df331c7af778858a281Karthik Ravi Shankar 249975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 250975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Starts the virtual display if one does not already exist. 251975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 252c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private void startVirtualDisplay() { 253c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (DEBUG) { 2542f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon Log.d(TAG, "Request to start VD, DM:" + mDisplayManager); 255c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 256c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 257c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (mDisplayManager == null) { 258c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon Log.w(TAG, "Cannot create virtual display because mDisplayManager == null"); 259c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon return; 260c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 261c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 262975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon synchronized (mVdLock) { 263c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (mVirtualDisplay != null) { 2642f22da701b16f748abaeedd65be5ce5898abc824Santos Cordon Log.i(TAG, "VD already exists, ignoring request"); 265c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon return; 266c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 267c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 268b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH; 269b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */, 270b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi, 271b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon null /* surface */, flags, null /* callback */, null /* handler */, 272b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon UNIQUE_DISPLAY_ID); 27399493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar 27499493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar if (mVirtualDisplay != null) { 2752b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar mActivityManagerInternal.setVr2dDisplayId( 27699493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar mVirtualDisplay.getDisplay().getDisplayId()); 277728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon // Now create the ImageReader to supply a Surface to the new virtual display. 278728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon startImageReader(); 27999493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar } else { 28099493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar Log.w(TAG, "Virtual display id is null after createVirtualDisplay"); 2812b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY); 28299493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar return; 28399493dbc94989d4493ca6acb0db265a02f49f62eKarthik Ravi Shankar } 284c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 285c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 286cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar Log.i(TAG, "VD created: " + mVirtualDisplay); 287c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 288c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 289975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 290975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Stops the virtual display with a {@link #STOP_VIRTUAL_DISPLAY_DELAY_MILLIS} timeout. 291975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * The timeout prevents the virtual display from bouncing in cases where VrMode goes in and out 292975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * of being enabled. This can happen sometimes with our 2D test app. 293975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 294c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon private void stopVirtualDisplay() { 295975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mStopVDRunnable == null) { 296975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mStopVDRunnable = new Runnable() { 297975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon @Override 298975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon public void run() { 299975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mIsVrModeEnabled) { 300975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon Log.i(TAG, "Virtual Display destruction stopped: VrMode is back on."); 301975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } else { 302975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon Log.i(TAG, "Stopping Virtual Display"); 303975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon synchronized (mVdLock) { 3042b9aaedf6310694de31301659ce604ff195b32eeKarthik Ravi Shankar mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY); 305975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon setSurfaceLocked(null); // clean up and release the surface first. 306975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mVirtualDisplay != null) { 307975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mVirtualDisplay.release(); 308975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mVirtualDisplay = null; 309975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 310728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon stopImageReader(); 311975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 312975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 313975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 314975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon }; 315c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 316c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon 317975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mHandler.removeCallbacks(mStopVDRunnable); 318975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mHandler.postDelayed(mStopVDRunnable, STOP_VIRTUAL_DISPLAY_DELAY_MILLIS); 319975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 320975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon 321975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 322975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Set the surface to use with the virtual display. 323975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * 324975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Code should be locked by {@link #mVdLock} before invoked. 325975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * 326975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * @param surface The Surface to set. 327975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 328975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private void setSurfaceLocked(Surface surface) { 329975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon // Change the surface to either a valid surface or a null value. 330975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mSurface != surface && (surface == null || surface.isValid())) { 331975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon Log.i(TAG, "Setting the new surface from " + mSurface + " to " + surface); 332c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon if (mVirtualDisplay != null) { 333975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mVirtualDisplay.setSurface(surface); 334975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 335975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mSurface != null) { 336975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mSurface.release(); 337c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 338975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon mSurface = surface; 339975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 340975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 341975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon 342975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon /** 343975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * Starts an ImageReader as a do-nothing Surface. The virtual display will not get fully 344975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * initialized within surface flinger unless it has a valid Surface associated with it. We use 345975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon * the ImageReader as the default valid Surface. 346975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon */ 347975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon private void startImageReader() { 348975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon if (mImageReader == null) { 349cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mImageReader = ImageReader.newInstance(mVirtualDisplayWidth, mVirtualDisplayHeight, 350cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar PixelFormat.RGBA_8888, 2 /* maxImages */); 351cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar Log.i(TAG, "VD startImageReader: res = " + mVirtualDisplayWidth + "X" + 352cdf9ce7229e791fe345b0860fe32433f15c95db8Karthik Ravi Shankar mVirtualDisplayHeight + ", dpi = " + mVirtualDisplayDpi); 353975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon } 354975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon synchronized (mVdLock) { 355975c00d8ffeeb72a05bc229e0e1234e771c4a824Santos Cordon setSurfaceLocked(mImageReader.getSurface()); 356c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 357c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon } 358728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon 359728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon /** 360728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon * Cleans up the ImageReader. 361728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon */ 362728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon private void stopImageReader() { 363728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon if (mImageReader != null) { 364728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon mImageReader.close(); 365728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon mImageReader = null; 366728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon } 367728d81f67326ad0c2f468d1da560936b5ffb90a0Santos Cordon } 368c14513d81ef22cfbab93a9209f237534b3b5edc8Santos Cordon} 369