blob: cb8f3e20d3683940dea58c847a859f76ef42b101 [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;
29import android.view.SurfaceControl.PhysicalDisplayInfo;
Jeff Brown64a55af2012-08-26 02:47:39 -070030
Jeff Brown4ed8fe72012-08-30 18:18:29 -070031import java.io.PrintWriter;
32
Jeff Brown64a55af2012-08-26 02:47:39 -070033/**
34 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070035 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070036 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070037 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070038 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070039final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070040 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown64a55af2012-08-26 02:47:39 -070041
Jeff Brown4ed8fe72012-08-30 18:18:29 -070042 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080043 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
44 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070045 };
46
47 private final SparseArray<LocalDisplayDevice> mDevices =
48 new SparseArray<LocalDisplayDevice>();
Jeff Brown66692502012-10-18 16:13:44 -070049 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070050
Mathias Agopian3866f0d2013-02-11 22:08:48 -080051 private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
Jeff Brown4ed8fe72012-08-30 18:18:29 -070052
Jeff Brown66692502012-10-18 16:13:44 -070053 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070054 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
55 Context context, Handler handler, Listener listener) {
56 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070057 }
58
59 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070060 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070061 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070062
63 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080064
65 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
66 tryConnectDisplayLocked(builtInDisplayId);
67 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070068 }
69
Jesse Halle244db42012-11-08 11:55:14 -080070 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080071 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
72 if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
Jesse Halle244db42012-11-08 11:55:14 -080073 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
74 if (device == null) {
75 // Display was added.
76 device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
77 mDevices.put(builtInDisplayId, device);
78 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
79 } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
80 // Display properties changed.
81 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -070082 }
Jesse Halle244db42012-11-08 11:55:14 -080083 } else {
84 // The display is no longer available. Ignore the attempt to add it.
85 // If it was connected but has already been disconnected, we'll get a
86 // disconnect event that will remove it from mDevices.
87 }
88 }
89
90 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
91 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
92 if (device != null) {
93 // Display was removed.
94 mDevices.remove(builtInDisplayId);
95 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -070096 }
Jeff Brown64a55af2012-08-26 02:47:39 -070097 }
98
99 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700100 private final int mBuiltInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800101 private final SurfaceControl.PhysicalDisplayInfo mPhys;
Jeff Brown64a55af2012-08-26 02:47:39 -0700102
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700103 private DisplayDeviceInfo mInfo;
104 private boolean mHavePendingChanges;
Jeff Brown9e316a12012-10-08 19:17:06 -0700105 private boolean mBlanked;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700106
107 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800108 SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700109 super(LocalDisplayAdapter.this, displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700110 mBuiltInDisplayId = builtInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800111 mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700112 }
113
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800114 public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700115 if (!mPhys.equals(phys)) {
116 mPhys.copyFrom(phys);
117 mHavePendingChanges = true;
118 return true;
119 }
120 return false;
Jeff Brown64a55af2012-08-26 02:47:39 -0700121 }
122
123 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700124 public void applyPendingDisplayDeviceInfoChangesLocked() {
125 if (mHavePendingChanges) {
126 mInfo = null;
127 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700128 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700129 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700130
131 @Override
132 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
133 if (mInfo == null) {
134 mInfo = new DisplayDeviceInfo();
135 mInfo.width = mPhys.width;
136 mInfo.height = mPhys.height;
137 mInfo.refreshRate = mPhys.refreshRate;
Jeff Brown77aebfd2012-10-01 21:07:03 -0700138
Jeff Brownf0681b32012-10-23 17:35:57 -0700139 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700140 // support compositing from gralloc protected buffers.
Jeff Brownf0681b32012-10-23 17:35:57 -0700141 if (mPhys.secure) {
142 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
143 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
144 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700145
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800146 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700147 mInfo.name = getContext().getResources().getString(
148 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700149 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700150 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Jeff Brown92130f62012-10-24 21:28:33 -0700151 mInfo.type = Display.TYPE_BUILT_IN;
Jeff Browncbad9762012-09-04 21:57:59 -0700152 mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
153 mInfo.xDpi = mPhys.xDpi;
154 mInfo.yDpi = mPhys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700155 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700156 } else {
Jeff Brown92130f62012-10-24 21:28:33 -0700157 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700158 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700159 mInfo.name = getContext().getResources().getString(
160 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700161 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
Jeff Browncbad9762012-09-04 21:57:59 -0700162 mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700163
164 // For demonstration purposes, allow rotation of the external display.
165 // In the future we might allow the user to configure this directly.
166 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
167 mInfo.rotation = Surface.ROTATION_270;
168 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700169 }
170 }
171 return mInfo;
172 }
173
174 @Override
Jeff Brown9e316a12012-10-08 19:17:06 -0700175 public void blankLocked() {
176 mBlanked = true;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800177 SurfaceControl.blankDisplay(getDisplayTokenLocked());
Jeff Brown9e316a12012-10-08 19:17:06 -0700178 }
179
180 @Override
181 public void unblankLocked() {
182 mBlanked = false;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800183 SurfaceControl.unblankDisplay(getDisplayTokenLocked());
Jeff Brown9e316a12012-10-08 19:17:06 -0700184 }
185
186 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700187 public void dumpLocked(PrintWriter pw) {
188 super.dumpLocked(pw);
189 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
190 pw.println("mPhys=" + mPhys);
Jeff Brown9e316a12012-10-08 19:17:06 -0700191 pw.println("mBlanked=" + mBlanked);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700192 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700193 }
Jeff Browne87bf032012-09-20 18:30:13 -0700194
195 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
196 public HotplugDisplayEventReceiver(Looper looper) {
197 super(looper);
198 }
199
200 @Override
201 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
202 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800203 if (connected) {
204 tryConnectDisplayLocked(builtInDisplayId);
205 } else {
206 tryDisconnectDisplayLocked(builtInDisplayId);
207 }
Jeff Browne87bf032012-09-20 18:30:13 -0700208 }
209 }
210 }
211}