blob: 21ae048e1d756d508545df6f9258a20ae28ccebe [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
Adrian Roos30f53212018-01-05 16:14:34 +010019import android.app.ActivityThread;
Adam Powell49e7ff92015-05-14 16:18:53 -070020import android.content.res.Resources;
Jeff Brown5d6443b2015-04-10 20:15:01 -070021import com.android.server.LocalServices;
22import com.android.server.lights.Light;
23import com.android.server.lights.LightsManager;
24
Jeff Brown64a55af2012-08-26 02:47:39 -070025import android.content.Context;
Chris Phoenixbc839a32017-10-21 14:46:15 -070026import android.hardware.sidekick.SidekickInternal;
Griff Hazend3c454d2016-03-25 07:30:34 -070027import android.os.Build;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070028import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070029import android.os.IBinder;
Jeff Browne87bf032012-09-20 18:30:13 -070030import android.os.Looper;
Jeff Brown5d6443b2015-04-10 20:15:01 -070031import android.os.PowerManager;
Jeff Brown27f1d672012-10-17 18:32:34 -070032import android.os.SystemProperties;
Jeff Brown3edf5272014-08-14 19:25:14 -070033import android.os.Trace;
Dan Stoza00101052014-05-02 15:23:40 -070034import android.util.Slog;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070035import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070036import android.view.Display;
Adrian Roos1cf585052018-01-03 18:43:27 +010037import android.view.DisplayCutout;
Jeff Browne87bf032012-09-20 18:30:13 -070038import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070039import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080040import android.view.SurfaceControl;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070041import java.io.PrintWriter;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070042import java.util.ArrayList;
Michael Wright58e829f2015-09-15 00:13:26 +010043import java.util.Arrays;
Michael Wright1c9977b2016-07-12 13:30:10 -070044import java.util.Collections;
45import java.util.List;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070046
Jeff Brown64a55af2012-08-26 02:47:39 -070047/**
48 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070049 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070050 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070051 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070052 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070053final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070054 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown5d6443b2015-04-10 20:15:01 -070055 private static final boolean DEBUG = false;
Jeff Brown64a55af2012-08-26 02:47:39 -070056
Wale Ogunwale361ca212014-11-20 11:42:38 -080057 private static final String UNIQUE_ID_PREFIX = "local:";
58
Adam Powell01f280d2015-05-18 16:07:42 -070059 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
60
Jeff Brown4ed8fe72012-08-30 18:18:29 -070061 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080062 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
63 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070064 };
65
66 private final SparseArray<LocalDisplayDevice> mDevices =
67 new SparseArray<LocalDisplayDevice>();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070068 @SuppressWarnings("unused") // Becomes active at instantiation time.
Jeff Brown66692502012-10-18 16:13:44 -070069 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070070
Jeff Brown66692502012-10-18 16:13:44 -070071 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070072 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
73 Context context, Handler handler, Listener listener) {
74 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070075 }
76
77 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070078 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070079 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070080
81 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080082
83 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
84 tryConnectDisplayLocked(builtInDisplayId);
85 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070086 }
87
Jesse Halle244db42012-11-08 11:55:14 -080088 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080089 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070090 if (displayToken != null) {
91 SurfaceControl.PhysicalDisplayInfo[] configs =
92 SurfaceControl.getDisplayConfigs(displayToken);
93 if (configs == null) {
94 // There are no valid configs for this device, so we can't use it
95 Slog.w(TAG, "No valid configs found for display device " +
96 builtInDisplayId);
97 return;
98 }
99 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
100 if (activeConfig < 0) {
101 // There is no active config, and for now we don't have the
102 // policy to set one.
103 Slog.w(TAG, "No active config found for display device " +
104 builtInDisplayId);
105 return;
106 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700107 int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
108 if (activeColorMode < 0) {
109 // We failed to get the active color mode. We don't bail out here since on the next
110 // configuration pass we'll go ahead and set it to whatever it was set to last (or
111 // COLOR_MODE_NATIVE if this is the first configuration).
112 Slog.w(TAG, "Unable to get active color mode for display device " +
113 builtInDisplayId);
114 activeColorMode = Display.COLOR_MODE_INVALID;
115 }
116 int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
Jesse Halle244db42012-11-08 11:55:14 -0800117 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
118 if (device == null) {
119 // Display was added.
Dan Stoza00101052014-05-02 15:23:40 -0700120 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700121 configs, activeConfig, colorModes, activeColorMode);
Jesse Halle244db42012-11-08 11:55:14 -0800122 mDevices.put(builtInDisplayId, device);
123 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Michael Wright1c9977b2016-07-12 13:30:10 -0700124 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
125 colorModes, activeColorMode)) {
Jesse Halle244db42012-11-08 11:55:14 -0800126 // Display properties changed.
127 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700128 }
Jesse Halle244db42012-11-08 11:55:14 -0800129 } else {
130 // The display is no longer available. Ignore the attempt to add it.
131 // If it was connected but has already been disconnected, we'll get a
132 // disconnect event that will remove it from mDevices.
133 }
134 }
135
136 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
137 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
138 if (device != null) {
139 // Display was removed.
140 mDevices.remove(builtInDisplayId);
141 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700142 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700143 }
144
Prashant Malanic55929a2014-05-25 01:59:21 -0700145 static int getPowerModeForState(int state) {
146 switch (state) {
147 case Display.STATE_OFF:
148 return SurfaceControl.POWER_MODE_OFF;
Jeff Brown5dc21912014-07-17 18:50:18 -0700149 case Display.STATE_DOZE:
Prashant Malanic55929a2014-05-25 01:59:21 -0700150 return SurfaceControl.POWER_MODE_DOZE;
Jeff Brown5dc21912014-07-17 18:50:18 -0700151 case Display.STATE_DOZE_SUSPEND:
152 return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700153 case Display.STATE_ON_SUSPEND:
154 return SurfaceControl.POWER_MODE_ON_SUSPEND;
Prashant Malanic55929a2014-05-25 01:59:21 -0700155 default:
156 return SurfaceControl.POWER_MODE_NORMAL;
157 }
Jeff Brown44b1f762014-04-22 18:07:24 -0700158 }
159
Jeff Brown64a55af2012-08-26 02:47:39 -0700160 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700161 private final int mBuiltInDisplayId;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700162 private final Light mBacklight;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700163 private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
Michael Wright1c9977b2016-07-12 13:30:10 -0700164 private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
Jeff Brown64a55af2012-08-26 02:47:39 -0700165
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700166 private DisplayDeviceInfo mInfo;
167 private boolean mHavePendingChanges;
Jeff Brown037c33e2014-04-09 00:31:55 -0700168 private int mState = Display.STATE_UNKNOWN;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700169 private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Michael Wright58e829f2015-09-15 00:13:26 +0100170 private int mActivePhysIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700171 private int mDefaultModeId;
172 private int mActiveModeId;
173 private boolean mActiveModeInvalid;
Michael Wright1c9977b2016-07-12 13:30:10 -0700174 private int mActiveColorMode;
175 private boolean mActiveColorModeInvalid;
Michael Wright9ff94c02016-03-30 18:05:40 -0700176 private Display.HdrCapabilities mHdrCapabilities;
Chris Phoenixbc839a32017-10-21 14:46:15 -0700177 private boolean mSidekickActive;
178 private SidekickInternal mSidekickInternal;
Michael Wright58e829f2015-09-15 00:13:26 +0100179
180 private SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
Jeff Brown5d6443b2015-04-10 20:15:01 -0700181
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700182 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700183 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
184 int[] colorModes, int activeColorMode) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800185 super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700186 mBuiltInDisplayId = builtInDisplayId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700187 updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
188 colorModes, activeColorMode);
189 updateColorModesLocked(colorModes, activeColorMode);
Chris Phoenixbc839a32017-10-21 14:46:15 -0700190 mSidekickInternal = LocalServices.getService(SidekickInternal.class);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700191 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
192 LightsManager lights = LocalServices.getService(LightsManager.class);
193 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
194 } else {
195 mBacklight = null;
196 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700197 mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700198 }
199
Michael Wright1c9977b2016-07-12 13:30:10 -0700200 @Override
201 public boolean hasStableUniqueId() {
202 return true;
203 }
204
Michael Wright3f145a22014-07-22 19:46:03 -0700205 public boolean updatePhysicalDisplayInfoLocked(
Michael Wright1c9977b2016-07-12 13:30:10 -0700206 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
207 int[] colorModes, int activeColorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100208 mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
209 mActivePhysIndex = activeDisplayInfo;
Michael Wright58e829f2015-09-15 00:13:26 +0100210 // Build an updated list of all existing modes.
211 ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
212 boolean modesAdded = false;
213 for (int i = 0; i < physicalDisplayInfos.length; i++) {
214 SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
215 // First, check to see if we've already added a matching mode. Since not all
216 // configuration options are exposed via Display.Mode, it's possible that we have
217 // multiple PhysicalDisplayInfos that would generate the same Display.Mode.
218 boolean existingMode = false;
219 for (int j = 0; j < records.size(); j++) {
220 if (records.get(j).hasMatchingMode(info)) {
221 existingMode = true;
222 break;
223 }
224 }
225 if (existingMode) {
226 continue;
227 }
228 // If we haven't already added a mode for this configuration to the new set of
229 // supported modes then check to see if we have one in the prior set of supported
230 // modes to reuse.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700231 DisplayModeRecord record = findDisplayModeRecord(info);
Michael Wright58e829f2015-09-15 00:13:26 +0100232 if (record == null) {
233 record = new DisplayModeRecord(info);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700234 modesAdded = true;
235 }
236 records.add(record);
Michael Wright58e829f2015-09-15 00:13:26 +0100237 }
238
239 // Get the currently active mode
240 DisplayModeRecord activeRecord = null;
241 for (int i = 0; i < records.size(); i++) {
242 DisplayModeRecord record = records.get(i);
243 if (record.hasMatchingMode(physicalDisplayInfos[activeDisplayInfo])){
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700244 activeRecord = record;
Michael Wright58e829f2015-09-15 00:13:26 +0100245 break;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700246 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700247 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700248 // Check whether surface flinger spontaneously changed modes out from under us. Schedule
249 // traversals to ensure that the correct state is reapplied if necessary.
250 if (mActiveModeId != 0
251 && mActiveModeId != activeRecord.mMode.getModeId()) {
252 mActiveModeInvalid = true;
253 sendTraversalRequestLocked();
254 }
Michael Wright58e829f2015-09-15 00:13:26 +0100255
Michael Wright58e829f2015-09-15 00:13:26 +0100256 boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
Michael Wright1c9977b2016-07-12 13:30:10 -0700257 // If the records haven't changed then we're done here.
258 if (!recordsChanged) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700259 return false;
260 }
261 // Update the index of modes.
262 mHavePendingChanges = true;
Michael Wright58e829f2015-09-15 00:13:26 +0100263
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700264 mSupportedModes.clear();
265 for (DisplayModeRecord record : records) {
266 mSupportedModes.put(record.mMode.getModeId(), record);
267 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700268 // Update the default mode, if needed.
269 if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700270 if (mDefaultModeId != 0) {
Michael Wright58e829f2015-09-15 00:13:26 +0100271 Slog.w(TAG, "Default display mode no longer available, using currently"
272 + " active mode as default.");
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700273 }
274 mDefaultModeId = activeRecord.mMode.getModeId();
275 }
276 // Determine whether the active mode is still there.
277 if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
278 if (mActiveModeId != 0) {
279 Slog.w(TAG, "Active display mode no longer available, reverting to default"
280 + " mode.");
281 }
282 mActiveModeId = mDefaultModeId;
283 mActiveModeInvalid = true;
284 }
Michael Wright58e829f2015-09-15 00:13:26 +0100285
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700286 // Schedule traversals so that we apply pending changes.
287 sendTraversalRequestLocked();
288 return true;
289 }
290
Michael Wright1c9977b2016-07-12 13:30:10 -0700291 private boolean updateColorModesLocked(int[] colorModes,
292 int activeColorMode) {
293 List<Integer> pendingColorModes = new ArrayList<>();
294
thecrazyskullb34c81042016-12-18 12:48:20 -0500295 if (colorModes == null) return false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700296 // Build an updated list of all existing color modes.
297 boolean colorModesAdded = false;
298 for (int colorMode: colorModes) {
299 if (!mSupportedColorModes.contains(colorMode)) {
300 colorModesAdded = true;
301 }
302 pendingColorModes.add(colorMode);
303 }
304
305 boolean colorModesChanged =
306 pendingColorModes.size() != mSupportedColorModes.size()
307 || colorModesAdded;
308
309 // If the supported color modes haven't changed then we're done here.
310 if (!colorModesChanged) {
311 return false;
312 }
313
314 mHavePendingChanges = true;
315
316 mSupportedColorModes.clear();
317 mSupportedColorModes.addAll(pendingColorModes);
318 Collections.sort(mSupportedColorModes);
319
320 // Determine whether the active color mode is still there.
321 if (!mSupportedColorModes.contains(mActiveColorMode)) {
322 if (mActiveColorMode != 0) {
323 Slog.w(TAG, "Active color mode no longer available, reverting"
324 + " to default mode.");
325 mActiveColorMode = Display.COLOR_MODE_DEFAULT;
326 mActiveColorModeInvalid = true;
327 } else {
328 if (!mSupportedColorModes.isEmpty()) {
329 // This should never happen.
330 Slog.e(TAG, "Default and active color mode is no longer available!"
331 + " Reverting to first available mode.");
332 mActiveColorMode = mSupportedColorModes.get(0);
333 mActiveColorModeInvalid = true;
334 } else {
335 // This should really never happen.
336 Slog.e(TAG, "No color modes available!");
337 }
338 }
339 }
340 return true;
341 }
342
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700343 private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
344 for (int i = 0; i < mSupportedModes.size(); i++) {
345 DisplayModeRecord record = mSupportedModes.valueAt(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100346 if (record.hasMatchingMode(info)) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700347 return record;
348 }
349 }
350 return null;
Jeff Brown64a55af2012-08-26 02:47:39 -0700351 }
352
353 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700354 public void applyPendingDisplayDeviceInfoChangesLocked() {
355 if (mHavePendingChanges) {
356 mInfo = null;
357 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700358 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700359 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700360
361 @Override
362 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
363 if (mInfo == null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100364 SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700365 mInfo = new DisplayDeviceInfo();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700366 mInfo.width = phys.width;
367 mInfo.height = phys.height;
368 mInfo.modeId = mActiveModeId;
369 mInfo.defaultModeId = mDefaultModeId;
370 mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
371 for (int i = 0; i < mSupportedModes.size(); i++) {
372 DisplayModeRecord record = mSupportedModes.valueAt(i);
373 mInfo.supportedModes[i] = record.mMode;
374 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700375 mInfo.colorMode = mActiveColorMode;
376 mInfo.supportedColorModes =
377 new int[mSupportedColorModes.size()];
378 for (int i = 0; i < mSupportedColorModes.size(); i++) {
379 mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100380 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700381 mInfo.hdrCapabilities = mHdrCapabilities;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700382 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
383 mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
Jeff Brown037c33e2014-04-09 00:31:55 -0700384 mInfo.state = mState;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800385 mInfo.uniqueId = getUniqueId();
Jeff Brown77aebfd2012-10-01 21:07:03 -0700386
Jeff Brownf0681b32012-10-23 17:35:57 -0700387 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700388 // support compositing from gralloc protected buffers.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700389 if (phys.secure) {
Jeff Brownf0681b32012-10-23 17:35:57 -0700390 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
391 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
392 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700393
Adrian Roos30f53212018-01-05 16:14:34 +0100394 final Resources res = getOverlayContext().getResources();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800395 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700396 mInfo.name = res.getString(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700397 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700398 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700399 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Adam Powell01f280d2015-05-18 16:07:42 -0700400 if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
Griff Hazend3c454d2016-03-25 07:30:34 -0700401 || (Build.IS_EMULATOR
Adam Powell01f280d2015-05-18 16:07:42 -0700402 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700403 mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
404 }
Jorim Jaggi60640512018-06-29 01:14:31 +0200405 mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
406 mInfo.width, mInfo.height);
Jeff Brown92130f62012-10-24 21:28:33 -0700407 mInfo.type = Display.TYPE_BUILT_IN;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700408 mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
409 mInfo.xDpi = phys.xDpi;
410 mInfo.yDpi = phys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700411 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700412 } else {
Adrian Roos1cf585052018-01-03 18:43:27 +0100413 mInfo.displayCutout = null;
Jeff Brown92130f62012-10-24 21:28:33 -0700414 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700415 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700416 mInfo.name = getContext().getResources().getString(
417 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700418 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700419 mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700420
421 // For demonstration purposes, allow rotation of the external display.
422 // In the future we might allow the user to configure this directly.
423 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
424 mInfo.rotation = Surface.ROTATION_270;
425 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700426
427 // For demonstration purposes, allow rotation of the external display
428 // to follow the built-in display.
429 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
430 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
431 }
Michael Wright4b0fa172016-03-11 17:15:24 -0800432
433 if (!res.getBoolean(
434 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
435 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
436 }
Pavel Maltseva6fec7b2018-04-04 10:14:55 -0700437
438 if (res.getBoolean(com.android.internal.R.bool.config_localDisplaysPrivate)) {
439 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE;
440 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700441 }
442 }
443 return mInfo;
444 }
445
446 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700447 public Runnable requestDisplayStateLocked(final int state, final int brightness) {
448 // Assume that the brightness is off if the display is being turned off.
449 assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
450
451 final boolean stateChanged = (mState != state);
452 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
453 if (stateChanged || brightnessChanged) {
Jeff Browne75926d2014-09-18 15:24:49 -0700454 final int displayId = mBuiltInDisplayId;
455 final IBinder token = getDisplayTokenLocked();
Jeff Brown5d6443b2015-04-10 20:15:01 -0700456 final int oldState = mState;
Jeff Browne75926d2014-09-18 15:24:49 -0700457
Jeff Brown5d6443b2015-04-10 20:15:01 -0700458 if (stateChanged) {
459 mState = state;
460 updateDeviceInfoLocked();
461 }
462
463 if (brightnessChanged) {
464 mBrightness = brightness;
465 }
466
467 // Defer actually setting the display state until after we have exited
Jeff Browne75926d2014-09-18 15:24:49 -0700468 // the critical section since it can take hundreds of milliseconds
469 // to complete.
470 return new Runnable() {
471 @Override
472 public void run() {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700473 // Exit a suspended state before making any changes.
474 int currentState = oldState;
475 if (Display.isSuspendedState(oldState)
476 || oldState == Display.STATE_UNKNOWN) {
477 if (!Display.isSuspendedState(state)) {
478 setDisplayState(state);
479 currentState = state;
480 } else if (state == Display.STATE_DOZE_SUSPEND
481 || oldState == Display.STATE_DOZE_SUSPEND) {
482 setDisplayState(Display.STATE_DOZE);
483 currentState = Display.STATE_DOZE;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700484 } else if (state == Display.STATE_ON_SUSPEND
485 || oldState == Display.STATE_ON_SUSPEND) {
486 setDisplayState(Display.STATE_ON);
487 currentState = Display.STATE_ON;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700488 } else {
489 return; // old state and new state is off
490 }
491 }
492
Santos Cordond6a56602016-09-20 15:50:35 -0700493 // If the state change was from or to VR, then we need to tell the light
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700494 // so that it can apply appropriate VR brightness settings. Also, update the
495 // brightness so the state is propogated to light.
496 boolean vrModeChange = false;
Santos Cordond6a56602016-09-20 15:50:35 -0700497 if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
498 currentState != state) {
499 setVrMode(state == Display.STATE_VR);
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700500 vrModeChange = true;
Santos Cordond6a56602016-09-20 15:50:35 -0700501 }
502
503
Jeff Brown5d6443b2015-04-10 20:15:01 -0700504 // Apply brightness changes given that we are in a non-suspended state.
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700505 if (brightnessChanged || vrModeChange) {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700506 setDisplayBrightness(brightness);
507 }
508
509 // Enter the final desired state, possibly suspended.
510 if (state != currentState) {
511 setDisplayState(state);
512 }
513 }
514
Santos Cordond6a56602016-09-20 15:50:35 -0700515 private void setVrMode(boolean isVrEnabled) {
516 if (DEBUG) {
517 Slog.d(TAG, "setVrMode("
518 + "id=" + displayId
519 + ", state=" + Display.stateToString(state) + ")");
520 }
521 mBacklight.setVrMode(isVrEnabled);
522 }
523
Jeff Brown5d6443b2015-04-10 20:15:01 -0700524 private void setDisplayState(int state) {
525 if (DEBUG) {
526 Slog.d(TAG, "setDisplayState("
527 + "id=" + displayId
528 + ", state=" + Display.stateToString(state) + ")");
529 }
530
Chris Phoenixbc839a32017-10-21 14:46:15 -0700531 // We must tell sidekick to stop controlling the display before we
532 // can change its power mode, so do that first.
533 if (mSidekickActive) {
534 Trace.traceBegin(Trace.TRACE_TAG_POWER,
535 "SidekickInternal#endDisplayControl");
536 try {
537 mSidekickInternal.endDisplayControl();
538 } finally {
539 Trace.traceEnd(Trace.TRACE_TAG_POWER);
540 }
541 mSidekickActive = false;
542 }
543 final int mode = getPowerModeForState(state);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700544 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
545 + "id=" + displayId
546 + ", state=" + Display.stateToString(state) + ")");
Jeff Browne75926d2014-09-18 15:24:49 -0700547 try {
548 SurfaceControl.setDisplayPowerMode(token, mode);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100549 Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
Jeff Browne75926d2014-09-18 15:24:49 -0700550 } finally {
551 Trace.traceEnd(Trace.TRACE_TAG_POWER);
552 }
Chris Phoenixbc839a32017-10-21 14:46:15 -0700553 // If we're entering a suspended (but not OFF) power state and we
554 // have a sidekick available, tell it now that it can take control.
555 if (Display.isSuspendedState(state) && state != Display.STATE_OFF
556 && mSidekickInternal != null && !mSidekickActive) {
557 Trace.traceBegin(Trace.TRACE_TAG_POWER,
558 "SidekickInternal#startDisplayControl");
559 try {
560 mSidekickActive = mSidekickInternal.startDisplayControl(state);
561 } finally {
562 Trace.traceEnd(Trace.TRACE_TAG_POWER);
563 }
564 }
Jeff Browne75926d2014-09-18 15:24:49 -0700565 }
Jeff Brown5d6443b2015-04-10 20:15:01 -0700566
567 private void setDisplayBrightness(int brightness) {
568 if (DEBUG) {
569 Slog.d(TAG, "setDisplayBrightness("
570 + "id=" + displayId + ", brightness=" + brightness + ")");
571 }
572
573 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
574 + "id=" + displayId + ", brightness=" + brightness + ")");
575 try {
576 mBacklight.setBrightness(brightness);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100577 Trace.traceCounter(Trace.TRACE_TAG_POWER,
Michael Wrighta9f37ab2017-08-15 17:14:20 +0100578 "ScreenBrightness", brightness);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700579 } finally {
580 Trace.traceEnd(Trace.TRACE_TAG_POWER);
581 }
582 }
Jeff Browne75926d2014-09-18 15:24:49 -0700583 };
Jeff Brown037c33e2014-04-09 00:31:55 -0700584 }
Jeff Browne75926d2014-09-18 15:24:49 -0700585 return null;
Jeff Brown9e316a12012-10-08 19:17:06 -0700586 }
587
588 @Override
Robert Carrae606b42018-02-15 15:36:23 -0800589 public void requestDisplayModesLocked(int colorMode, int modeId) {
590 if (requestModeLocked(modeId) ||
591 requestColorModeLocked(colorMode)) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700592 updateDeviceInfoLocked();
593 }
594 }
595
Adrian Roos898ec382018-01-17 12:54:50 +0100596 @Override
597 public void onOverlayChangedLocked() {
598 updateDeviceInfoLocked();
599 }
600
Robert Carrae606b42018-02-15 15:36:23 -0800601 public boolean requestModeLocked(int modeId) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700602 if (modeId == 0) {
603 modeId = mDefaultModeId;
604 } else if (mSupportedModes.indexOfKey(modeId) < 0) {
605 Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
606 + " reverting to default display mode.");
607 modeId = mDefaultModeId;
608 }
Michael Wright58e829f2015-09-15 00:13:26 +0100609
Michael Wright1c9977b2016-07-12 13:30:10 -0700610 int physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100611 if (physIndex < 0) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700612 Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
613 + " trying with default mode ID");
Michael Wright58e829f2015-09-15 00:13:26 +0100614 modeId = mDefaultModeId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700615 physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100616 }
Jorim Jaggi3b3cbb52015-09-24 17:35:58 -0700617 if (mActivePhysIndex == physIndex) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700618 return false;
Michael Wright3f145a22014-07-22 19:46:03 -0700619 }
Michael Wright58e829f2015-09-15 00:13:26 +0100620 SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
621 mActivePhysIndex = physIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700622 mActiveModeId = modeId;
623 mActiveModeInvalid = false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700624 return true;
625 }
626
Robert Carrae606b42018-02-15 15:36:23 -0800627 public boolean requestColorModeLocked(int colorMode) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700628 if (mActiveColorMode == colorMode) {
629 return false;
630 }
631 if (!mSupportedColorModes.contains(colorMode)) {
632 Slog.w(TAG, "Unable to find color mode " + colorMode
633 + ", ignoring request.");
634 return false;
635 }
636 SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
637 mActiveColorMode = colorMode;
638 mActiveColorModeInvalid = false;
639 return true;
Michael Wright3f145a22014-07-22 19:46:03 -0700640 }
641
642 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700643 public void dumpLocked(PrintWriter pw) {
644 super.dumpLocked(pw);
645 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
Michael Wright58e829f2015-09-15 00:13:26 +0100646 pw.println("mActivePhysIndex=" + mActivePhysIndex);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700647 pw.println("mActiveModeId=" + mActiveModeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700648 pw.println("mActiveColorMode=" + mActiveColorMode);
Jeff Brown037c33e2014-04-09 00:31:55 -0700649 pw.println("mState=" + Display.stateToString(mState));
Jeff Brown5d6443b2015-04-10 20:15:01 -0700650 pw.println("mBrightness=" + mBrightness);
651 pw.println("mBacklight=" + mBacklight);
Michael Wright58e829f2015-09-15 00:13:26 +0100652 pw.println("mDisplayInfos=");
653 for (int i = 0; i < mDisplayInfos.length; i++) {
654 pw.println(" " + mDisplayInfos[i]);
655 }
656 pw.println("mSupportedModes=");
657 for (int i = 0; i < mSupportedModes.size(); i++) {
658 pw.println(" " + mSupportedModes.valueAt(i));
659 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700660 pw.print("mSupportedColorModes=[");
661 for (int i = 0; i < mSupportedColorModes.size(); i++) {
Michael Wright58e829f2015-09-15 00:13:26 +0100662 if (i != 0) {
663 pw.print(", ");
664 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700665 pw.print(mSupportedColorModes.get(i));
Michael Wright58e829f2015-09-15 00:13:26 +0100666 }
667 pw.println("]");
668 }
669
Michael Wright1c9977b2016-07-12 13:30:10 -0700670 private int findDisplayInfoIndexLocked(int modeId) {
Michael Wright58e829f2015-09-15 00:13:26 +0100671 DisplayModeRecord record = mSupportedModes.get(modeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700672 if (record != null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100673 for (int i = 0; i < mDisplayInfos.length; i++) {
674 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
Michael Wright1c9977b2016-07-12 13:30:10 -0700675 if (record.hasMatchingMode(info)){
Michael Wright58e829f2015-09-15 00:13:26 +0100676 return i;
677 }
678 }
679 }
680 return -1;
Jeff Brown037c33e2014-04-09 00:31:55 -0700681 }
682
683 private void updateDeviceInfoLocked() {
684 mInfo = null;
685 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700686 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700687 }
Michael Wright3f145a22014-07-22 19:46:03 -0700688
Adrian Roos30f53212018-01-05 16:14:34 +0100689 /** Supplies a context whose Resources apply runtime-overlays */
690 Context getOverlayContext() {
691 return ActivityThread.currentActivityThread().getSystemUiContext();
692 }
693
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700694 /**
695 * Keeps track of a display configuration.
696 */
697 private static final class DisplayModeRecord {
698 public final Display.Mode mMode;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700699
Michael Wright58e829f2015-09-15 00:13:26 +0100700 public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700701 mMode = createMode(phys.width, phys.height, phys.refreshRate);
Michael Wright58e829f2015-09-15 00:13:26 +0100702 }
703
704 /**
705 * Returns whether the mode generated by the given PhysicalDisplayInfo matches the mode
706 * contained by the record modulo mode ID.
707 *
708 * Note that this doesn't necessarily mean the the PhysicalDisplayInfos are identical, just
709 * that they generate identical modes.
710 */
711 public boolean hasMatchingMode(SurfaceControl.PhysicalDisplayInfo info) {
712 int modeRefreshRate = Float.floatToIntBits(mMode.getRefreshRate());
713 int displayInfoRefreshRate = Float.floatToIntBits(info.refreshRate);
714 return mMode.getPhysicalWidth() == info.width
715 && mMode.getPhysicalHeight() == info.height
716 && modeRefreshRate == displayInfoRefreshRate;
717 }
718
719 public String toString() {
720 return "DisplayModeRecord{mMode=" + mMode + "}";
Michael Wright3f145a22014-07-22 19:46:03 -0700721 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700722 }
Jeff Browne87bf032012-09-20 18:30:13 -0700723
724 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
725 public HotplugDisplayEventReceiver(Looper looper) {
Jorim Jaggi34a0cdb2017-06-08 15:40:38 -0700726 super(looper, VSYNC_SOURCE_APP);
Jeff Browne87bf032012-09-20 18:30:13 -0700727 }
728
729 @Override
730 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
731 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800732 if (connected) {
733 tryConnectDisplayLocked(builtInDisplayId);
734 } else {
735 tryDisconnectDisplayLocked(builtInDisplayId);
736 }
Jeff Browne87bf032012-09-20 18:30:13 -0700737 }
738 }
739 }
Dan Stoza00101052014-05-02 15:23:40 -0700740}