blob: d61a418c30a25c9cfcb8a011b5d04c1c027cc774 [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;
Michael Wright1c9977b2016-07-12 13:30:10 -070042import java.util.Collections;
43import java.util.List;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070044
Jeff Brown64a55af2012-08-26 02:47:39 -070045/**
46 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070047 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070048 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070049 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070050 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070051final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070052 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown5d6443b2015-04-10 20:15:01 -070053 private static final boolean DEBUG = false;
Jeff Brown64a55af2012-08-26 02:47:39 -070054
Wale Ogunwale361ca212014-11-20 11:42:38 -080055 private static final String UNIQUE_ID_PREFIX = "local:";
56
Adam Powell01f280d2015-05-18 16:07:42 -070057 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
58
Jeff Brown4ed8fe72012-08-30 18:18:29 -070059 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080060 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
61 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070062 };
63
64 private final SparseArray<LocalDisplayDevice> mDevices =
65 new SparseArray<LocalDisplayDevice>();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070066 @SuppressWarnings("unused") // Becomes active at instantiation time.
Jeff Brown66692502012-10-18 16:13:44 -070067 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070068
Jeff Brown66692502012-10-18 16:13:44 -070069 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070070 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
71 Context context, Handler handler, Listener listener) {
72 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070073 }
74
75 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070076 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070077 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070078
79 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080080
81 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
82 tryConnectDisplayLocked(builtInDisplayId);
83 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070084 }
85
Jesse Halle244db42012-11-08 11:55:14 -080086 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080087 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070088 if (displayToken != null) {
89 SurfaceControl.PhysicalDisplayInfo[] configs =
90 SurfaceControl.getDisplayConfigs(displayToken);
91 if (configs == null) {
92 // There are no valid configs for this device, so we can't use it
93 Slog.w(TAG, "No valid configs found for display device " +
94 builtInDisplayId);
95 return;
96 }
97 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
98 if (activeConfig < 0) {
99 // There is no active config, and for now we don't have the
100 // policy to set one.
101 Slog.w(TAG, "No active config found for display device " +
102 builtInDisplayId);
103 return;
104 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700105 int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
106 if (activeColorMode < 0) {
107 // We failed to get the active color mode. We don't bail out here since on the next
108 // configuration pass we'll go ahead and set it to whatever it was set to last (or
109 // COLOR_MODE_NATIVE if this is the first configuration).
110 Slog.w(TAG, "Unable to get active color mode for display device " +
111 builtInDisplayId);
112 activeColorMode = Display.COLOR_MODE_INVALID;
113 }
114 int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
Jesse Halle244db42012-11-08 11:55:14 -0800115 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
116 if (device == null) {
117 // Display was added.
Dan Stoza00101052014-05-02 15:23:40 -0700118 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700119 configs, activeConfig, colorModes, activeColorMode);
Jesse Halle244db42012-11-08 11:55:14 -0800120 mDevices.put(builtInDisplayId, device);
121 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Michael Wright1c9977b2016-07-12 13:30:10 -0700122 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
123 colorModes, activeColorMode)) {
Jesse Halle244db42012-11-08 11:55:14 -0800124 // Display properties changed.
125 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700126 }
Jesse Halle244db42012-11-08 11:55:14 -0800127 } else {
128 // The display is no longer available. Ignore the attempt to add it.
129 // If it was connected but has already been disconnected, we'll get a
130 // disconnect event that will remove it from mDevices.
131 }
132 }
133
134 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
135 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
136 if (device != null) {
137 // Display was removed.
138 mDevices.remove(builtInDisplayId);
139 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700140 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700141 }
142
Prashant Malanic55929a2014-05-25 01:59:21 -0700143 static int getPowerModeForState(int state) {
144 switch (state) {
145 case Display.STATE_OFF:
146 return SurfaceControl.POWER_MODE_OFF;
Jeff Brown5dc21912014-07-17 18:50:18 -0700147 case Display.STATE_DOZE:
Prashant Malanic55929a2014-05-25 01:59:21 -0700148 return SurfaceControl.POWER_MODE_DOZE;
Jeff Brown5dc21912014-07-17 18:50:18 -0700149 case Display.STATE_DOZE_SUSPEND:
150 return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
Prashant Malanic55929a2014-05-25 01:59:21 -0700151 default:
152 return SurfaceControl.POWER_MODE_NORMAL;
153 }
Jeff Brown44b1f762014-04-22 18:07:24 -0700154 }
155
Jeff Brown64a55af2012-08-26 02:47:39 -0700156 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700157 private final int mBuiltInDisplayId;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700158 private final Light mBacklight;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700159 private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
Michael Wright1c9977b2016-07-12 13:30:10 -0700160 private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
Jeff Brown64a55af2012-08-26 02:47:39 -0700161
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700162 private DisplayDeviceInfo mInfo;
163 private boolean mHavePendingChanges;
Jeff Brown037c33e2014-04-09 00:31:55 -0700164 private int mState = Display.STATE_UNKNOWN;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700165 private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Michael Wright58e829f2015-09-15 00:13:26 +0100166 private int mActivePhysIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700167 private int mDefaultModeId;
168 private int mActiveModeId;
169 private boolean mActiveModeInvalid;
Michael Wright1c9977b2016-07-12 13:30:10 -0700170 private int mActiveColorMode;
171 private boolean mActiveColorModeInvalid;
Michael Wright9ff94c02016-03-30 18:05:40 -0700172 private Display.HdrCapabilities mHdrCapabilities;
Michael Wright58e829f2015-09-15 00:13:26 +0100173
174 private SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
Jeff Brown5d6443b2015-04-10 20:15:01 -0700175
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700176 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700177 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
178 int[] colorModes, int activeColorMode) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800179 super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700180 mBuiltInDisplayId = builtInDisplayId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700181 updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
182 colorModes, activeColorMode);
183 updateColorModesLocked(colorModes, activeColorMode);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700184 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
185 LightsManager lights = LocalServices.getService(LightsManager.class);
186 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
187 } else {
188 mBacklight = null;
189 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700190 mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700191 }
192
Michael Wright1c9977b2016-07-12 13:30:10 -0700193 @Override
194 public boolean hasStableUniqueId() {
195 return true;
196 }
197
Michael Wright3f145a22014-07-22 19:46:03 -0700198 public boolean updatePhysicalDisplayInfoLocked(
Michael Wright1c9977b2016-07-12 13:30:10 -0700199 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
200 int[] colorModes, int activeColorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100201 mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
202 mActivePhysIndex = activeDisplayInfo;
Michael Wright58e829f2015-09-15 00:13:26 +0100203 // Build an updated list of all existing modes.
204 ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
205 boolean modesAdded = false;
206 for (int i = 0; i < physicalDisplayInfos.length; i++) {
207 SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
208 // First, check to see if we've already added a matching mode. Since not all
209 // configuration options are exposed via Display.Mode, it's possible that we have
210 // multiple PhysicalDisplayInfos that would generate the same Display.Mode.
211 boolean existingMode = false;
212 for (int j = 0; j < records.size(); j++) {
213 if (records.get(j).hasMatchingMode(info)) {
214 existingMode = true;
215 break;
216 }
217 }
218 if (existingMode) {
219 continue;
220 }
221 // If we haven't already added a mode for this configuration to the new set of
222 // supported modes then check to see if we have one in the prior set of supported
223 // modes to reuse.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700224 DisplayModeRecord record = findDisplayModeRecord(info);
Michael Wright58e829f2015-09-15 00:13:26 +0100225 if (record == null) {
226 record = new DisplayModeRecord(info);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700227 modesAdded = true;
228 }
229 records.add(record);
Michael Wright58e829f2015-09-15 00:13:26 +0100230 }
231
232 // Get the currently active mode
233 DisplayModeRecord activeRecord = null;
234 for (int i = 0; i < records.size(); i++) {
235 DisplayModeRecord record = records.get(i);
236 if (record.hasMatchingMode(physicalDisplayInfos[activeDisplayInfo])){
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700237 activeRecord = record;
Michael Wright58e829f2015-09-15 00:13:26 +0100238 break;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700239 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700240 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700241 // Check whether surface flinger spontaneously changed modes out from under us. Schedule
242 // traversals to ensure that the correct state is reapplied if necessary.
243 if (mActiveModeId != 0
244 && mActiveModeId != activeRecord.mMode.getModeId()) {
245 mActiveModeInvalid = true;
246 sendTraversalRequestLocked();
247 }
Michael Wright58e829f2015-09-15 00:13:26 +0100248
Michael Wright58e829f2015-09-15 00:13:26 +0100249 boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
Michael Wright1c9977b2016-07-12 13:30:10 -0700250 // If the records haven't changed then we're done here.
251 if (!recordsChanged) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700252 return false;
253 }
254 // Update the index of modes.
255 mHavePendingChanges = true;
Michael Wright58e829f2015-09-15 00:13:26 +0100256
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700257 mSupportedModes.clear();
258 for (DisplayModeRecord record : records) {
259 mSupportedModes.put(record.mMode.getModeId(), record);
260 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700261 // Update the default mode, if needed.
262 if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700263 if (mDefaultModeId != 0) {
Michael Wright58e829f2015-09-15 00:13:26 +0100264 Slog.w(TAG, "Default display mode no longer available, using currently"
265 + " active mode as default.");
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700266 }
267 mDefaultModeId = activeRecord.mMode.getModeId();
268 }
269 // Determine whether the active mode is still there.
270 if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
271 if (mActiveModeId != 0) {
272 Slog.w(TAG, "Active display mode no longer available, reverting to default"
273 + " mode.");
274 }
275 mActiveModeId = mDefaultModeId;
276 mActiveModeInvalid = true;
277 }
Michael Wright58e829f2015-09-15 00:13:26 +0100278
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700279 // Schedule traversals so that we apply pending changes.
280 sendTraversalRequestLocked();
281 return true;
282 }
283
Michael Wright1c9977b2016-07-12 13:30:10 -0700284 private boolean updateColorModesLocked(int[] colorModes,
285 int activeColorMode) {
286 List<Integer> pendingColorModes = new ArrayList<>();
287
thecrazyskullb34c81042016-12-18 12:48:20 -0500288 if (colorModes == null) return false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700289 // Build an updated list of all existing color modes.
290 boolean colorModesAdded = false;
291 for (int colorMode: colorModes) {
292 if (!mSupportedColorModes.contains(colorMode)) {
293 colorModesAdded = true;
294 }
295 pendingColorModes.add(colorMode);
296 }
297
298 boolean colorModesChanged =
299 pendingColorModes.size() != mSupportedColorModes.size()
300 || colorModesAdded;
301
302 // If the supported color modes haven't changed then we're done here.
303 if (!colorModesChanged) {
304 return false;
305 }
306
307 mHavePendingChanges = true;
308
309 mSupportedColorModes.clear();
310 mSupportedColorModes.addAll(pendingColorModes);
311 Collections.sort(mSupportedColorModes);
312
313 // Determine whether the active color mode is still there.
314 if (!mSupportedColorModes.contains(mActiveColorMode)) {
315 if (mActiveColorMode != 0) {
316 Slog.w(TAG, "Active color mode no longer available, reverting"
317 + " to default mode.");
318 mActiveColorMode = Display.COLOR_MODE_DEFAULT;
319 mActiveColorModeInvalid = true;
320 } else {
321 if (!mSupportedColorModes.isEmpty()) {
322 // This should never happen.
323 Slog.e(TAG, "Default and active color mode is no longer available!"
324 + " Reverting to first available mode.");
325 mActiveColorMode = mSupportedColorModes.get(0);
326 mActiveColorModeInvalid = true;
327 } else {
328 // This should really never happen.
329 Slog.e(TAG, "No color modes available!");
330 }
331 }
332 }
333 return true;
334 }
335
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700336 private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
337 for (int i = 0; i < mSupportedModes.size(); i++) {
338 DisplayModeRecord record = mSupportedModes.valueAt(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100339 if (record.hasMatchingMode(info)) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700340 return record;
341 }
342 }
343 return null;
Jeff Brown64a55af2012-08-26 02:47:39 -0700344 }
345
346 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700347 public void applyPendingDisplayDeviceInfoChangesLocked() {
348 if (mHavePendingChanges) {
349 mInfo = null;
350 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700351 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700352 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700353
354 @Override
355 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
356 if (mInfo == null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100357 SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700358 mInfo = new DisplayDeviceInfo();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700359 mInfo.width = phys.width;
360 mInfo.height = phys.height;
361 mInfo.modeId = mActiveModeId;
362 mInfo.defaultModeId = mDefaultModeId;
363 mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
364 for (int i = 0; i < mSupportedModes.size(); i++) {
365 DisplayModeRecord record = mSupportedModes.valueAt(i);
366 mInfo.supportedModes[i] = record.mMode;
367 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700368 mInfo.colorMode = mActiveColorMode;
369 mInfo.supportedColorModes =
370 new int[mSupportedColorModes.size()];
371 for (int i = 0; i < mSupportedColorModes.size(); i++) {
372 mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100373 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700374 mInfo.hdrCapabilities = mHdrCapabilities;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700375 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
376 mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
Jeff Brown037c33e2014-04-09 00:31:55 -0700377 mInfo.state = mState;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800378 mInfo.uniqueId = getUniqueId();
Jeff Brown77aebfd2012-10-01 21:07:03 -0700379
Jeff Brownf0681b32012-10-23 17:35:57 -0700380 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700381 // support compositing from gralloc protected buffers.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700382 if (phys.secure) {
Jeff Brownf0681b32012-10-23 17:35:57 -0700383 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
384 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
385 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700386
Michael Wright4b0fa172016-03-11 17:15:24 -0800387 final Resources res = getContext().getResources();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800388 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700389 mInfo.name = res.getString(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700390 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700391 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700392 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Adam Powell01f280d2015-05-18 16:07:42 -0700393 if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
Griff Hazend3c454d2016-03-25 07:30:34 -0700394 || (Build.IS_EMULATOR
Adam Powell01f280d2015-05-18 16:07:42 -0700395 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700396 mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
397 }
Jeff Brown92130f62012-10-24 21:28:33 -0700398 mInfo.type = Display.TYPE_BUILT_IN;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700399 mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
400 mInfo.xDpi = phys.xDpi;
401 mInfo.yDpi = phys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700402 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700403 } else {
Jeff Brown92130f62012-10-24 21:28:33 -0700404 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700405 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700406 mInfo.name = getContext().getResources().getString(
407 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700408 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700409 mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700410
411 // For demonstration purposes, allow rotation of the external display.
412 // In the future we might allow the user to configure this directly.
413 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
414 mInfo.rotation = Surface.ROTATION_270;
415 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700416
417 // For demonstration purposes, allow rotation of the external display
418 // to follow the built-in display.
419 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
420 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
421 }
Michael Wright4b0fa172016-03-11 17:15:24 -0800422
423 if (!res.getBoolean(
424 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
425 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
426 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700427 }
428 }
429 return mInfo;
430 }
431
432 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700433 public Runnable requestDisplayStateLocked(final int state, final int brightness) {
434 // Assume that the brightness is off if the display is being turned off.
435 assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
436
437 final boolean stateChanged = (mState != state);
438 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
439 if (stateChanged || brightnessChanged) {
Jeff Browne75926d2014-09-18 15:24:49 -0700440 final int displayId = mBuiltInDisplayId;
441 final IBinder token = getDisplayTokenLocked();
Jeff Brown5d6443b2015-04-10 20:15:01 -0700442 final int oldState = mState;
Jeff Browne75926d2014-09-18 15:24:49 -0700443
Jeff Brown5d6443b2015-04-10 20:15:01 -0700444 if (stateChanged) {
445 mState = state;
446 updateDeviceInfoLocked();
447 }
448
449 if (brightnessChanged) {
450 mBrightness = brightness;
451 }
452
453 // Defer actually setting the display state until after we have exited
Jeff Browne75926d2014-09-18 15:24:49 -0700454 // the critical section since it can take hundreds of milliseconds
455 // to complete.
456 return new Runnable() {
457 @Override
458 public void run() {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700459 // Exit a suspended state before making any changes.
460 int currentState = oldState;
461 if (Display.isSuspendedState(oldState)
462 || oldState == Display.STATE_UNKNOWN) {
463 if (!Display.isSuspendedState(state)) {
464 setDisplayState(state);
465 currentState = state;
466 } else if (state == Display.STATE_DOZE_SUSPEND
467 || oldState == Display.STATE_DOZE_SUSPEND) {
468 setDisplayState(Display.STATE_DOZE);
469 currentState = Display.STATE_DOZE;
470 } else {
471 return; // old state and new state is off
472 }
473 }
474
Santos Cordond6a56602016-09-20 15:50:35 -0700475 // If the state change was from or to VR, then we need to tell the light
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700476 // so that it can apply appropriate VR brightness settings. Also, update the
477 // brightness so the state is propogated to light.
478 boolean vrModeChange = false;
Santos Cordond6a56602016-09-20 15:50:35 -0700479 if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
480 currentState != state) {
481 setVrMode(state == Display.STATE_VR);
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700482 vrModeChange = true;
Santos Cordond6a56602016-09-20 15:50:35 -0700483 }
484
485
Jeff Brown5d6443b2015-04-10 20:15:01 -0700486 // Apply brightness changes given that we are in a non-suspended state.
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700487 if (brightnessChanged || vrModeChange) {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700488 setDisplayBrightness(brightness);
489 }
490
491 // Enter the final desired state, possibly suspended.
492 if (state != currentState) {
493 setDisplayState(state);
494 }
495 }
496
Santos Cordond6a56602016-09-20 15:50:35 -0700497 private void setVrMode(boolean isVrEnabled) {
498 if (DEBUG) {
499 Slog.d(TAG, "setVrMode("
500 + "id=" + displayId
501 + ", state=" + Display.stateToString(state) + ")");
502 }
503 mBacklight.setVrMode(isVrEnabled);
504 }
505
Jeff Brown5d6443b2015-04-10 20:15:01 -0700506 private void setDisplayState(int state) {
507 if (DEBUG) {
508 Slog.d(TAG, "setDisplayState("
509 + "id=" + displayId
510 + ", state=" + Display.stateToString(state) + ")");
511 }
512
513 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
514 + "id=" + displayId
515 + ", state=" + Display.stateToString(state) + ")");
Jeff Browne75926d2014-09-18 15:24:49 -0700516 try {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700517 final int mode = getPowerModeForState(state);
Jeff Browne75926d2014-09-18 15:24:49 -0700518 SurfaceControl.setDisplayPowerMode(token, mode);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100519 Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
Jeff Browne75926d2014-09-18 15:24:49 -0700520 } finally {
521 Trace.traceEnd(Trace.TRACE_TAG_POWER);
522 }
523 }
Jeff Brown5d6443b2015-04-10 20:15:01 -0700524
525 private void setDisplayBrightness(int brightness) {
526 if (DEBUG) {
527 Slog.d(TAG, "setDisplayBrightness("
528 + "id=" + displayId + ", brightness=" + brightness + ")");
529 }
530
531 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
532 + "id=" + displayId + ", brightness=" + brightness + ")");
533 try {
534 mBacklight.setBrightness(brightness);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100535 Trace.traceCounter(Trace.TRACE_TAG_POWER,
Michael Wrighta9f37ab2017-08-15 17:14:20 +0100536 "ScreenBrightness", brightness);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700537 } finally {
538 Trace.traceEnd(Trace.TRACE_TAG_POWER);
539 }
540 }
Jeff Browne75926d2014-09-18 15:24:49 -0700541 };
Jeff Brown037c33e2014-04-09 00:31:55 -0700542 }
Jeff Browne75926d2014-09-18 15:24:49 -0700543 return null;
Jeff Brown9e316a12012-10-08 19:17:06 -0700544 }
545
546 @Override
Michael Wright1c9977b2016-07-12 13:30:10 -0700547 public void requestDisplayModesInTransactionLocked(
548 int colorMode, int modeId) {
549 if (requestModeInTransactionLocked(modeId) ||
550 requestColorModeInTransactionLocked(colorMode)) {
551 updateDeviceInfoLocked();
552 }
553 }
554
555 public boolean requestModeInTransactionLocked(int modeId) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700556 if (modeId == 0) {
557 modeId = mDefaultModeId;
558 } else if (mSupportedModes.indexOfKey(modeId) < 0) {
559 Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
560 + " reverting to default display mode.");
561 modeId = mDefaultModeId;
562 }
Michael Wright58e829f2015-09-15 00:13:26 +0100563
Michael Wright1c9977b2016-07-12 13:30:10 -0700564 int physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100565 if (physIndex < 0) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700566 Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
567 + " trying with default mode ID");
Michael Wright58e829f2015-09-15 00:13:26 +0100568 modeId = mDefaultModeId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700569 physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100570 }
Jorim Jaggi3b3cbb52015-09-24 17:35:58 -0700571 if (mActivePhysIndex == physIndex) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700572 return false;
Michael Wright3f145a22014-07-22 19:46:03 -0700573 }
Michael Wright58e829f2015-09-15 00:13:26 +0100574 SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
575 mActivePhysIndex = physIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700576 mActiveModeId = modeId;
577 mActiveModeInvalid = false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700578 return true;
579 }
580
581 public boolean requestColorModeInTransactionLocked(int colorMode) {
582 if (mActiveColorMode == colorMode) {
583 return false;
584 }
585 if (!mSupportedColorModes.contains(colorMode)) {
586 Slog.w(TAG, "Unable to find color mode " + colorMode
587 + ", ignoring request.");
588 return false;
589 }
590 SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
591 mActiveColorMode = colorMode;
592 mActiveColorModeInvalid = false;
593 return true;
Michael Wright3f145a22014-07-22 19:46:03 -0700594 }
595
596 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700597 public void dumpLocked(PrintWriter pw) {
598 super.dumpLocked(pw);
599 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
Michael Wright58e829f2015-09-15 00:13:26 +0100600 pw.println("mActivePhysIndex=" + mActivePhysIndex);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700601 pw.println("mActiveModeId=" + mActiveModeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700602 pw.println("mActiveColorMode=" + mActiveColorMode);
Jeff Brown037c33e2014-04-09 00:31:55 -0700603 pw.println("mState=" + Display.stateToString(mState));
Jeff Brown5d6443b2015-04-10 20:15:01 -0700604 pw.println("mBrightness=" + mBrightness);
605 pw.println("mBacklight=" + mBacklight);
Michael Wright58e829f2015-09-15 00:13:26 +0100606 pw.println("mDisplayInfos=");
607 for (int i = 0; i < mDisplayInfos.length; i++) {
608 pw.println(" " + mDisplayInfos[i]);
609 }
610 pw.println("mSupportedModes=");
611 for (int i = 0; i < mSupportedModes.size(); i++) {
612 pw.println(" " + mSupportedModes.valueAt(i));
613 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700614 pw.print("mSupportedColorModes=[");
615 for (int i = 0; i < mSupportedColorModes.size(); i++) {
Michael Wright58e829f2015-09-15 00:13:26 +0100616 if (i != 0) {
617 pw.print(", ");
618 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700619 pw.print(mSupportedColorModes.get(i));
Michael Wright58e829f2015-09-15 00:13:26 +0100620 }
621 pw.println("]");
622 }
623
Michael Wright1c9977b2016-07-12 13:30:10 -0700624 private int findDisplayInfoIndexLocked(int modeId) {
Michael Wright58e829f2015-09-15 00:13:26 +0100625 DisplayModeRecord record = mSupportedModes.get(modeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700626 if (record != null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100627 for (int i = 0; i < mDisplayInfos.length; i++) {
628 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
Michael Wright1c9977b2016-07-12 13:30:10 -0700629 if (record.hasMatchingMode(info)){
Michael Wright58e829f2015-09-15 00:13:26 +0100630 return i;
631 }
632 }
633 }
634 return -1;
Jeff Brown037c33e2014-04-09 00:31:55 -0700635 }
636
637 private void updateDeviceInfoLocked() {
638 mInfo = null;
639 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700640 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700641 }
Michael Wright3f145a22014-07-22 19:46:03 -0700642
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700643 /**
644 * Keeps track of a display configuration.
645 */
646 private static final class DisplayModeRecord {
647 public final Display.Mode mMode;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700648
Michael Wright58e829f2015-09-15 00:13:26 +0100649 public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700650 mMode = createMode(phys.width, phys.height, phys.refreshRate);
Michael Wright58e829f2015-09-15 00:13:26 +0100651 }
652
653 /**
654 * Returns whether the mode generated by the given PhysicalDisplayInfo matches the mode
655 * contained by the record modulo mode ID.
656 *
657 * Note that this doesn't necessarily mean the the PhysicalDisplayInfos are identical, just
658 * that they generate identical modes.
659 */
660 public boolean hasMatchingMode(SurfaceControl.PhysicalDisplayInfo info) {
661 int modeRefreshRate = Float.floatToIntBits(mMode.getRefreshRate());
662 int displayInfoRefreshRate = Float.floatToIntBits(info.refreshRate);
663 return mMode.getPhysicalWidth() == info.width
664 && mMode.getPhysicalHeight() == info.height
665 && modeRefreshRate == displayInfoRefreshRate;
666 }
667
668 public String toString() {
669 return "DisplayModeRecord{mMode=" + mMode + "}";
Michael Wright3f145a22014-07-22 19:46:03 -0700670 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700671 }
Jeff Browne87bf032012-09-20 18:30:13 -0700672
673 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
674 public HotplugDisplayEventReceiver(Looper looper) {
Jorim Jaggi34a0cdb2017-06-08 15:40:38 -0700675 super(looper, VSYNC_SOURCE_APP);
Jeff Browne87bf032012-09-20 18:30:13 -0700676 }
677
678 @Override
679 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
680 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800681 if (connected) {
682 tryConnectDisplayLocked(builtInDisplayId);
683 } else {
684 tryDisconnectDisplayLocked(builtInDisplayId);
685 }
Jeff Browne87bf032012-09-20 18:30:13 -0700686 }
687 }
688 }
Dan Stoza00101052014-05-02 15:23:40 -0700689}