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; 2864a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.view.Surface.PhysicalDisplayInfo; 2964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport java.io.PrintWriter; 314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 3264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown/** 3364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * A display adapter for the local displays managed by Surface Flinger. 34bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * <p> 354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 36bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p> 3764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown */ 384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownfinal class LocalDisplayAdapter extends DisplayAdapter { 39bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final String TAG = "LocalDisplayAdapter"; 4064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] { 424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Surface.BUILT_IN_DISPLAY_ID_MAIN, 434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Surface.BUILT_IN_DISPLAY_ID_HDMI, 444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown }; 454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final SparseArray<LocalDisplayDevice> mDevices = 474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown new SparseArray<LocalDisplayDevice>(); 4866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private HotplugDisplayEventReceiver mHotplugReceiver; 494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo(); 514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 5266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Called with SyncRoot lock held. 534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Context context, Handler handler, Listener listener) { 554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super(syncRoot, context, handler, listener, TAG); 5664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 5764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 5864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown @Override 594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void registerLocked() { 604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super.registerLocked(); 6166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 6266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper()); 634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown scanDisplaysLocked(); 644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private void scanDisplaysLocked() { 674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) { 684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId); 694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) { 704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown LocalDisplayDevice device = mDevices.get(builtInDisplayId); 714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (device == null) { 724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display was added. 734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys); 744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDevices.put(builtInDisplayId, device); 754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); 764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) { 774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display properties changed. 784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED); 794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else { 814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown LocalDisplayDevice device = mDevices.get(builtInDisplayId); 824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (device != null) { 834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display was removed. 844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDevices.remove(builtInDisplayId); 854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); 864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 8964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 9064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 9164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown private final class LocalDisplayDevice extends DisplayDevice { 924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final int mBuiltInDisplayId; 934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final PhysicalDisplayInfo mPhys; 9464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private DisplayDeviceInfo mInfo; 964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private boolean mHavePendingChanges; 979e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown private boolean mBlanked; 984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId, 1004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown PhysicalDisplayInfo phys) { 101bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown super(LocalDisplayAdapter.this, displayToken); 1024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mBuiltInDisplayId = builtInDisplayId; 1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mPhys = new PhysicalDisplayInfo(phys); 1044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) { 1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (!mPhys.equals(phys)) { 1084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mPhys.copyFrom(phys); 1094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mHavePendingChanges = true; 1104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return true; 1114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return false; 11364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 11464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 11564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown @Override 1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void applyPendingDisplayDeviceInfoChangesLocked() { 1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mHavePendingChanges) { 1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo = null; 1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mHavePendingChanges = false; 120bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 12164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown @Override 1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mInfo == null) { 1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo = new DisplayDeviceInfo(); 1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.width = mPhys.width; 1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.height = mPhys.height; 1294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.refreshRate = mPhys.refreshRate; 13077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown 131f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown // Assume that all built-in displays that have secure output (eg. HDCP) also 13277aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown // support compositing from gralloc protected buffers. 133f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (mPhys.secure) { 134f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown mInfo.flags = DisplayDeviceInfo.FLAG_SECURE 135f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 136f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 13777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown 1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) { 1394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.name = getContext().getResources().getString( 1404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown com.android.internal.R.string.display_manager_built_in_display_name); 14177aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY 14227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; 14392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.type = Display.TYPE_BUILT_IN; 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); 145cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.xDpi = mPhys.xDpi; 146cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.yDpi = mPhys.yDpi; 147d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; 1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else { 14992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.type = Display.TYPE_HDMI; 1504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.name = getContext().getResources().getString( 1514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown com.android.internal.R.string.display_manager_hdmi_display_name); 152d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); 15427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown 15527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown // For demonstration purposes, allow rotation of the external display. 15627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown // In the future we might allow the user to configure this directly. 15727f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 15827f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown mInfo.rotation = Surface.ROTATION_270; 15927f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown } 1604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return mInfo; 1634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown @Override 1669e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown public void blankLocked() { 1679e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown mBlanked = true; 1689e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown Surface.blankDisplay(getDisplayTokenLocked()); 1699e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown } 1709e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown 1719e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown @Override 1729e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown public void unblankLocked() { 1739e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown mBlanked = false; 1749e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown Surface.unblankDisplay(getDisplayTokenLocked()); 1759e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown } 1769e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown 1779e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown @Override 1784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void dumpLocked(PrintWriter pw) { 1794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super.dumpLocked(pw); 1804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId); 1814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown pw.println("mPhys=" + mPhys); 1829e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown pw.println("mBlanked=" + mBlanked); 1834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 18464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 185e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown 186e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown private final class HotplugDisplayEventReceiver extends DisplayEventReceiver { 187e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown public HotplugDisplayEventReceiver(Looper looper) { 188e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown super(looper); 189e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 190e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown 191e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown @Override 192e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { 193e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown synchronized (getSyncRoot()) { 194e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown scanDisplaysLocked(); 195e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 196e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 197e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 198e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown}