164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown/*
264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * Copyright (C) 2012 The Android Open Source Project
364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown *
464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * you may not use this file except in compliance with the License.
664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * You may obtain a copy of the License at
764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown *
864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown *
1064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * Unless required by applicable law or agreed to in writing, software
1164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * See the License for the specific language governing permissions and
1464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * limitations under the License.
1564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown */
1664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
1764a55af0ac700baecb0877235eb42caac59a3560Jeff Brownpackage com.android.server.display;
1864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
1964a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.content.Context;
204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.os.Handler;
2164a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.os.IBinder;
22e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brownimport android.os.Looper;
2327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brownimport android.os.SystemProperties;
244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport android.util.SparseArray;
2592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brownimport android.view.Display;
26e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brownimport android.view.DisplayEventReceiver;
2764a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.view.Surface;
283866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl;
293866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl.PhysicalDisplayInfo;
3064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport java.io.PrintWriter;
324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown/**
3464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * A display adapter for the local displays managed by Surface Flinger.
35bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * <p>
364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
37bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p>
3864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown */
394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownfinal class LocalDisplayAdapter extends DisplayAdapter {
40bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final String TAG = "LocalDisplayAdapter";
4164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
433866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
443866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    };
464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SparseArray<LocalDisplayDevice> mDevices =
484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new SparseArray<LocalDisplayDevice>();
4966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown    private HotplugDisplayEventReceiver mHotplugReceiver;
504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
513866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
5366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown    // Called with SyncRoot lock held.
544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Context context, Handler handler, Listener listener) {
564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        super(syncRoot, context, handler, listener, TAG);
5764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    }
5864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
5964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    @Override
604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void registerLocked() {
614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        super.registerLocked();
6266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown
6366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
66e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            tryConnectDisplayLocked(builtInDisplayId);
67e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall        }
68e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall    }
69e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall
70e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall    private void tryConnectDisplayLocked(int builtInDisplayId) {
713866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
723866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
73e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            LocalDisplayDevice device = mDevices.get(builtInDisplayId);
74e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            if (device == null) {
75e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                // Display was added.
76e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
77e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                mDevices.put(builtInDisplayId, device);
78e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
79e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
80e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                // Display properties changed.
81e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
83e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall        } else {
84e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            // The display is no longer available. Ignore the attempt to add it.
85e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            // If it was connected but has already been disconnected, we'll get a
86e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            // disconnect event that will remove it from mDevices.
87e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall        }
88e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall    }
89e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall
90e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall    private void tryDisconnectDisplayLocked(int builtInDisplayId) {
91e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall        LocalDisplayDevice device = mDevices.get(builtInDisplayId);
92e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall        if (device != null) {
93e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            // Display was removed.
94e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            mDevices.remove(builtInDisplayId);
95e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
9764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    }
9864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
9964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    private final class LocalDisplayDevice extends DisplayDevice {
1004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        private final int mBuiltInDisplayId;
1013866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        private final SurfaceControl.PhysicalDisplayInfo mPhys;
10264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        private DisplayDeviceInfo mInfo;
1044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        private boolean mHavePendingChanges;
1059e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        private boolean mBlanked;
1064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
1083866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian                SurfaceControl.PhysicalDisplayInfo phys) {
109bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            super(LocalDisplayAdapter.this, displayToken);
1104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mBuiltInDisplayId = builtInDisplayId;
1113866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
1124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1143866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!mPhys.equals(phys)) {
1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mPhys.copyFrom(phys);
1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mHavePendingChanges = true;
1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return true;
1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return false;
12164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        }
12264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
12364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        @Override
1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void applyPendingDisplayDeviceInfoChangesLocked() {
1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (mHavePendingChanges) {
1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mInfo = null;
1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mHavePendingChanges = false;
128bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
12964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        }
1304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
1324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
1334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (mInfo == null) {
1344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mInfo = new DisplayDeviceInfo();
1354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mInfo.width = mPhys.width;
1364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mInfo.height = mPhys.height;
1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mInfo.refreshRate = mPhys.refreshRate;
13877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown
139f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown                // Assume that all built-in displays that have secure output (eg. HDCP) also
14077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown                // support compositing from gralloc protected buffers.
141f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown                if (mPhys.secure) {
142f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown                    mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
143f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown                            | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
144f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown                }
14577aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown
1463866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian                if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    mInfo.name = getContext().getResources().getString(
1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                            com.android.internal.R.string.display_manager_built_in_display_name);
14977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown                    mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
15027f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                            | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
15192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown                    mInfo.type = Display.TYPE_BUILT_IN;
152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                    mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                    mInfo.xDpi = mPhys.xDpi;
154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                    mInfo.yDpi = mPhys.yDpi;
155d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
1564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                } else {
15792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown                    mInfo.type = Display.TYPE_HDMI;
1584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    mInfo.name = getContext().getResources().getString(
1594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                            com.android.internal.R.string.display_manager_hdmi_display_name);
160d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                    mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
16227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown
16327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                    // For demonstration purposes, allow rotation of the external display.
16427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                    // In the future we might allow the user to configure this directly.
16527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                    if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
16627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                        mInfo.rotation = Surface.ROTATION_270;
16727f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                    }
1684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                }
1694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
1704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return mInfo;
1714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
1724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
1749e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        public void blankLocked() {
1759e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            mBlanked = true;
1763866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            SurfaceControl.blankDisplay(getDisplayTokenLocked());
1779e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        }
1789e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
1799e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        @Override
1809e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        public void unblankLocked() {
1819e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            mBlanked = false;
1823866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            SurfaceControl.unblankDisplay(getDisplayTokenLocked());
1839e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        }
1849e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
1859e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        @Override
1864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void dumpLocked(PrintWriter pw) {
1874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            super.dumpLocked(pw);
1884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
1894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            pw.println("mPhys=" + mPhys);
1909e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("mBlanked=" + mBlanked);
1914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
19264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    }
193e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
194e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
195e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        public HotplugDisplayEventReceiver(Looper looper) {
196e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            super(looper);
197e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        }
198e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
199e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        @Override
200e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
201e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            synchronized (getSyncRoot()) {
202e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                if (connected) {
203e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                    tryConnectDisplayLocked(builtInDisplayId);
204e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                } else {
205e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                    tryDisconnectDisplayLocked(builtInDisplayId);
206e244db42da1cb07f53a1fc921b45d498000b56e8Jesse Hall                }
207e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            }
208e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        }
209e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    }
210e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown}