blob: 02be477fc18fa4a55c00217983e8c8f01fe2ff17 [file] [log] [blame]
Jeff Brown64a55af2012-08-26 02:47:39 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.display;
18
19import android.content.Context;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070020import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070021import android.os.IBinder;
Jeff Browne87bf032012-09-20 18:30:13 -070022import android.os.Looper;
Jeff Brown27f1d672012-10-17 18:32:34 -070023import android.os.SystemProperties;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070024import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070025import android.view.Display;
Jeff Browne87bf032012-09-20 18:30:13 -070026import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070027import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080028import android.view.SurfaceControl;
Jeff Brown64a55af2012-08-26 02:47:39 -070029
Jeff Brown4ed8fe72012-08-30 18:18:29 -070030import java.io.PrintWriter;
31
Jeff Brown64a55af2012-08-26 02:47:39 -070032/**
33 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070034 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070035 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070036 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070037 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070038final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070039 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown64a55af2012-08-26 02:47:39 -070040
Jeff Brown4ed8fe72012-08-30 18:18:29 -070041 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080042 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
43 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070044 };
45
46 private final SparseArray<LocalDisplayDevice> mDevices =
47 new SparseArray<LocalDisplayDevice>();
Jeff Brown66692502012-10-18 16:13:44 -070048 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070049
Mathias Agopian3866f0d2013-02-11 22:08:48 -080050 private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
Jeff Brown4ed8fe72012-08-30 18:18:29 -070051
Jeff Brown66692502012-10-18 16:13:44 -070052 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070053 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
54 Context context, Handler handler, Listener listener) {
55 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070056 }
57
58 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070059 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070060 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070061
62 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080063
64 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
65 tryConnectDisplayLocked(builtInDisplayId);
66 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070067 }
68
Jesse Halle244db42012-11-08 11:55:14 -080069 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080070 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
71 if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
Jesse Halle244db42012-11-08 11:55:14 -080072 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
73 if (device == null) {
74 // Display was added.
75 device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
76 mDevices.put(builtInDisplayId, device);
77 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
78 } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
79 // Display properties changed.
80 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -070081 }
Jesse Halle244db42012-11-08 11:55:14 -080082 } else {
83 // The display is no longer available. Ignore the attempt to add it.
84 // If it was connected but has already been disconnected, we'll get a
85 // disconnect event that will remove it from mDevices.
86 }
87 }
88
89 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
90 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
91 if (device != null) {
92 // Display was removed.
93 mDevices.remove(builtInDisplayId);
94 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -070095 }
Jeff Brown64a55af2012-08-26 02:47:39 -070096 }
97
98 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070099 private final int mBuiltInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800100 private final SurfaceControl.PhysicalDisplayInfo mPhys;
Jeff Brown64a55af2012-08-26 02:47:39 -0700101
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700102 private DisplayDeviceInfo mInfo;
103 private boolean mHavePendingChanges;
Jeff Brown9e316a12012-10-08 19:17:06 -0700104 private boolean mBlanked;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700105
106 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800107 SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700108 super(LocalDisplayAdapter.this, displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700109 mBuiltInDisplayId = builtInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800110 mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700111 }
112
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800113 public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700114 if (!mPhys.equals(phys)) {
115 mPhys.copyFrom(phys);
116 mHavePendingChanges = true;
117 return true;
118 }
119 return false;
Jeff Brown64a55af2012-08-26 02:47:39 -0700120 }
121
122 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700123 public void applyPendingDisplayDeviceInfoChangesLocked() {
124 if (mHavePendingChanges) {
125 mInfo = null;
126 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700127 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700128 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700129
130 @Override
131 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
132 if (mInfo == null) {
133 mInfo = new DisplayDeviceInfo();
134 mInfo.width = mPhys.width;
135 mInfo.height = mPhys.height;
136 mInfo.refreshRate = mPhys.refreshRate;
Jeff Brown77aebfd2012-10-01 21:07:03 -0700137
Jeff Brownf0681b32012-10-23 17:35:57 -0700138 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700139 // support compositing from gralloc protected buffers.
Jeff Brownf0681b32012-10-23 17:35:57 -0700140 if (mPhys.secure) {
141 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
142 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
143 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700144
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800145 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700146 mInfo.name = getContext().getResources().getString(
147 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700148 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700149 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Jeff Brown92130f62012-10-24 21:28:33 -0700150 mInfo.type = Display.TYPE_BUILT_IN;
Jeff Browncbad9762012-09-04 21:57:59 -0700151 mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
152 mInfo.xDpi = mPhys.xDpi;
153 mInfo.yDpi = mPhys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700154 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700155 } else {
Jeff Brown92130f62012-10-24 21:28:33 -0700156 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700157 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700158 mInfo.name = getContext().getResources().getString(
159 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700160 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
Jeff Browncbad9762012-09-04 21:57:59 -0700161 mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700162
163 // For demonstration purposes, allow rotation of the external display.
164 // In the future we might allow the user to configure this directly.
165 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
166 mInfo.rotation = Surface.ROTATION_270;
167 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700168
169 // For demonstration purposes, allow rotation of the external display
170 // to follow the built-in display.
171 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
172 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
173 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700174 }
175 }
176 return mInfo;
177 }
178
179 @Override
Jeff Brown9e316a12012-10-08 19:17:06 -0700180 public void blankLocked() {
181 mBlanked = true;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800182 SurfaceControl.blankDisplay(getDisplayTokenLocked());
Jeff Brown9e316a12012-10-08 19:17:06 -0700183 }
184
185 @Override
186 public void unblankLocked() {
187 mBlanked = false;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800188 SurfaceControl.unblankDisplay(getDisplayTokenLocked());
Jeff Brown9e316a12012-10-08 19:17:06 -0700189 }
190
191 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700192 public void dumpLocked(PrintWriter pw) {
193 super.dumpLocked(pw);
194 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
195 pw.println("mPhys=" + mPhys);
Jeff Brown9e316a12012-10-08 19:17:06 -0700196 pw.println("mBlanked=" + mBlanked);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700197 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700198 }
Jeff Browne87bf032012-09-20 18:30:13 -0700199
200 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
201 public HotplugDisplayEventReceiver(Looper looper) {
202 super(looper);
203 }
204
205 @Override
206 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
207 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800208 if (connected) {
209 tryConnectDisplayLocked(builtInDisplayId);
210 } else {
211 tryDisconnectDisplayLocked(builtInDisplayId);
212 }
Jeff Browne87bf032012-09-20 18:30:13 -0700213 }
214 }
215 }
216}