LocalDisplayAdapter.java revision f0681b34dffc1510cbd9c3da5c3a7e695553fa8d
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; 25e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brownimport android.view.DisplayEventReceiver; 2664a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.view.Surface; 2764a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.view.Surface.PhysicalDisplayInfo; 2864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport java.io.PrintWriter; 304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 3164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown/** 3264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown * A display adapter for the local displays managed by Surface Flinger. 33bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * <p> 344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 35bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p> 3664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown */ 374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownfinal class LocalDisplayAdapter extends DisplayAdapter { 38bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown private static final String TAG = "LocalDisplayAdapter"; 3964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] { 414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Surface.BUILT_IN_DISPLAY_ID_MAIN, 424ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Surface.BUILT_IN_DISPLAY_ID_HDMI, 434ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown }; 444ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final SparseArray<LocalDisplayDevice> mDevices = 464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown new SparseArray<LocalDisplayDevice>(); 4766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private HotplugDisplayEventReceiver mHotplugReceiver; 484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo(); 504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 5166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Called with SyncRoot lock held. 524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown Context context, Handler handler, Listener listener) { 544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super(syncRoot, context, handler, listener, TAG); 5564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 5664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 5764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown @Override 584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void registerLocked() { 594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super.registerLocked(); 6066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 6166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper()); 624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown scanDisplaysLocked(); 634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private void scanDisplaysLocked() { 664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) { 674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId); 684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) { 694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown LocalDisplayDevice device = mDevices.get(builtInDisplayId); 704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (device == null) { 714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display was added. 724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys); 734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDevices.put(builtInDisplayId, device); 744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); 754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) { 764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display properties changed. 774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED); 784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else { 804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown LocalDisplayDevice device = mDevices.get(builtInDisplayId); 814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (device != null) { 824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown // Display was removed. 834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mDevices.remove(builtInDisplayId); 844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); 854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 8864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 8964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 9064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown private final class LocalDisplayDevice extends DisplayDevice { 914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final int mBuiltInDisplayId; 924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private final PhysicalDisplayInfo mPhys; 9364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private DisplayDeviceInfo mInfo; 954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown private boolean mHavePendingChanges; 969e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown private boolean mBlanked; 974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId, 994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown PhysicalDisplayInfo phys) { 100bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown super(LocalDisplayAdapter.this, displayToken); 1014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mBuiltInDisplayId = builtInDisplayId; 1024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mPhys = new PhysicalDisplayInfo(phys); 1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) { 1064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (!mPhys.equals(phys)) { 1074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mPhys.copyFrom(phys); 1084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mHavePendingChanges = true; 1094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return true; 1104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return false; 11264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 11364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown 11464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown @Override 1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void applyPendingDisplayDeviceInfoChangesLocked() { 1164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mHavePendingChanges) { 1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo = null; 1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mHavePendingChanges = false; 119bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown } 12064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown @Override 1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mInfo == null) { 1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo = new DisplayDeviceInfo(); 1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.width = mPhys.width; 1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.height = mPhys.height; 1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.refreshRate = mPhys.refreshRate; 12977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown 130f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown // Assume that all built-in displays that have secure output (eg. HDCP) also 13177aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown // support compositing from gralloc protected buffers. 132f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (mPhys.secure) { 133f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown mInfo.flags = DisplayDeviceInfo.FLAG_SECURE 134f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 135f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 13677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown 1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) { 1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.name = getContext().getResources().getString( 1394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown com.android.internal.R.string.display_manager_built_in_display_name); 14077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY 14127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.xDpi = mPhys.xDpi; 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.yDpi = mPhys.yDpi; 145d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; 1464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } else { 1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown mInfo.name = getContext().getResources().getString( 1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown com.android.internal.R.string.display_manager_hdmi_display_name); 149d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); 15127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown 15227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown // For demonstration purposes, allow rotation of the external display. 15327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown // In the future we might allow the user to configure this directly. 15427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 15527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown mInfo.rotation = Surface.ROTATION_270; 15627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown } 1574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown return mInfo; 1604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 1614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown 1624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown @Override 1639e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown public void blankLocked() { 1649e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown mBlanked = true; 1659e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown Surface.blankDisplay(getDisplayTokenLocked()); 1669e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown } 1679e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown 1689e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown @Override 1699e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown public void unblankLocked() { 1709e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown mBlanked = false; 1719e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown Surface.unblankDisplay(getDisplayTokenLocked()); 1729e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown } 1739e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown 1749e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown @Override 1754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown public void dumpLocked(PrintWriter pw) { 1764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown super.dumpLocked(pw); 1774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId); 1784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown pw.println("mPhys=" + mPhys); 1799e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown pw.println("mBlanked=" + mBlanked); 1804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown } 18164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown } 182e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown 183e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown private final class HotplugDisplayEventReceiver extends DisplayEventReceiver { 184e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown public HotplugDisplayEventReceiver(Looper looper) { 185e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown super(looper); 186e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 187e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown 188e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown @Override 189e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) { 190e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown synchronized (getSyncRoot()) { 191e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown scanDisplaysLocked(); 192e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 193e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 194e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown } 195e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown}