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}