blob: b9a279ad13ea0fb4d4579cafe24fe1bc1db7267e [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;
Adrian Roos1cf585052018-01-03 18:43:27 +010034import android.text.TextUtils;
35import android.util.PathParser;
Dan Stoza00101052014-05-02 15:23:40 -070036import android.util.Slog;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070037import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070038import android.view.Display;
Adrian Roos1cf585052018-01-03 18:43:27 +010039import android.view.DisplayCutout;
Jeff Browne87bf032012-09-20 18:30:13 -070040import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070041import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080042import android.view.SurfaceControl;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070043import java.io.PrintWriter;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070044import java.util.ArrayList;
Michael Wright58e829f2015-09-15 00:13:26 +010045import java.util.Arrays;
Michael Wright1c9977b2016-07-12 13:30:10 -070046import java.util.Collections;
47import java.util.List;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070048
Jeff Brown64a55af2012-08-26 02:47:39 -070049/**
50 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070051 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070052 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070053 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070054 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070055final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070056 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown5d6443b2015-04-10 20:15:01 -070057 private static final boolean DEBUG = false;
Jeff Brown64a55af2012-08-26 02:47:39 -070058
Wale Ogunwale361ca212014-11-20 11:42:38 -080059 private static final String UNIQUE_ID_PREFIX = "local:";
60
Adam Powell01f280d2015-05-18 16:07:42 -070061 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
62
Jeff Brown4ed8fe72012-08-30 18:18:29 -070063 private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080064 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
65 SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
Jeff Brown4ed8fe72012-08-30 18:18:29 -070066 };
67
68 private final SparseArray<LocalDisplayDevice> mDevices =
69 new SparseArray<LocalDisplayDevice>();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070070 @SuppressWarnings("unused") // Becomes active at instantiation time.
Jeff Brown66692502012-10-18 16:13:44 -070071 private HotplugDisplayEventReceiver mHotplugReceiver;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070072
Jeff Brown66692502012-10-18 16:13:44 -070073 // Called with SyncRoot lock held.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070074 public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
75 Context context, Handler handler, Listener listener) {
76 super(syncRoot, context, handler, listener, TAG);
Jeff Brown64a55af2012-08-26 02:47:39 -070077 }
78
79 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -070080 public void registerLocked() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -070081 super.registerLocked();
Jeff Brown66692502012-10-18 16:13:44 -070082
83 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080084
85 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
86 tryConnectDisplayLocked(builtInDisplayId);
87 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070088 }
89
Jesse Halle244db42012-11-08 11:55:14 -080090 private void tryConnectDisplayLocked(int builtInDisplayId) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080091 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070092 if (displayToken != null) {
93 SurfaceControl.PhysicalDisplayInfo[] configs =
94 SurfaceControl.getDisplayConfigs(displayToken);
95 if (configs == null) {
96 // There are no valid configs for this device, so we can't use it
97 Slog.w(TAG, "No valid configs found for display device " +
98 builtInDisplayId);
99 return;
100 }
101 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
102 if (activeConfig < 0) {
103 // There is no active config, and for now we don't have the
104 // policy to set one.
105 Slog.w(TAG, "No active config found for display device " +
106 builtInDisplayId);
107 return;
108 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700109 int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
110 if (activeColorMode < 0) {
111 // We failed to get the active color mode. We don't bail out here since on the next
112 // configuration pass we'll go ahead and set it to whatever it was set to last (or
113 // COLOR_MODE_NATIVE if this is the first configuration).
114 Slog.w(TAG, "Unable to get active color mode for display device " +
115 builtInDisplayId);
116 activeColorMode = Display.COLOR_MODE_INVALID;
117 }
118 int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
Jesse Halle244db42012-11-08 11:55:14 -0800119 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
120 if (device == null) {
121 // Display was added.
Dan Stoza00101052014-05-02 15:23:40 -0700122 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700123 configs, activeConfig, colorModes, activeColorMode);
Jesse Halle244db42012-11-08 11:55:14 -0800124 mDevices.put(builtInDisplayId, device);
125 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Michael Wright1c9977b2016-07-12 13:30:10 -0700126 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
127 colorModes, activeColorMode)) {
Jesse Halle244db42012-11-08 11:55:14 -0800128 // Display properties changed.
129 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700130 }
Jesse Halle244db42012-11-08 11:55:14 -0800131 } else {
132 // The display is no longer available. Ignore the attempt to add it.
133 // If it was connected but has already been disconnected, we'll get a
134 // disconnect event that will remove it from mDevices.
135 }
136 }
137
138 private void tryDisconnectDisplayLocked(int builtInDisplayId) {
139 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
140 if (device != null) {
141 // Display was removed.
142 mDevices.remove(builtInDisplayId);
143 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700144 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700145 }
146
Prashant Malanic55929a2014-05-25 01:59:21 -0700147 static int getPowerModeForState(int state) {
148 switch (state) {
149 case Display.STATE_OFF:
150 return SurfaceControl.POWER_MODE_OFF;
Jeff Brown5dc21912014-07-17 18:50:18 -0700151 case Display.STATE_DOZE:
Prashant Malanic55929a2014-05-25 01:59:21 -0700152 return SurfaceControl.POWER_MODE_DOZE;
Jeff Brown5dc21912014-07-17 18:50:18 -0700153 case Display.STATE_DOZE_SUSPEND:
154 return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700155 case Display.STATE_ON_SUSPEND:
156 return SurfaceControl.POWER_MODE_ON_SUSPEND;
Prashant Malanic55929a2014-05-25 01:59:21 -0700157 default:
158 return SurfaceControl.POWER_MODE_NORMAL;
159 }
Jeff Brown44b1f762014-04-22 18:07:24 -0700160 }
161
Jeff Brown64a55af2012-08-26 02:47:39 -0700162 private final class LocalDisplayDevice extends DisplayDevice {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700163 private final int mBuiltInDisplayId;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700164 private final Light mBacklight;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700165 private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
Michael Wright1c9977b2016-07-12 13:30:10 -0700166 private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
Jeff Brown64a55af2012-08-26 02:47:39 -0700167
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700168 private DisplayDeviceInfo mInfo;
169 private boolean mHavePendingChanges;
Jeff Brown037c33e2014-04-09 00:31:55 -0700170 private int mState = Display.STATE_UNKNOWN;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700171 private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
Michael Wright58e829f2015-09-15 00:13:26 +0100172 private int mActivePhysIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700173 private int mDefaultModeId;
174 private int mActiveModeId;
175 private boolean mActiveModeInvalid;
Michael Wright1c9977b2016-07-12 13:30:10 -0700176 private int mActiveColorMode;
177 private boolean mActiveColorModeInvalid;
Michael Wright9ff94c02016-03-30 18:05:40 -0700178 private Display.HdrCapabilities mHdrCapabilities;
Chris Phoenixbc839a32017-10-21 14:46:15 -0700179 private boolean mSidekickActive;
180 private SidekickInternal mSidekickInternal;
Michael Wright58e829f2015-09-15 00:13:26 +0100181
182 private SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
Jeff Brown5d6443b2015-04-10 20:15:01 -0700183
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700184 public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700185 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
186 int[] colorModes, int activeColorMode) {
Wale Ogunwale361ca212014-11-20 11:42:38 -0800187 super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700188 mBuiltInDisplayId = builtInDisplayId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700189 updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
190 colorModes, activeColorMode);
191 updateColorModesLocked(colorModes, activeColorMode);
Chris Phoenixbc839a32017-10-21 14:46:15 -0700192 mSidekickInternal = LocalServices.getService(SidekickInternal.class);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700193 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
194 LightsManager lights = LocalServices.getService(LightsManager.class);
195 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
196 } else {
197 mBacklight = null;
198 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700199 mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700200 }
201
Michael Wright1c9977b2016-07-12 13:30:10 -0700202 @Override
203 public boolean hasStableUniqueId() {
204 return true;
205 }
206
Michael Wright3f145a22014-07-22 19:46:03 -0700207 public boolean updatePhysicalDisplayInfoLocked(
Michael Wright1c9977b2016-07-12 13:30:10 -0700208 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
209 int[] colorModes, int activeColorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100210 mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
211 mActivePhysIndex = activeDisplayInfo;
Michael Wright58e829f2015-09-15 00:13:26 +0100212 // 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
Michael Wright58e829f2015-09-15 00:13:26 +0100258 boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
Michael Wright1c9977b2016-07-12 13:30:10 -0700259 // If the records haven't changed then we're done here.
260 if (!recordsChanged) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700261 return false;
262 }
263 // Update the index of modes.
264 mHavePendingChanges = true;
Michael Wright58e829f2015-09-15 00:13:26 +0100265
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700266 mSupportedModes.clear();
267 for (DisplayModeRecord record : records) {
268 mSupportedModes.put(record.mMode.getModeId(), record);
269 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700270 // Update the default mode, if needed.
271 if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700272 if (mDefaultModeId != 0) {
Michael Wright58e829f2015-09-15 00:13:26 +0100273 Slog.w(TAG, "Default display mode no longer available, using currently"
274 + " active mode as default.");
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700275 }
276 mDefaultModeId = activeRecord.mMode.getModeId();
277 }
278 // Determine whether the active mode is still there.
279 if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
280 if (mActiveModeId != 0) {
281 Slog.w(TAG, "Active display mode no longer available, reverting to default"
282 + " mode.");
283 }
284 mActiveModeId = mDefaultModeId;
285 mActiveModeInvalid = true;
286 }
Michael Wright58e829f2015-09-15 00:13:26 +0100287
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700288 // Schedule traversals so that we apply pending changes.
289 sendTraversalRequestLocked();
290 return true;
291 }
292
Michael Wright1c9977b2016-07-12 13:30:10 -0700293 private boolean updateColorModesLocked(int[] colorModes,
294 int activeColorMode) {
295 List<Integer> pendingColorModes = new ArrayList<>();
296
thecrazyskullb34c81042016-12-18 12:48:20 -0500297 if (colorModes == null) return false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700298 // Build an updated list of all existing color modes.
299 boolean colorModesAdded = false;
300 for (int colorMode: colorModes) {
301 if (!mSupportedColorModes.contains(colorMode)) {
302 colorModesAdded = true;
303 }
304 pendingColorModes.add(colorMode);
305 }
306
307 boolean colorModesChanged =
308 pendingColorModes.size() != mSupportedColorModes.size()
309 || colorModesAdded;
310
311 // If the supported color modes haven't changed then we're done here.
312 if (!colorModesChanged) {
313 return false;
314 }
315
316 mHavePendingChanges = true;
317
318 mSupportedColorModes.clear();
319 mSupportedColorModes.addAll(pendingColorModes);
320 Collections.sort(mSupportedColorModes);
321
322 // Determine whether the active color mode is still there.
323 if (!mSupportedColorModes.contains(mActiveColorMode)) {
324 if (mActiveColorMode != 0) {
325 Slog.w(TAG, "Active color mode no longer available, reverting"
326 + " to default mode.");
327 mActiveColorMode = Display.COLOR_MODE_DEFAULT;
328 mActiveColorModeInvalid = true;
329 } else {
330 if (!mSupportedColorModes.isEmpty()) {
331 // This should never happen.
332 Slog.e(TAG, "Default and active color mode is no longer available!"
333 + " Reverting to first available mode.");
334 mActiveColorMode = mSupportedColorModes.get(0);
335 mActiveColorModeInvalid = true;
336 } else {
337 // This should really never happen.
338 Slog.e(TAG, "No color modes available!");
339 }
340 }
341 }
342 return true;
343 }
344
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700345 private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
346 for (int i = 0; i < mSupportedModes.size(); i++) {
347 DisplayModeRecord record = mSupportedModes.valueAt(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100348 if (record.hasMatchingMode(info)) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700349 return record;
350 }
351 }
352 return null;
Jeff Brown64a55af2012-08-26 02:47:39 -0700353 }
354
355 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700356 public void applyPendingDisplayDeviceInfoChangesLocked() {
357 if (mHavePendingChanges) {
358 mInfo = null;
359 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700360 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700361 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700362
363 @Override
364 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
365 if (mInfo == null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100366 SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700367 mInfo = new DisplayDeviceInfo();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700368 mInfo.width = phys.width;
369 mInfo.height = phys.height;
370 mInfo.modeId = mActiveModeId;
371 mInfo.defaultModeId = mDefaultModeId;
372 mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
373 for (int i = 0; i < mSupportedModes.size(); i++) {
374 DisplayModeRecord record = mSupportedModes.valueAt(i);
375 mInfo.supportedModes[i] = record.mMode;
376 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700377 mInfo.colorMode = mActiveColorMode;
378 mInfo.supportedColorModes =
379 new int[mSupportedColorModes.size()];
380 for (int i = 0; i < mSupportedColorModes.size(); i++) {
381 mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100382 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700383 mInfo.hdrCapabilities = mHdrCapabilities;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700384 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
385 mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
Jeff Brown037c33e2014-04-09 00:31:55 -0700386 mInfo.state = mState;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800387 mInfo.uniqueId = getUniqueId();
Jeff Brown77aebfd2012-10-01 21:07:03 -0700388
Jeff Brownf0681b32012-10-23 17:35:57 -0700389 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700390 // support compositing from gralloc protected buffers.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700391 if (phys.secure) {
Jeff Brownf0681b32012-10-23 17:35:57 -0700392 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
393 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
394 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700395
Adrian Roos30f53212018-01-05 16:14:34 +0100396 final Resources res = getOverlayContext().getResources();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800397 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700398 mInfo.name = res.getString(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700399 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700400 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700401 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Adam Powell01f280d2015-05-18 16:07:42 -0700402 if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
Griff Hazend3c454d2016-03-25 07:30:34 -0700403 || (Build.IS_EMULATOR
Adam Powell01f280d2015-05-18 16:07:42 -0700404 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700405 mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
406 }
Adrian Roos6a4fa0e2018-03-05 19:50:16 +0100407 mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width,
408 mInfo.height);
Jeff Brown92130f62012-10-24 21:28:33 -0700409 mInfo.type = Display.TYPE_BUILT_IN;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700410 mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
411 mInfo.xDpi = phys.xDpi;
412 mInfo.yDpi = phys.yDpi;
Jeff Brownd728bf52012-09-08 18:05:28 -0700413 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700414 } else {
Adrian Roos1cf585052018-01-03 18:43:27 +0100415 mInfo.displayCutout = null;
Jeff Brown92130f62012-10-24 21:28:33 -0700416 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700417 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700418 mInfo.name = getContext().getResources().getString(
419 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700420 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700421 mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
Jeff Brown27f1d672012-10-17 18:32:34 -0700422
423 // For demonstration purposes, allow rotation of the external display.
424 // In the future we might allow the user to configure this directly.
425 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
426 mInfo.rotation = Surface.ROTATION_270;
427 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700428
429 // For demonstration purposes, allow rotation of the external display
430 // to follow the built-in display.
431 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
432 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
433 }
Michael Wright4b0fa172016-03-11 17:15:24 -0800434
435 if (!res.getBoolean(
436 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
437 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
438 }
Pavel Maltseva6fec7b2018-04-04 10:14:55 -0700439
440 if (res.getBoolean(com.android.internal.R.bool.config_localDisplaysPrivate)) {
441 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE;
442 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700443 }
444 }
445 return mInfo;
446 }
447
448 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700449 public Runnable requestDisplayStateLocked(final int state, final int brightness) {
450 // Assume that the brightness is off if the display is being turned off.
451 assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
452
453 final boolean stateChanged = (mState != state);
454 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
455 if (stateChanged || brightnessChanged) {
Jeff Browne75926d2014-09-18 15:24:49 -0700456 final int displayId = mBuiltInDisplayId;
457 final IBinder token = getDisplayTokenLocked();
Jeff Brown5d6443b2015-04-10 20:15:01 -0700458 final int oldState = mState;
Jeff Browne75926d2014-09-18 15:24:49 -0700459
Jeff Brown5d6443b2015-04-10 20:15:01 -0700460 if (stateChanged) {
461 mState = state;
462 updateDeviceInfoLocked();
463 }
464
465 if (brightnessChanged) {
466 mBrightness = brightness;
467 }
468
469 // Defer actually setting the display state until after we have exited
Jeff Browne75926d2014-09-18 15:24:49 -0700470 // the critical section since it can take hundreds of milliseconds
471 // to complete.
472 return new Runnable() {
473 @Override
474 public void run() {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700475 // Exit a suspended state before making any changes.
476 int currentState = oldState;
477 if (Display.isSuspendedState(oldState)
478 || oldState == Display.STATE_UNKNOWN) {
479 if (!Display.isSuspendedState(state)) {
480 setDisplayState(state);
481 currentState = state;
482 } else if (state == Display.STATE_DOZE_SUSPEND
483 || oldState == Display.STATE_DOZE_SUSPEND) {
484 setDisplayState(Display.STATE_DOZE);
485 currentState = Display.STATE_DOZE;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700486 } else if (state == Display.STATE_ON_SUSPEND
487 || oldState == Display.STATE_ON_SUSPEND) {
488 setDisplayState(Display.STATE_ON);
489 currentState = Display.STATE_ON;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700490 } else {
491 return; // old state and new state is off
492 }
493 }
494
Santos Cordond6a56602016-09-20 15:50:35 -0700495 // If the state change was from or to VR, then we need to tell the light
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700496 // so that it can apply appropriate VR brightness settings. Also, update the
497 // brightness so the state is propogated to light.
498 boolean vrModeChange = false;
Santos Cordond6a56602016-09-20 15:50:35 -0700499 if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
500 currentState != state) {
501 setVrMode(state == Display.STATE_VR);
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700502 vrModeChange = true;
Santos Cordond6a56602016-09-20 15:50:35 -0700503 }
504
505
Jeff Brown5d6443b2015-04-10 20:15:01 -0700506 // Apply brightness changes given that we are in a non-suspended state.
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700507 if (brightnessChanged || vrModeChange) {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700508 setDisplayBrightness(brightness);
509 }
510
511 // Enter the final desired state, possibly suspended.
512 if (state != currentState) {
513 setDisplayState(state);
514 }
515 }
516
Santos Cordond6a56602016-09-20 15:50:35 -0700517 private void setVrMode(boolean isVrEnabled) {
518 if (DEBUG) {
519 Slog.d(TAG, "setVrMode("
520 + "id=" + displayId
521 + ", state=" + Display.stateToString(state) + ")");
522 }
523 mBacklight.setVrMode(isVrEnabled);
524 }
525
Jeff Brown5d6443b2015-04-10 20:15:01 -0700526 private void setDisplayState(int state) {
527 if (DEBUG) {
528 Slog.d(TAG, "setDisplayState("
529 + "id=" + displayId
530 + ", state=" + Display.stateToString(state) + ")");
531 }
532
Chris Phoenixbc839a32017-10-21 14:46:15 -0700533 // We must tell sidekick to stop controlling the display before we
534 // can change its power mode, so do that first.
535 if (mSidekickActive) {
536 Trace.traceBegin(Trace.TRACE_TAG_POWER,
537 "SidekickInternal#endDisplayControl");
538 try {
539 mSidekickInternal.endDisplayControl();
540 } finally {
541 Trace.traceEnd(Trace.TRACE_TAG_POWER);
542 }
543 mSidekickActive = false;
544 }
545 final int mode = getPowerModeForState(state);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700546 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
547 + "id=" + displayId
548 + ", state=" + Display.stateToString(state) + ")");
Jeff Browne75926d2014-09-18 15:24:49 -0700549 try {
550 SurfaceControl.setDisplayPowerMode(token, mode);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100551 Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
Jeff Browne75926d2014-09-18 15:24:49 -0700552 } finally {
553 Trace.traceEnd(Trace.TRACE_TAG_POWER);
554 }
Chris Phoenixbc839a32017-10-21 14:46:15 -0700555 // If we're entering a suspended (but not OFF) power state and we
556 // have a sidekick available, tell it now that it can take control.
557 if (Display.isSuspendedState(state) && state != Display.STATE_OFF
558 && mSidekickInternal != null && !mSidekickActive) {
559 Trace.traceBegin(Trace.TRACE_TAG_POWER,
560 "SidekickInternal#startDisplayControl");
561 try {
562 mSidekickActive = mSidekickInternal.startDisplayControl(state);
563 } finally {
564 Trace.traceEnd(Trace.TRACE_TAG_POWER);
565 }
566 }
Jeff Browne75926d2014-09-18 15:24:49 -0700567 }
Jeff Brown5d6443b2015-04-10 20:15:01 -0700568
569 private void setDisplayBrightness(int brightness) {
570 if (DEBUG) {
571 Slog.d(TAG, "setDisplayBrightness("
572 + "id=" + displayId + ", brightness=" + brightness + ")");
573 }
574
575 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
576 + "id=" + displayId + ", brightness=" + brightness + ")");
577 try {
578 mBacklight.setBrightness(brightness);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100579 Trace.traceCounter(Trace.TRACE_TAG_POWER,
Michael Wrighta9f37ab2017-08-15 17:14:20 +0100580 "ScreenBrightness", brightness);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700581 } finally {
582 Trace.traceEnd(Trace.TRACE_TAG_POWER);
583 }
584 }
Jeff Browne75926d2014-09-18 15:24:49 -0700585 };
Jeff Brown037c33e2014-04-09 00:31:55 -0700586 }
Jeff Browne75926d2014-09-18 15:24:49 -0700587 return null;
Jeff Brown9e316a12012-10-08 19:17:06 -0700588 }
589
590 @Override
Robert Carrae606b42018-02-15 15:36:23 -0800591 public void requestDisplayModesLocked(int colorMode, int modeId) {
592 if (requestModeLocked(modeId) ||
593 requestColorModeLocked(colorMode)) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700594 updateDeviceInfoLocked();
595 }
596 }
597
Adrian Roos898ec382018-01-17 12:54:50 +0100598 @Override
599 public void onOverlayChangedLocked() {
600 updateDeviceInfoLocked();
601 }
602
Robert Carrae606b42018-02-15 15:36:23 -0800603 public boolean requestModeLocked(int modeId) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700604 if (modeId == 0) {
605 modeId = mDefaultModeId;
606 } else if (mSupportedModes.indexOfKey(modeId) < 0) {
607 Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
608 + " reverting to default display mode.");
609 modeId = mDefaultModeId;
610 }
Michael Wright58e829f2015-09-15 00:13:26 +0100611
Michael Wright1c9977b2016-07-12 13:30:10 -0700612 int physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100613 if (physIndex < 0) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700614 Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
615 + " trying with default mode ID");
Michael Wright58e829f2015-09-15 00:13:26 +0100616 modeId = mDefaultModeId;
Michael Wright1c9977b2016-07-12 13:30:10 -0700617 physIndex = findDisplayInfoIndexLocked(modeId);
Michael Wright58e829f2015-09-15 00:13:26 +0100618 }
Jorim Jaggi3b3cbb52015-09-24 17:35:58 -0700619 if (mActivePhysIndex == physIndex) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700620 return false;
Michael Wright3f145a22014-07-22 19:46:03 -0700621 }
Michael Wright58e829f2015-09-15 00:13:26 +0100622 SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
623 mActivePhysIndex = physIndex;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700624 mActiveModeId = modeId;
625 mActiveModeInvalid = false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700626 return true;
627 }
628
Robert Carrae606b42018-02-15 15:36:23 -0800629 public boolean requestColorModeLocked(int colorMode) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700630 if (mActiveColorMode == colorMode) {
631 return false;
632 }
633 if (!mSupportedColorModes.contains(colorMode)) {
634 Slog.w(TAG, "Unable to find color mode " + colorMode
635 + ", ignoring request.");
636 return false;
637 }
638 SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
639 mActiveColorMode = colorMode;
640 mActiveColorModeInvalid = false;
641 return true;
Michael Wright3f145a22014-07-22 19:46:03 -0700642 }
643
644 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700645 public void dumpLocked(PrintWriter pw) {
646 super.dumpLocked(pw);
647 pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
Michael Wright58e829f2015-09-15 00:13:26 +0100648 pw.println("mActivePhysIndex=" + mActivePhysIndex);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700649 pw.println("mActiveModeId=" + mActiveModeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700650 pw.println("mActiveColorMode=" + mActiveColorMode);
Jeff Brown037c33e2014-04-09 00:31:55 -0700651 pw.println("mState=" + Display.stateToString(mState));
Jeff Brown5d6443b2015-04-10 20:15:01 -0700652 pw.println("mBrightness=" + mBrightness);
653 pw.println("mBacklight=" + mBacklight);
Michael Wright58e829f2015-09-15 00:13:26 +0100654 pw.println("mDisplayInfos=");
655 for (int i = 0; i < mDisplayInfos.length; i++) {
656 pw.println(" " + mDisplayInfos[i]);
657 }
658 pw.println("mSupportedModes=");
659 for (int i = 0; i < mSupportedModes.size(); i++) {
660 pw.println(" " + mSupportedModes.valueAt(i));
661 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700662 pw.print("mSupportedColorModes=[");
663 for (int i = 0; i < mSupportedColorModes.size(); i++) {
Michael Wright58e829f2015-09-15 00:13:26 +0100664 if (i != 0) {
665 pw.print(", ");
666 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700667 pw.print(mSupportedColorModes.get(i));
Michael Wright58e829f2015-09-15 00:13:26 +0100668 }
669 pw.println("]");
670 }
671
Michael Wright1c9977b2016-07-12 13:30:10 -0700672 private int findDisplayInfoIndexLocked(int modeId) {
Michael Wright58e829f2015-09-15 00:13:26 +0100673 DisplayModeRecord record = mSupportedModes.get(modeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700674 if (record != null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100675 for (int i = 0; i < mDisplayInfos.length; i++) {
676 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
Michael Wright1c9977b2016-07-12 13:30:10 -0700677 if (record.hasMatchingMode(info)){
Michael Wright58e829f2015-09-15 00:13:26 +0100678 return i;
679 }
680 }
681 }
682 return -1;
Jeff Brown037c33e2014-04-09 00:31:55 -0700683 }
684
685 private void updateDeviceInfoLocked() {
686 mInfo = null;
687 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700688 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700689 }
Michael Wright3f145a22014-07-22 19:46:03 -0700690
Adrian Roos30f53212018-01-05 16:14:34 +0100691 /** Supplies a context whose Resources apply runtime-overlays */
692 Context getOverlayContext() {
693 return ActivityThread.currentActivityThread().getSystemUiContext();
694 }
695
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700696 /**
697 * Keeps track of a display configuration.
698 */
699 private static final class DisplayModeRecord {
700 public final Display.Mode mMode;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700701
Michael Wright58e829f2015-09-15 00:13:26 +0100702 public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700703 mMode = createMode(phys.width, phys.height, phys.refreshRate);
Michael Wright58e829f2015-09-15 00:13:26 +0100704 }
705
706 /**
707 * Returns whether the mode generated by the given PhysicalDisplayInfo matches the mode
708 * contained by the record modulo mode ID.
709 *
710 * Note that this doesn't necessarily mean the the PhysicalDisplayInfos are identical, just
711 * that they generate identical modes.
712 */
713 public boolean hasMatchingMode(SurfaceControl.PhysicalDisplayInfo info) {
714 int modeRefreshRate = Float.floatToIntBits(mMode.getRefreshRate());
715 int displayInfoRefreshRate = Float.floatToIntBits(info.refreshRate);
716 return mMode.getPhysicalWidth() == info.width
717 && mMode.getPhysicalHeight() == info.height
718 && modeRefreshRate == displayInfoRefreshRate;
719 }
720
721 public String toString() {
722 return "DisplayModeRecord{mMode=" + mMode + "}";
Michael Wright3f145a22014-07-22 19:46:03 -0700723 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700724 }
Jeff Browne87bf032012-09-20 18:30:13 -0700725
726 private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
727 public HotplugDisplayEventReceiver(Looper looper) {
Jorim Jaggi34a0cdb2017-06-08 15:40:38 -0700728 super(looper, VSYNC_SOURCE_APP);
Jeff Browne87bf032012-09-20 18:30:13 -0700729 }
730
731 @Override
732 public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
733 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800734 if (connected) {
735 tryConnectDisplayLocked(builtInDisplayId);
736 } else {
737 tryDisconnectDisplayLocked(builtInDisplayId);
738 }
Jeff Browne87bf032012-09-20 18:30:13 -0700739 }
740 }
741 }
Dan Stoza00101052014-05-02 15:23:40 -0700742}