blob: 7b16ea61eb74577452bb9eb3f24a6d6ff6987e98 [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
Adam Powell49e7ff92015-05-14 16:18:53 -070019import android.content.res.Resources;
Jeff Brown5d6443b2015-04-10 20:15:01 -070020import com.android.server.LocalServices;
21import com.android.server.lights.Light;
22import com.android.server.lights.LightsManager;
23
Jeff Brown64a55af2012-08-26 02:47:39 -070024import android.content.Context;
Griff Hazend3c454d2016-03-25 07:30:34 -070025import android.os.Build;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070026import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070027import android.os.IBinder;
Jeff Browne87bf032012-09-20 18:30:13 -070028import android.os.Looper;
Jeff Brown5d6443b2015-04-10 20:15:01 -070029import android.os.PowerManager;
Jeff Brown27f1d672012-10-17 18:32:34 -070030import android.os.SystemProperties;
Jeff Brown3edf5272014-08-14 19:25:14 -070031import android.os.Trace;
Dan Stoza00101052014-05-02 15:23:40 -070032import android.util.Slog;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070033import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070034import android.view.Display;
Jeff Browne87bf032012-09-20 18:30:13 -070035import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070036import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080037import android.view.SurfaceControl;
Jeff Brown64a55af2012-08-26 02:47:39 -070038
Jeff Brown4ed8fe72012-08-30 18:18:29 -070039import java.io.PrintWriter;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070040import java.util.ArrayList;
Michael Wright58e829f2015-09-15 00:13:26 +010041import java.util.Arrays;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070042
Jeff Brown64a55af2012-08-26 02:47:39 -070043/**
44 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070045 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070046 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070047 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070048 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070049final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070050 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown5d6443b2015-04-10 20:15:01 -070051 private static final boolean DEBUG = false;
Jeff Brown64a55af2012-08-26 02:47:39 -070052
Wale Ogunwale361ca212014-11-20 11:42:38 -080053 private static final String UNIQUE_ID_PREFIX = "local:";
54
Adam Powell01f280d2015-05-18 16:07:42 -070055 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
56
Jeff Brown4ed8fe72012-08-30 18:18:29 -070057 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080058 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
59 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070060 };
61
62 private final SparseArray<LocalDisplayDevice> mDevices =
63 new SparseArray<LocalDisplayDevice>();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070064 @SuppressWarnings("unused") // Becomes active at instantiation time.
Jeff Brown66692502012-10-18 16:13:44 -070065 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070066
Jeff Brown66692502012-10-18 16:13:44 -070067 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070068 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
69 Context context, Handler handler, Listener listener) {
70 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070071 }
72
73 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070074 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070075 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070076
77 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080078
79 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
80 tryConnectDisplayLocked(builtInDisplayId);
81 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070082 }
83
Jesse Halle244db42012-11-08 11:55:14 -080084 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080085 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070086 if (displayToken != null) {
87 SurfaceControl.PhysicalDisplayInfo[] configs =
88 SurfaceControl.getDisplayConfigs(displayToken);
89 if (configs == null) {
90 // There are no valid configs for this device, so we can't use it
91 Slog.w(TAG, "No valid configs found for display device " +
92 builtInDisplayId);
93 return;
94 }
95 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
96 if (activeConfig < 0) {
97 // There is no active config, and for now we don't have the
98 // policy to set one.
99 Slog.w(TAG, "No active config found for display device " +
100 builtInDisplayId);
101 return;
102 }
Jesse Halle244db42012-11-08 11:55:14 -0800103 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
104 if (device == null) {
105 // Display was added.
Dan Stoza00101052014-05-02 15:23:40 -0700106 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
Michael Wright3f145a22014-07-22 19:46:03 -0700107 configs, activeConfig);
Jesse Halle244db42012-11-08 11:55:14 -0800108 mDevices.put(builtInDisplayId, device);
109 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Michael Wright3f145a22014-07-22 19:46:03 -0700110 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig)) {
Jesse Halle244db42012-11-08 11:55:14 -0800111 // Display properties changed.
112 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700113 }
Jesse Halle244db42012-11-08 11:55:14 -0800114 } else {
115 // The display is no longer available. Ignore the attempt to add it.
116 // If it was connected but has already been disconnected, we'll get a
117 // disconnect event that will remove it from mDevices.
118 }
119 }
120
121 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
122 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
123 if (device != null) {
124 // Display was removed.
125 mDevices.remove(builtInDisplayId);
126 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700127 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700128 }
129
Prashant Malanic55929a2014-05-25 01:59:21 -0700130 static int getPowerModeForState(int state) {
131 switch (state) {
132 case Display.STATE_OFF:
133 return SurfaceControl.POWER_MODE_OFF;
Jeff Brown5dc21912014-07-17 18:50:18 -0700134 case Display.STATE_DOZE:
Prashant Malanic55929a2014-05-25 01:59:21 -0700135 return SurfaceControl.POWER_MODE_DOZE;
Jeff Brown5dc21912014-07-17 18:50:18 -0700136 case Display.STATE_DOZE_SUSPEND:
137 return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
Prashant Malanic55929a2014-05-25 01:59:21 -0700138 default:
139 return SurfaceControl.POWER_MODE_NORMAL;
140 }
Jeff Brown44b1f762014-04-22 18:07:24 -0700141 }
142
Jeff Brown64a55af2012-08-26 02:47:39 -0700143 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700144 private final int mBuiltInDisplayId;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700145 private final Light mBacklight;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700146 private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
Michael Wright58e829f2015-09-15 00:13:26 +0100147 private final SparseArray<Display.ColorTransform> mSupportedColorTransforms =
148 new SparseArray<>();
Jeff Brown64a55af2012-08-26 02:47:39 -0700149
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700150 private DisplayDeviceInfo mInfo;
151 private boolean mHavePendingChanges;
Jeff Brown037c33e2014-04-09 00:31:55 -0700152 private int mState = Display.STATE_UNKNOWN;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700153 private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Michael Wright58e829f2015-09-15 00:13:26 +0100154 private int mActivePhysIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700155 private int mDefaultModeId;
156 private int mActiveModeId;
157 private boolean mActiveModeInvalid;
Michael Wright58e829f2015-09-15 00:13:26 +0100158 private int mDefaultColorTransformId;
159 private int mActiveColorTransformId;
160 private boolean mActiveColorTransformInvalid;
Michael Wright9ff94c02016-03-30 18:05:40 -0700161 private Display.HdrCapabilities mHdrCapabilities;
Michael Wright58e829f2015-09-15 00:13:26 +0100162
163 private SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
Jeff Brown5d6443b2015-04-10 20:15:01 -0700164
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700165 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Michael Wright3f145a22014-07-22 19:46:03 -0700166 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800167 super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700168 mBuiltInDisplayId = builtInDisplayId;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700169 updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700170 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
171 LightsManager lights = LocalServices.getService(LightsManager.class);
172 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
173 } else {
174 mBacklight = null;
175 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700176 mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700177 }
178
Michael Wright3f145a22014-07-22 19:46:03 -0700179 public boolean updatePhysicalDisplayInfoLocked(
180 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo) {
Michael Wright58e829f2015-09-15 00:13:26 +0100181 mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
182 mActivePhysIndex = activeDisplayInfo;
183 ArrayList<Display.ColorTransform> colorTransforms = new ArrayList<>();
184
185 // Build an updated list of all existing color transforms.
186 boolean colorTransformsAdded = false;
187 Display.ColorTransform activeColorTransform = null;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700188 for (int i = 0; i < physicalDisplayInfos.length; i++) {
189 SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
Michael Wright58e829f2015-09-15 00:13:26 +0100190 // First check to see if we've already added this color transform
191 boolean existingMode = false;
192 for (int j = 0; j < colorTransforms.size(); j++) {
193 if (colorTransforms.get(j).getColorTransform() == info.colorTransform) {
194 existingMode = true;
195 break;
196 }
197 }
198 if (existingMode) {
199 continue;
200 }
201 Display.ColorTransform colorTransform = findColorTransform(info);
202 if (colorTransform == null) {
203 colorTransform = createColorTransform(info.colorTransform);
204 colorTransformsAdded = true;
205 }
206 colorTransforms.add(colorTransform);
207 if (i == activeDisplayInfo) {
208 activeColorTransform = colorTransform;
209 }
210 }
211
212 // Build an updated list of all existing modes.
213 ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
214 boolean modesAdded = false;
215 for (int i = 0; i < physicalDisplayInfos.length; i++) {
216 SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
217 // First, check to see if we've already added a matching mode. Since not all
218 // configuration options are exposed via Display.Mode, it's possible that we have
219 // multiple PhysicalDisplayInfos that would generate the same Display.Mode.
220 boolean existingMode = false;
221 for (int j = 0; j < records.size(); j++) {
222 if (records.get(j).hasMatchingMode(info)) {
223 existingMode = true;
224 break;
225 }
226 }
227 if (existingMode) {
228 continue;
229 }
230 // If we haven't already added a mode for this configuration to the new set of
231 // supported modes then check to see if we have one in the prior set of supported
232 // modes to reuse.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700233 DisplayModeRecord record = findDisplayModeRecord(info);
Michael Wright58e829f2015-09-15 00:13:26 +0100234 if (record == null) {
235 record = new DisplayModeRecord(info);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700236 modesAdded = true;
237 }
238 records.add(record);
Michael Wright58e829f2015-09-15 00:13:26 +0100239 }
240
241 // Get the currently active mode
242 DisplayModeRecord activeRecord = null;
243 for (int i = 0; i < records.size(); i++) {
244 DisplayModeRecord record = records.get(i);
245 if (record.hasMatchingMode(physicalDisplayInfos[activeDisplayInfo])){
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700246 activeRecord = record;
Michael Wright58e829f2015-09-15 00:13:26 +0100247 break;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700248 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700249 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700250 // Check whether surface flinger spontaneously changed modes out from under us. Schedule
251 // traversals to ensure that the correct state is reapplied if necessary.
252 if (mActiveModeId != 0
253 && mActiveModeId != activeRecord.mMode.getModeId()) {
254 mActiveModeInvalid = true;
255 sendTraversalRequestLocked();
256 }
Michael Wright58e829f2015-09-15 00:13:26 +0100257 // Check whether surface flinger spontaneously changed color transforms out from under
258 // us.
259 if (mActiveColorTransformId != 0
260 && mActiveColorTransformId != activeColorTransform.getId()) {
261 mActiveColorTransformInvalid = true;
262 sendTraversalRequestLocked();
263 }
264
265 boolean colorTransformsChanged =
266 colorTransforms.size() != mSupportedColorTransforms.size()
267 || colorTransformsAdded;
268 boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
269 // If neither the records nor the supported color transforms have changed then we're
270 // done here.
271 if (!recordsChanged && !colorTransformsChanged) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700272 return false;
273 }
274 // Update the index of modes.
275 mHavePendingChanges = true;
Michael Wright58e829f2015-09-15 00:13:26 +0100276
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700277 mSupportedModes.clear();
278 for (DisplayModeRecord record : records) {
279 mSupportedModes.put(record.mMode.getModeId(), record);
280 }
Michael Wright58e829f2015-09-15 00:13:26 +0100281 mSupportedColorTransforms.clear();
282 for (Display.ColorTransform colorTransform : colorTransforms) {
283 mSupportedColorTransforms.put(colorTransform.getId(), colorTransform);
284 }
285
286 // Update the default mode and color transform if needed. This needs to be done in
287 // tandem so we always have a default state to fall back to.
288 if (findDisplayInfoIndexLocked(mDefaultColorTransformId, mDefaultModeId) < 0) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700289 if (mDefaultModeId != 0) {
Michael Wright58e829f2015-09-15 00:13:26 +0100290 Slog.w(TAG, "Default display mode no longer available, using currently"
291 + " active mode as default.");
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700292 }
293 mDefaultModeId = activeRecord.mMode.getModeId();
Michael Wright58e829f2015-09-15 00:13:26 +0100294 if (mDefaultColorTransformId != 0) {
295 Slog.w(TAG, "Default color transform no longer available, using currently"
296 + " active color transform as default");
297 }
298 mDefaultColorTransformId = activeColorTransform.getId();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700299 }
300 // Determine whether the active mode is still there.
301 if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
302 if (mActiveModeId != 0) {
303 Slog.w(TAG, "Active display mode no longer available, reverting to default"
304 + " mode.");
305 }
306 mActiveModeId = mDefaultModeId;
307 mActiveModeInvalid = true;
308 }
Michael Wright58e829f2015-09-15 00:13:26 +0100309
310 // Determine whether the active color transform is still there.
311 if (mSupportedColorTransforms.indexOfKey(mActiveColorTransformId) < 0) {
312 if (mActiveColorTransformId != 0) {
313 Slog.w(TAG, "Active color transform no longer available, reverting"
314 + " to default transform.");
315 }
316 mActiveColorTransformId = mDefaultColorTransformId;
317 mActiveColorTransformInvalid = true;
318 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700319 // Schedule traversals so that we apply pending changes.
320 sendTraversalRequestLocked();
321 return true;
322 }
323
324 private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
325 for (int i = 0; i < mSupportedModes.size(); i++) {
326 DisplayModeRecord record = mSupportedModes.valueAt(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100327 if (record.hasMatchingMode(info)) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700328 return record;
329 }
330 }
331 return null;
Jeff Brown64a55af2012-08-26 02:47:39 -0700332 }
333
Michael Wright58e829f2015-09-15 00:13:26 +0100334 private Display.ColorTransform findColorTransform(SurfaceControl.PhysicalDisplayInfo info) {
335 for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
336 Display.ColorTransform transform = mSupportedColorTransforms.valueAt(i);
337 if (transform.getColorTransform() == info.colorTransform) {
338 return transform;
339 }
340 }
341 return null;
342 }
343
Jeff Brown64a55af2012-08-26 02:47:39 -0700344 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700345 public void applyPendingDisplayDeviceInfoChangesLocked() {
346 if (mHavePendingChanges) {
347 mInfo = null;
348 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700349 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700350 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700351
352 @Override
353 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
354 if (mInfo == null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100355 SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700356 mInfo = new DisplayDeviceInfo();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700357 mInfo.width = phys.width;
358 mInfo.height = phys.height;
359 mInfo.modeId = mActiveModeId;
360 mInfo.defaultModeId = mDefaultModeId;
361 mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
362 for (int i = 0; i < mSupportedModes.size(); i++) {
363 DisplayModeRecord record = mSupportedModes.valueAt(i);
364 mInfo.supportedModes[i] = record.mMode;
365 }
Michael Wright58e829f2015-09-15 00:13:26 +0100366 mInfo.colorTransformId = mActiveColorTransformId;
367 mInfo.defaultColorTransformId = mDefaultColorTransformId;
368 mInfo.supportedColorTransforms =
369 new Display.ColorTransform[mSupportedColorTransforms.size()];
370 for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
371 mInfo.supportedColorTransforms[i] = mSupportedColorTransforms.valueAt(i);
372 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700373 mInfo.hdrCapabilities = mHdrCapabilities;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700374 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
375 mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
Jeff Brown037c33e2014-04-09 00:31:55 -0700376 mInfo.state = mState;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800377 mInfo.uniqueId = getUniqueId();
Jeff Brown77aebfd2012-10-01 21:07:03 -0700378
Jeff Brownf0681b32012-10-23 17:35:57 -0700379 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700380 // support compositing from gralloc protected buffers.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700381 if (phys.secure) {
Jeff Brownf0681b32012-10-23 17:35:57 -0700382 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
383 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
384 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700385
Michael Wright4b0fa172016-03-11 17:15:24 -0800386 final Resources res = getContext().getResources();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800387 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700388 mInfo.name = res.getString(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700389 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700390 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700391 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Adam Powell01f280d2015-05-18 16:07:42 -0700392 if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
Griff Hazend3c454d2016-03-25 07:30:34 -0700393 || (Build.IS_EMULATOR
Adam Powell01f280d2015-05-18 16:07:42 -0700394 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700395 mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
396 }
Jeff Brown92130f62012-10-24 21:28:33 -0700397 mInfo.type = Display.TYPE_BUILT_IN;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700398 mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
399 mInfo.xDpi = phys.xDpi;
400 mInfo.yDpi = phys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700401 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700402 } else {
Jeff Brown92130f62012-10-24 21:28:33 -0700403 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700404 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700405 mInfo.name = getContext().getResources().getString(
406 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700407 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700408 mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700409
410 // For demonstration purposes, allow rotation of the external display.
411 // In the future we might allow the user to configure this directly.
412 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
413 mInfo.rotation = Surface.ROTATION_270;
414 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700415
416 // For demonstration purposes, allow rotation of the external display
417 // to follow the built-in display.
418 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
419 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
420 }
Michael Wright4b0fa172016-03-11 17:15:24 -0800421
422 if (!res.getBoolean(
423 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
424 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
425 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700426 }
427 }
428 return mInfo;
429 }
430
431 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700432 public Runnable requestDisplayStateLocked(final int state, final int brightness) {
433 // Assume that the brightness is off if the display is being turned off.
434 assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
435
436 final boolean stateChanged = (mState != state);
437 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
438 if (stateChanged || brightnessChanged) {
Jeff Browne75926d2014-09-18 15:24:49 -0700439 final int displayId = mBuiltInDisplayId;
440 final IBinder token = getDisplayTokenLocked();
Jeff Brown5d6443b2015-04-10 20:15:01 -0700441 final int oldState = mState;
Jeff Browne75926d2014-09-18 15:24:49 -0700442
Jeff Brown5d6443b2015-04-10 20:15:01 -0700443 if (stateChanged) {
444 mState = state;
445 updateDeviceInfoLocked();
446 }
447
448 if (brightnessChanged) {
449 mBrightness = brightness;
450 }
451
452 // Defer actually setting the display state until after we have exited
Jeff Browne75926d2014-09-18 15:24:49 -0700453 // the critical section since it can take hundreds of milliseconds
454 // to complete.
455 return new Runnable() {
456 @Override
457 public void run() {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700458 // Exit a suspended state before making any changes.
459 int currentState = oldState;
460 if (Display.isSuspendedState(oldState)
461 || oldState == Display.STATE_UNKNOWN) {
462 if (!Display.isSuspendedState(state)) {
463 setDisplayState(state);
464 currentState = state;
465 } else if (state == Display.STATE_DOZE_SUSPEND
466 || oldState == Display.STATE_DOZE_SUSPEND) {
467 setDisplayState(Display.STATE_DOZE);
468 currentState = Display.STATE_DOZE;
469 } else {
470 return; // old state and new state is off
471 }
472 }
473
474 // Apply brightness changes given that we are in a non-suspended state.
475 if (brightnessChanged) {
476 setDisplayBrightness(brightness);
477 }
478
479 // Enter the final desired state, possibly suspended.
480 if (state != currentState) {
481 setDisplayState(state);
482 }
483 }
484
485 private void setDisplayState(int state) {
486 if (DEBUG) {
487 Slog.d(TAG, "setDisplayState("
488 + "id=" + displayId
489 + ", state=" + Display.stateToString(state) + ")");
490 }
491
492 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
493 + "id=" + displayId
494 + ", state=" + Display.stateToString(state) + ")");
Jeff Browne75926d2014-09-18 15:24:49 -0700495 try {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700496 final int mode = getPowerModeForState(state);
Jeff Browne75926d2014-09-18 15:24:49 -0700497 SurfaceControl.setDisplayPowerMode(token, mode);
498 } finally {
499 Trace.traceEnd(Trace.TRACE_TAG_POWER);
500 }
501 }
Jeff Brown5d6443b2015-04-10 20:15:01 -0700502
503 private void setDisplayBrightness(int brightness) {
504 if (DEBUG) {
505 Slog.d(TAG, "setDisplayBrightness("
506 + "id=" + displayId + ", brightness=" + brightness + ")");
507 }
508
509 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
510 + "id=" + displayId + ", brightness=" + brightness + ")");
511 try {
512 mBacklight.setBrightness(brightness);
513 } finally {
514 Trace.traceEnd(Trace.TRACE_TAG_POWER);
515 }
516 }
Jeff Browne75926d2014-09-18 15:24:49 -0700517 };
Jeff Brown037c33e2014-04-09 00:31:55 -0700518 }
Jeff Browne75926d2014-09-18 15:24:49 -0700519 return null;
Jeff Brown9e316a12012-10-08 19:17:06 -0700520 }
521
522 @Override
Michael Wright58e829f2015-09-15 00:13:26 +0100523 public void requestColorTransformAndModeInTransactionLocked(
524 int colorTransformId, int modeId) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700525 if (modeId == 0) {
526 modeId = mDefaultModeId;
527 } else if (mSupportedModes.indexOfKey(modeId) < 0) {
528 Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
529 + " reverting to default display mode.");
530 modeId = mDefaultModeId;
531 }
Michael Wright58e829f2015-09-15 00:13:26 +0100532
533 if (colorTransformId == 0) {
534 colorTransformId = mDefaultColorTransformId;
535 } else if (mSupportedColorTransforms.indexOfKey(colorTransformId) < 0) {
536 Slog.w(TAG, "Requested color transform " + colorTransformId + " is not supported"
537 + " by this display, reverting to the default color transform");
538 colorTransformId = mDefaultColorTransformId;
539 }
540 int physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
541 if (physIndex < 0) {
542 Slog.w(TAG, "Requested color transform, mode ID pair (" + colorTransformId + ", "
543 + modeId + ") not available, trying color transform with default mode ID");
544 modeId = mDefaultModeId;
545 physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
546 if (physIndex < 0) {
547 Slog.w(TAG, "Requested color transform with default mode ID still not"
548 + " available, falling back to default color transform with default"
549 + " mode.");
550 colorTransformId = mDefaultColorTransformId;
551 physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
552 }
553 }
Jorim Jaggi3b3cbb52015-09-24 17:35:58 -0700554 if (mActivePhysIndex == physIndex) {
Michael Wright3f145a22014-07-22 19:46:03 -0700555 return;
556 }
Michael Wright58e829f2015-09-15 00:13:26 +0100557 SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
558 mActivePhysIndex = physIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700559 mActiveModeId = modeId;
560 mActiveModeInvalid = false;
Michael Wright58e829f2015-09-15 00:13:26 +0100561 mActiveColorTransformId = colorTransformId;
562 mActiveColorTransformInvalid = false;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700563 updateDeviceInfoLocked();
Michael Wright3f145a22014-07-22 19:46:03 -0700564 }
565
566 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700567 public void dumpLocked(PrintWriter pw) {
568 super.dumpLocked(pw);
569 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
Michael Wright58e829f2015-09-15 00:13:26 +0100570 pw.println("mActivePhysIndex=" + mActivePhysIndex);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700571 pw.println("mActiveModeId=" + mActiveModeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100572 pw.println("mActiveColorTransformId=" + mActiveColorTransformId);
Jeff Brown037c33e2014-04-09 00:31:55 -0700573 pw.println("mState=" + Display.stateToString(mState));
Jeff Brown5d6443b2015-04-10 20:15:01 -0700574 pw.println("mBrightness=" + mBrightness);
575 pw.println("mBacklight=" + mBacklight);
Michael Wright58e829f2015-09-15 00:13:26 +0100576 pw.println("mDisplayInfos=");
577 for (int i = 0; i < mDisplayInfos.length; i++) {
578 pw.println(" " + mDisplayInfos[i]);
579 }
580 pw.println("mSupportedModes=");
581 for (int i = 0; i < mSupportedModes.size(); i++) {
582 pw.println(" " + mSupportedModes.valueAt(i));
583 }
584 pw.println("mSupportedColorTransforms=[");
585 for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
586 if (i != 0) {
587 pw.print(", ");
588 }
589 pw.print(mSupportedColorTransforms.valueAt(i));
590 }
591 pw.println("]");
592 }
593
594 private int findDisplayInfoIndexLocked(int colorTransformId, int modeId) {
595 DisplayModeRecord record = mSupportedModes.get(modeId);
596 Display.ColorTransform transform = mSupportedColorTransforms.get(colorTransformId);
597 if (record != null && transform != null) {
598 for (int i = 0; i < mDisplayInfos.length; i++) {
599 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
600 if (info.colorTransform == transform.getColorTransform()
601 && record.hasMatchingMode(info)){
602 return i;
603 }
604 }
605 }
606 return -1;
Jeff Brown037c33e2014-04-09 00:31:55 -0700607 }
608
609 private void updateDeviceInfoLocked() {
610 mInfo = null;
611 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700612 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700613 }
Michael Wright3f145a22014-07-22 19:46:03 -0700614
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700615 /**
616 * Keeps track of a display configuration.
617 */
618 private static final class DisplayModeRecord {
619 public final Display.Mode mMode;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700620
Michael Wright58e829f2015-09-15 00:13:26 +0100621 public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700622 mMode = createMode(phys.width, phys.height, phys.refreshRate);
Michael Wright58e829f2015-09-15 00:13:26 +0100623 }
624
625 /**
626 * Returns whether the mode generated by the given PhysicalDisplayInfo matches the mode
627 * contained by the record modulo mode ID.
628 *
629 * Note that this doesn't necessarily mean the the PhysicalDisplayInfos are identical, just
630 * that they generate identical modes.
631 */
632 public boolean hasMatchingMode(SurfaceControl.PhysicalDisplayInfo info) {
633 int modeRefreshRate = Float.floatToIntBits(mMode.getRefreshRate());
634 int displayInfoRefreshRate = Float.floatToIntBits(info.refreshRate);
635 return mMode.getPhysicalWidth() == info.width
636 && mMode.getPhysicalHeight() == info.height
637 && modeRefreshRate == displayInfoRefreshRate;
638 }
639
640 public String toString() {
641 return "DisplayModeRecord{mMode=" + mMode + "}";
Michael Wright3f145a22014-07-22 19:46:03 -0700642 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700643 }
Jeff Browne87bf032012-09-20 18:30:13 -0700644
645 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
646 public HotplugDisplayEventReceiver(Looper looper) {
647 super(looper);
648 }
649
650 @Override
651 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
652 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800653 if (connected) {
654 tryConnectDisplayLocked(builtInDisplayId);
655 } else {
656 tryDisconnectDisplayLocked(builtInDisplayId);
657 }
Jeff Browne87bf032012-09-20 18:30:13 -0700658 }
659 }
660 }
Dan Stoza00101052014-05-02 15:23:40 -0700661}