blob: 7f43e43dd8a97ed1d0ddf21e5d1ecee722030518 [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;
Dan Stoza00101052014-05-02 15:23:40 -070024import android.util.Slog;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070025import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070026import android.view.Display;
Jeff Browne87bf032012-09-20 18:30:13 -070027import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070028import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080029import android.view.SurfaceControl;
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
Jeff Brown66692502012-10-18 16:13:44 -070051 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070052 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
53 Context context, Handler handler, Listener listener) {
54 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070055 }
56
57 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070058 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070059 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070060
61 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080062
63 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
64 tryConnectDisplayLocked(builtInDisplayId);
65 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070066 }
67
Jesse Halle244db42012-11-08 11:55:14 -080068 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080069 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070070 if (displayToken != null) {
71 SurfaceControl.PhysicalDisplayInfo[] configs =
72 SurfaceControl.getDisplayConfigs(displayToken);
73 if (configs == null) {
74 // There are no valid configs for this device, so we can't use it
75 Slog.w(TAG, "No valid configs found for display device " +
76 builtInDisplayId);
77 return;
78 }
79 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
80 if (activeConfig < 0) {
81 // There is no active config, and for now we don't have the
82 // policy to set one.
83 Slog.w(TAG, "No active config found for display device " +
84 builtInDisplayId);
85 return;
86 }
Jesse Halle244db42012-11-08 11:55:14 -080087 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
88 if (device == null) {
89 // Display was added.
Dan Stoza00101052014-05-02 15:23:40 -070090 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
91 configs[activeConfig]);
Jesse Halle244db42012-11-08 11:55:14 -080092 mDevices.put(builtInDisplayId, device);
93 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Dan Stoza00101052014-05-02 15:23:40 -070094 } else if (device.updatePhysicalDisplayInfoLocked(configs[activeConfig])) {
Jesse Halle244db42012-11-08 11:55:14 -080095 // Display properties changed.
96 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -070097 }
Jesse Halle244db42012-11-08 11:55:14 -080098 } else {
99 // The display is no longer available. Ignore the attempt to add it.
100 // If it was connected but has already been disconnected, we'll get a
101 // disconnect event that will remove it from mDevices.
102 }
103 }
104
105 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
106 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
107 if (device != null) {
108 // Display was removed.
109 mDevices.remove(builtInDisplayId);
110 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700111 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700112 }
113
Jeff Brown44b1f762014-04-22 18:07:24 -0700114 static boolean shouldBlank(int state) {
115 return state == Display.STATE_OFF;
116 }
117
118 static boolean shouldUnblank(int state) {
119 return state == Display.STATE_ON || state == Display.STATE_DOZING;
120 }
121
Jeff Brown64a55af2012-08-26 02:47:39 -0700122 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700123 private final int mBuiltInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800124 private final SurfaceControl.PhysicalDisplayInfo mPhys;
Jeff Brown64a55af2012-08-26 02:47:39 -0700125
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700126 private DisplayDeviceInfo mInfo;
127 private boolean mHavePendingChanges;
Jeff Brown037c33e2014-04-09 00:31:55 -0700128 private int mState = Display.STATE_UNKNOWN;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700129
130 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800131 SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700132 super(LocalDisplayAdapter.this, displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700133 mBuiltInDisplayId = builtInDisplayId;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800134 mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700135 }
136
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800137 public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700138 if (!mPhys.equals(phys)) {
139 mPhys.copyFrom(phys);
140 mHavePendingChanges = true;
141 return true;
142 }
143 return false;
Jeff Brown64a55af2012-08-26 02:47:39 -0700144 }
145
146 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700147 public void applyPendingDisplayDeviceInfoChangesLocked() {
148 if (mHavePendingChanges) {
149 mInfo = null;
150 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700151 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700152 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700153
154 @Override
155 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
156 if (mInfo == null) {
157 mInfo = new DisplayDeviceInfo();
158 mInfo.width = mPhys.width;
159 mInfo.height = mPhys.height;
160 mInfo.refreshRate = mPhys.refreshRate;
Jeff Brown037c33e2014-04-09 00:31:55 -0700161 mInfo.state = mState;
Jeff Brown77aebfd2012-10-01 21:07:03 -0700162
Jeff Brownf0681b32012-10-23 17:35:57 -0700163 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700164 // support compositing from gralloc protected buffers.
Jeff Brownf0681b32012-10-23 17:35:57 -0700165 if (mPhys.secure) {
166 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
167 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
168 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700169
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800170 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700171 mInfo.name = getContext().getResources().getString(
172 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700173 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700174 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Jeff Brown92130f62012-10-24 21:28:33 -0700175 mInfo.type = Display.TYPE_BUILT_IN;
Jeff Browncbad9762012-09-04 21:57:59 -0700176 mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
177 mInfo.xDpi = mPhys.xDpi;
178 mInfo.yDpi = mPhys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700179 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700180 } else {
Jeff Brown92130f62012-10-24 21:28:33 -0700181 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700182 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700183 mInfo.name = getContext().getResources().getString(
184 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700185 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
Jeff Browncbad9762012-09-04 21:57:59 -0700186 mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700187
188 // For demonstration purposes, allow rotation of the external display.
189 // In the future we might allow the user to configure this directly.
190 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
191 mInfo.rotation = Surface.ROTATION_270;
192 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700193
194 // For demonstration purposes, allow rotation of the external display
195 // to follow the built-in display.
196 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
197 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
198 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700199 }
200 }
201 return mInfo;
202 }
203
204 @Override
Jeff Brown037c33e2014-04-09 00:31:55 -0700205 public void requestDisplayStateLocked(int state) {
206 if (mState != state) {
Jeff Brown44b1f762014-04-22 18:07:24 -0700207 if (shouldBlank(state) && !shouldBlank(mState)) {
Jeff Brown037c33e2014-04-09 00:31:55 -0700208 SurfaceControl.blankDisplay(getDisplayTokenLocked());
Jeff Brown44b1f762014-04-22 18:07:24 -0700209 } else if (shouldUnblank(state) && !shouldUnblank(mState)) {
Jeff Brown037c33e2014-04-09 00:31:55 -0700210 SurfaceControl.unblankDisplay(getDisplayTokenLocked());
211 }
212 mState = state;
213 updateDeviceInfoLocked();
214 }
Jeff Brown9e316a12012-10-08 19:17:06 -0700215 }
216
217 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700218 public void dumpLocked(PrintWriter pw) {
219 super.dumpLocked(pw);
220 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
221 pw.println("mPhys=" + mPhys);
Jeff Brown037c33e2014-04-09 00:31:55 -0700222 pw.println("mState=" + Display.stateToString(mState));
223 }
224
225 private void updateDeviceInfoLocked() {
226 mInfo = null;
227 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700228 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700229 }
Jeff Browne87bf032012-09-20 18:30:13 -0700230
231 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
232 public HotplugDisplayEventReceiver(Looper looper) {
233 super(looper);
234 }
235
236 @Override
237 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
238 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800239 if (connected) {
240 tryConnectDisplayLocked(builtInDisplayId);
241 } else {
242 tryDisconnectDisplayLocked(builtInDisplayId);
243 }
Jeff Browne87bf032012-09-20 18:30:13 -0700244 }
245 }
246 }
Dan Stoza00101052014-05-02 15:23:40 -0700247}