blob: 308c755a08680c82b78453657abe59eb08c90aba [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;
Jeff Brown64a55af2012-08-26 02:47:39 -070020import android.content.Context;
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080021import android.content.res.Resources;
Chris Phoenixbc839a32017-10-21 14:46:15 -070022import android.hardware.sidekick.SidekickInternal;
Griff Hazend3c454d2016-03-25 07:30:34 -070023import android.os.Build;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070024import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070025import android.os.IBinder;
Jeff Browne87bf032012-09-20 18:30:13 -070026import android.os.Looper;
Jeff Brown5d6443b2015-04-10 20:15:01 -070027import android.os.PowerManager;
Jeff Brown27f1d672012-10-17 18:32:34 -070028import android.os.SystemProperties;
Jeff Brown3edf5272014-08-14 19:25:14 -070029import android.os.Trace;
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080030import android.util.LongSparseArray;
Dan Stoza00101052014-05-02 15:23:40 -070031import android.util.Slog;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070032import android.util.SparseArray;
Jeff Brown92130f62012-10-24 21:28:33 -070033import android.view.Display;
Dominik Laskowskidb845962019-01-27 21:20:00 -080034import android.view.DisplayAddress;
Adrian Roos1cf585052018-01-03 18:43:27 +010035import android.view.DisplayCutout;
Jeff Browne87bf032012-09-20 18:30:13 -070036import android.view.DisplayEventReceiver;
Jeff Brown64a55af2012-08-26 02:47:39 -070037import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080038import android.view.SurfaceControl;
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080039
40import com.android.server.LocalServices;
41import com.android.server.lights.Light;
42import com.android.server.lights.LightsManager;
43
Jeff Brown4ed8fe72012-08-30 18:18:29 -070044import java.io.PrintWriter;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070045import java.util.ArrayList;
Michael Wright58e829f2015-09-15 00:13:26 +010046import java.util.Arrays;
Michael Wright1c9977b2016-07-12 13:30:10 -070047import java.util.Collections;
48import java.util.List;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070049
Jeff Brown64a55af2012-08-26 02:47:39 -070050/**
51 * A display adapter for the local displays managed by Surface Flinger.
Jeff Brownbd6e1502012-08-28 03:27:37 -070052 * <p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070053 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
Jeff Brownbd6e1502012-08-28 03:27:37 -070054 * </p>
Jeff Brown64a55af2012-08-26 02:47:39 -070055 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -070056final class LocalDisplayAdapter extends DisplayAdapter {
Jeff Brownbd6e1502012-08-28 03:27:37 -070057 private static final String TAG = "LocalDisplayAdapter";
Jeff Brown5d6443b2015-04-10 20:15:01 -070058 private static final boolean DEBUG = false;
Jeff Brown64a55af2012-08-26 02:47:39 -070059
Wale Ogunwale361ca212014-11-20 11:42:38 -080060 private static final String UNIQUE_ID_PREFIX = "local:";
61
Adam Powell01f280d2015-05-18 16:07:42 -070062 private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
63
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080064 private final LongSparseArray<LocalDisplayDevice> mDevices =
65 new LongSparseArray<LocalDisplayDevice>();
Jeff Brown4ed8fe72012-08-30 18:18:29 -070066
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -070067 @SuppressWarnings("unused") // Becomes active at instantiation time.
Ady Abrahama5a21f72019-02-13 16:41:59 -080068 private PhysicalDisplayEventReceiver mPhysicalDisplayEventReceiver;
69
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
Ady Abrahama5a21f72019-02-13 16:41:59 -080081 mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
Jesse Halle244db42012-11-08 11:55:14 -080082
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080083 for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
84 tryConnectDisplayLocked(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -080085 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -070086 }
87
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080088 private void tryConnectDisplayLocked(long physicalDisplayId) {
89 final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
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
Dominik Laskowski3316a0a2019-01-25 02:56:41 -080095 Slog.w(TAG, "No valid configs found for display device " + physicalDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -070096 return;
97 }
98 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
99 if (activeConfig < 0) {
100 // There is no active config, and for now we don't have the
101 // policy to set one.
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800102 Slog.w(TAG, "No active config found for display device " + physicalDisplayId);
Dan Stoza00101052014-05-02 15:23:40 -0700103 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 " +
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800111 physicalDisplayId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700112 activeColorMode = Display.COLOR_MODE_INVALID;
113 }
114 int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
Michael Wrighta3dab232019-02-22 16:54:21 +0000115 int[] allowedConfigs = SurfaceControl.getAllowedDisplayConfigs(displayToken);
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800116 LocalDisplayDevice device = mDevices.get(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -0800117 if (device == null) {
118 // Display was added.
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800119 final boolean isInternal = mDevices.size() == 0;
120 device = new LocalDisplayDevice(displayToken, physicalDisplayId,
Michael Wrighta3dab232019-02-22 16:54:21 +0000121 configs, activeConfig, allowedConfigs, colorModes, activeColorMode,
122 isInternal);
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800123 mDevices.put(physicalDisplayId, device);
Jesse Halle244db42012-11-08 11:55:14 -0800124 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
Michael Wright1c9977b2016-07-12 13:30:10 -0700125 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
Michael Wrighta3dab232019-02-22 16:54:21 +0000126 allowedConfigs, colorModes, activeColorMode)) {
Jesse Halle244db42012-11-08 11:55:14 -0800127 // Display properties changed.
128 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700129 }
Jesse Halle244db42012-11-08 11:55:14 -0800130 } else {
131 // The display is no longer available. Ignore the attempt to add it.
132 // If it was connected but has already been disconnected, we'll get a
133 // disconnect event that will remove it from mDevices.
134 }
135 }
136
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800137 private void tryDisconnectDisplayLocked(long physicalDisplayId) {
138 LocalDisplayDevice device = mDevices.get(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -0800139 if (device != null) {
140 // Display was removed.
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800141 mDevices.remove(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -0800142 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700143 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700144 }
145
Prashant Malanic55929a2014-05-25 01:59:21 -0700146 static int getPowerModeForState(int state) {
147 switch (state) {
148 case Display.STATE_OFF:
149 return SurfaceControl.POWER_MODE_OFF;
Jeff Brown5dc21912014-07-17 18:50:18 -0700150 case Display.STATE_DOZE:
Prashant Malanic55929a2014-05-25 01:59:21 -0700151 return SurfaceControl.POWER_MODE_DOZE;
Jeff Brown5dc21912014-07-17 18:50:18 -0700152 case Display.STATE_DOZE_SUSPEND:
153 return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700154 case Display.STATE_ON_SUSPEND:
155 return SurfaceControl.POWER_MODE_ON_SUSPEND;
Prashant Malanic55929a2014-05-25 01:59:21 -0700156 default:
157 return SurfaceControl.POWER_MODE_NORMAL;
158 }
Jeff Brown44b1f762014-04-22 18:07:24 -0700159 }
160
Jeff Brown64a55af2012-08-26 02:47:39 -0700161 private final class LocalDisplayDevice extends DisplayDevice {
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800162 private final long mPhysicalDisplayId;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700163 private final Light mBacklight;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700164 private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
Michael Wright1c9977b2016-07-12 13:30:10 -0700165 private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800166 private final boolean mIsInternal;
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;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700172 private int mDefaultModeId;
173 private int mActiveModeId;
174 private boolean mActiveModeInvalid;
Michael Wrighta3dab232019-02-22 16:54:21 +0000175 private int[] mAllowedModeIds;
Ana Krulec4f753aa2019-11-14 00:49:39 +0100176 private float mMinRefreshRate;
177 private float mMaxRefreshRate;
Michael Wrighta3dab232019-02-22 16:54:21 +0000178 private boolean mAllowedModeIdsInvalid;
179 private int mActivePhysIndex;
180 private int[] mAllowedPhysIndexes;
Michael Wright1c9977b2016-07-12 13:30:10 -0700181 private int mActiveColorMode;
182 private boolean mActiveColorModeInvalid;
Michael Wright9ff94c02016-03-30 18:05:40 -0700183 private Display.HdrCapabilities mHdrCapabilities;
Chris Phoenixbc839a32017-10-21 14:46:15 -0700184 private boolean mSidekickActive;
185 private SidekickInternal mSidekickInternal;
Michael Wright58e829f2015-09-15 00:13:26 +0100186
Michael Wrighta3dab232019-02-22 16:54:21 +0000187 private SurfaceControl.PhysicalDisplayInfo[] mDisplayInfos;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700188
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800189 LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
Michael Wright1c9977b2016-07-12 13:30:10 -0700190 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
Michael Wrighta3dab232019-02-22 16:54:21 +0000191 int[] allowedDisplayInfos, int[] colorModes, int activeColorMode,
192 boolean isInternal) {
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800193 super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
194 mPhysicalDisplayId = physicalDisplayId;
195 mIsInternal = isInternal;
Michael Wright1c9977b2016-07-12 13:30:10 -0700196 updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
Michael Wrighta3dab232019-02-22 16:54:21 +0000197 allowedDisplayInfos, colorModes, activeColorMode);
Michael Wright1c9977b2016-07-12 13:30:10 -0700198 updateColorModesLocked(colorModes, activeColorMode);
Chris Phoenixbc839a32017-10-21 14:46:15 -0700199 mSidekickInternal = LocalServices.getService(SidekickInternal.class);
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800200 if (mIsInternal) {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700201 LightsManager lights = LocalServices.getService(LightsManager.class);
202 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
203 } else {
204 mBacklight = null;
205 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700206 mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700207 }
208
Michael Wright1c9977b2016-07-12 13:30:10 -0700209 @Override
210 public boolean hasStableUniqueId() {
211 return true;
212 }
213
Michael Wright3f145a22014-07-22 19:46:03 -0700214 public boolean updatePhysicalDisplayInfoLocked(
Michael Wright1c9977b2016-07-12 13:30:10 -0700215 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
Michael Wrighta3dab232019-02-22 16:54:21 +0000216 int[] allowedDisplayInfos, int[] colorModes, int activeColorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100217 mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
218 mActivePhysIndex = activeDisplayInfo;
Michael Wrighta3dab232019-02-22 16:54:21 +0000219 mAllowedPhysIndexes = Arrays.copyOf(allowedDisplayInfos, allowedDisplayInfos.length);
Michael Wright58e829f2015-09-15 00:13:26 +0100220 // Build an updated list of all existing modes.
221 ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
222 boolean modesAdded = false;
223 for (int i = 0; i < physicalDisplayInfos.length; i++) {
224 SurfaceControl.PhysicalDisplayInfo info = physicalDisplayInfos[i];
225 // First, check to see if we've already added a matching mode. Since not all
226 // configuration options are exposed via Display.Mode, it's possible that we have
227 // multiple PhysicalDisplayInfos that would generate the same Display.Mode.
228 boolean existingMode = false;
229 for (int j = 0; j < records.size(); j++) {
230 if (records.get(j).hasMatchingMode(info)) {
231 existingMode = true;
232 break;
233 }
234 }
235 if (existingMode) {
236 continue;
237 }
238 // If we haven't already added a mode for this configuration to the new set of
239 // supported modes then check to see if we have one in the prior set of supported
240 // modes to reuse.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700241 DisplayModeRecord record = findDisplayModeRecord(info);
Michael Wright58e829f2015-09-15 00:13:26 +0100242 if (record == null) {
243 record = new DisplayModeRecord(info);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700244 modesAdded = true;
245 }
246 records.add(record);
Michael Wright58e829f2015-09-15 00:13:26 +0100247 }
248
249 // Get the currently active mode
250 DisplayModeRecord activeRecord = null;
251 for (int i = 0; i < records.size(); i++) {
252 DisplayModeRecord record = records.get(i);
253 if (record.hasMatchingMode(physicalDisplayInfos[activeDisplayInfo])){
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700254 activeRecord = record;
Michael Wright58e829f2015-09-15 00:13:26 +0100255 break;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700256 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700257 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000258
259 // Check whether surface flinger spontaneously changed modes out from under us.
260 // Schedule traversals to ensure that the correct state is reapplied if necessary.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700261 if (mActiveModeId != 0
262 && mActiveModeId != activeRecord.mMode.getModeId()) {
263 mActiveModeInvalid = true;
264 sendTraversalRequestLocked();
265 }
Michael Wright58e829f2015-09-15 00:13:26 +0100266
Michael Wright58e829f2015-09-15 00:13:26 +0100267 boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
Michael Wright1c9977b2016-07-12 13:30:10 -0700268 // If the records haven't changed then we're done here.
269 if (!recordsChanged) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700270 return false;
271 }
272 // Update the index of modes.
273 mHavePendingChanges = true;
Michael Wright58e829f2015-09-15 00:13:26 +0100274
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700275 mSupportedModes.clear();
276 for (DisplayModeRecord record : records) {
277 mSupportedModes.put(record.mMode.getModeId(), record);
278 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000279
Michael Wright1c9977b2016-07-12 13:30:10 -0700280 // Update the default mode, if needed.
281 if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700282 if (mDefaultModeId != 0) {
Michael Wright58e829f2015-09-15 00:13:26 +0100283 Slog.w(TAG, "Default display mode no longer available, using currently"
284 + " active mode as default.");
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700285 }
286 mDefaultModeId = activeRecord.mMode.getModeId();
287 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000288
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700289 // Determine whether the active mode is still there.
290 if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
291 if (mActiveModeId != 0) {
292 Slog.w(TAG, "Active display mode no longer available, reverting to default"
293 + " mode.");
294 }
295 mActiveModeId = mDefaultModeId;
296 mActiveModeInvalid = true;
297 }
Michael Wright58e829f2015-09-15 00:13:26 +0100298
Michael Wrighta3dab232019-02-22 16:54:21 +0000299 // Determine what the currently allowed modes are
300 mAllowedModeIds = new int[] { mActiveModeId };
301 int[] allowedModeIds = new int[mAllowedPhysIndexes.length];
302 int size = 0;
303 for (int physIndex : mAllowedPhysIndexes) {
304 int modeId = findMatchingModeIdLocked(physIndex);
305 if (modeId > 0) {
306 allowedModeIds[size++] = modeId;
307 }
308 }
309
310 // If this is different from our desired allowed modes, then mark our current set as
311 // invalid so we correct this on the next traversal.
312 mAllowedModeIdsInvalid = !Arrays.equals(allowedModeIds, mAllowedModeIds);
313
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700314 // Schedule traversals so that we apply pending changes.
315 sendTraversalRequestLocked();
316 return true;
317 }
318
Michael Wright1c9977b2016-07-12 13:30:10 -0700319 private boolean updateColorModesLocked(int[] colorModes,
320 int activeColorMode) {
321 List<Integer> pendingColorModes = new ArrayList<>();
322
thecrazyskullb34c81042016-12-18 12:48:20 -0500323 if (colorModes == null) return false;
Michael Wright1c9977b2016-07-12 13:30:10 -0700324 // Build an updated list of all existing color modes.
325 boolean colorModesAdded = false;
326 for (int colorMode: colorModes) {
327 if (!mSupportedColorModes.contains(colorMode)) {
328 colorModesAdded = true;
329 }
330 pendingColorModes.add(colorMode);
331 }
332
333 boolean colorModesChanged =
334 pendingColorModes.size() != mSupportedColorModes.size()
335 || colorModesAdded;
336
337 // If the supported color modes haven't changed then we're done here.
338 if (!colorModesChanged) {
339 return false;
340 }
341
342 mHavePendingChanges = true;
343
344 mSupportedColorModes.clear();
345 mSupportedColorModes.addAll(pendingColorModes);
346 Collections.sort(mSupportedColorModes);
347
348 // Determine whether the active color mode is still there.
349 if (!mSupportedColorModes.contains(mActiveColorMode)) {
350 if (mActiveColorMode != 0) {
351 Slog.w(TAG, "Active color mode no longer available, reverting"
352 + " to default mode.");
353 mActiveColorMode = Display.COLOR_MODE_DEFAULT;
354 mActiveColorModeInvalid = true;
355 } else {
356 if (!mSupportedColorModes.isEmpty()) {
357 // This should never happen.
358 Slog.e(TAG, "Default and active color mode is no longer available!"
359 + " Reverting to first available mode.");
360 mActiveColorMode = mSupportedColorModes.get(0);
361 mActiveColorModeInvalid = true;
362 } else {
363 // This should really never happen.
364 Slog.e(TAG, "No color modes available!");
365 }
366 }
367 }
368 return true;
369 }
370
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700371 private DisplayModeRecord findDisplayModeRecord(SurfaceControl.PhysicalDisplayInfo info) {
372 for (int i = 0; i < mSupportedModes.size(); i++) {
373 DisplayModeRecord record = mSupportedModes.valueAt(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100374 if (record.hasMatchingMode(info)) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700375 return record;
376 }
377 }
378 return null;
Jeff Brown64a55af2012-08-26 02:47:39 -0700379 }
380
381 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700382 public void applyPendingDisplayDeviceInfoChangesLocked() {
383 if (mHavePendingChanges) {
384 mInfo = null;
385 mHavePendingChanges = false;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700386 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700387 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700388
389 @Override
390 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
391 if (mInfo == null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100392 SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700393 mInfo = new DisplayDeviceInfo();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700394 mInfo.width = phys.width;
395 mInfo.height = phys.height;
396 mInfo.modeId = mActiveModeId;
397 mInfo.defaultModeId = mDefaultModeId;
Michael Wrighta3dab232019-02-22 16:54:21 +0000398 mInfo.supportedModes = getDisplayModes(mSupportedModes);
Michael Wright1c9977b2016-07-12 13:30:10 -0700399 mInfo.colorMode = mActiveColorMode;
400 mInfo.supportedColorModes =
401 new int[mSupportedColorModes.size()];
402 for (int i = 0; i < mSupportedColorModes.size(); i++) {
403 mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
Michael Wright58e829f2015-09-15 00:13:26 +0100404 }
Michael Wright9ff94c02016-03-30 18:05:40 -0700405 mInfo.hdrCapabilities = mHdrCapabilities;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700406 mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
407 mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
Jeff Brown037c33e2014-04-09 00:31:55 -0700408 mInfo.state = mState;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800409 mInfo.uniqueId = getUniqueId();
Keun young Parkabf38e32019-04-23 19:18:34 -0700410 final DisplayAddress.Physical physicalAddress =
411 DisplayAddress.fromPhysicalDisplayId(mPhysicalDisplayId);
412 mInfo.address = physicalAddress;
Daichi Hirono1eb2a912019-11-14 16:23:15 +0900413 mInfo.densityDpi = (int) (phys.density * 160 + 0.5f);
414 mInfo.xDpi = phys.xDpi;
415 mInfo.yDpi = phys.yDpi;
Jeff Brown77aebfd2012-10-01 21:07:03 -0700416
Jeff Brownf0681b32012-10-23 17:35:57 -0700417 // Assume that all built-in displays that have secure output (eg. HDCP) also
Jeff Brown77aebfd2012-10-01 21:07:03 -0700418 // support compositing from gralloc protected buffers.
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700419 if (phys.secure) {
Jeff Brownf0681b32012-10-23 17:35:57 -0700420 mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
421 | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
422 }
Jeff Brown77aebfd2012-10-01 21:07:03 -0700423
Adrian Roos30f53212018-01-05 16:14:34 +0100424 final Resources res = getOverlayContext().getResources();
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800425 if (mIsInternal) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700426 mInfo.name = res.getString(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700427 com.android.internal.R.string.display_manager_built_in_display_name);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700428 mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
Jeff Brown27f1d672012-10-17 18:32:34 -0700429 | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
Adam Powell01f280d2015-05-18 16:07:42 -0700430 if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
Griff Hazend3c454d2016-03-25 07:30:34 -0700431 || (Build.IS_EMULATOR
Adam Powell01f280d2015-05-18 16:07:42 -0700432 && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
Adam Powell49e7ff92015-05-14 16:18:53 -0700433 mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
434 }
Adrian Roos8c28c7c2018-08-20 13:43:38 +0200435 if (res.getBoolean(
436 com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) {
437 mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT;
438 }
Jorim Jaggi60640512018-06-29 01:14:31 +0200439 mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
440 mInfo.width, mInfo.height);
Jeff Brown92130f62012-10-24 21:28:33 -0700441 mInfo.type = Display.TYPE_BUILT_IN;
Jeff Brownd728bf52012-09-08 18:05:28 -0700442 mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700443 } else {
Adrian Roos1cf585052018-01-03 18:43:27 +0100444 mInfo.displayCutout = null;
Jeff Brown92130f62012-10-24 21:28:33 -0700445 mInfo.type = Display.TYPE_HDMI;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700446 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700447 mInfo.name = getContext().getResources().getString(
448 com.android.internal.R.string.display_manager_hdmi_display_name);
Jeff Brownd728bf52012-09-08 18:05:28 -0700449 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
Jeff Brown27f1d672012-10-17 18:32:34 -0700450
451 // For demonstration purposes, allow rotation of the external display.
452 // In the future we might allow the user to configure this directly.
453 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
454 mInfo.rotation = Surface.ROTATION_270;
455 }
Scott Anderson8786ed92013-11-01 13:27:39 -0700456
457 // For demonstration purposes, allow rotation of the external display
458 // to follow the built-in display.
459 if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
460 mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
461 }
Michael Wright4b0fa172016-03-11 17:15:24 -0800462
463 if (!res.getBoolean(
464 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
465 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
466 }
Pavel Maltseva6fec7b2018-04-04 10:14:55 -0700467
Keun young Parkabf38e32019-04-23 19:18:34 -0700468 if (isDisplayPrivate(physicalAddress)) {
Pavel Maltseva6fec7b2018-04-04 10:14:55 -0700469 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE;
470 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700471 }
472 }
473 return mInfo;
474 }
475
476 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700477 public Runnable requestDisplayStateLocked(final int state, final int brightness) {
478 // Assume that the brightness is off if the display is being turned off.
479 assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
480
481 final boolean stateChanged = (mState != state);
482 final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
483 if (stateChanged || brightnessChanged) {
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800484 final long physicalDisplayId = mPhysicalDisplayId;
Jeff Browne75926d2014-09-18 15:24:49 -0700485 final IBinder token = getDisplayTokenLocked();
Jeff Brown5d6443b2015-04-10 20:15:01 -0700486 final int oldState = mState;
Jeff Browne75926d2014-09-18 15:24:49 -0700487
Jeff Brown5d6443b2015-04-10 20:15:01 -0700488 if (stateChanged) {
489 mState = state;
490 updateDeviceInfoLocked();
491 }
492
493 if (brightnessChanged) {
494 mBrightness = brightness;
495 }
496
497 // Defer actually setting the display state until after we have exited
Jeff Browne75926d2014-09-18 15:24:49 -0700498 // the critical section since it can take hundreds of milliseconds
499 // to complete.
500 return new Runnable() {
501 @Override
502 public void run() {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700503 // Exit a suspended state before making any changes.
504 int currentState = oldState;
505 if (Display.isSuspendedState(oldState)
506 || oldState == Display.STATE_UNKNOWN) {
507 if (!Display.isSuspendedState(state)) {
508 setDisplayState(state);
509 currentState = state;
510 } else if (state == Display.STATE_DOZE_SUSPEND
511 || oldState == Display.STATE_DOZE_SUSPEND) {
512 setDisplayState(Display.STATE_DOZE);
513 currentState = Display.STATE_DOZE;
Chris Phoenix10a4a642017-09-25 13:21:00 -0700514 } else if (state == Display.STATE_ON_SUSPEND
515 || oldState == Display.STATE_ON_SUSPEND) {
516 setDisplayState(Display.STATE_ON);
517 currentState = Display.STATE_ON;
Jeff Brown5d6443b2015-04-10 20:15:01 -0700518 } else {
519 return; // old state and new state is off
520 }
521 }
522
Santos Cordond6a56602016-09-20 15:50:35 -0700523 // If the state change was from or to VR, then we need to tell the light
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700524 // so that it can apply appropriate VR brightness settings. Also, update the
525 // brightness so the state is propogated to light.
526 boolean vrModeChange = false;
Santos Cordond6a56602016-09-20 15:50:35 -0700527 if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
528 currentState != state) {
529 setVrMode(state == Display.STATE_VR);
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700530 vrModeChange = true;
Santos Cordond6a56602016-09-20 15:50:35 -0700531 }
532
533
Jeff Brown5d6443b2015-04-10 20:15:01 -0700534 // Apply brightness changes given that we are in a non-suspended state.
Karthik Ravi Shankar66855312017-10-04 13:30:13 -0700535 if (brightnessChanged || vrModeChange) {
Jeff Brown5d6443b2015-04-10 20:15:01 -0700536 setDisplayBrightness(brightness);
537 }
538
539 // Enter the final desired state, possibly suspended.
540 if (state != currentState) {
541 setDisplayState(state);
542 }
543 }
544
Santos Cordond6a56602016-09-20 15:50:35 -0700545 private void setVrMode(boolean isVrEnabled) {
546 if (DEBUG) {
547 Slog.d(TAG, "setVrMode("
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800548 + "id=" + physicalDisplayId
Santos Cordond6a56602016-09-20 15:50:35 -0700549 + ", state=" + Display.stateToString(state) + ")");
550 }
551 mBacklight.setVrMode(isVrEnabled);
552 }
553
Jeff Brown5d6443b2015-04-10 20:15:01 -0700554 private void setDisplayState(int state) {
555 if (DEBUG) {
556 Slog.d(TAG, "setDisplayState("
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800557 + "id=" + physicalDisplayId
Jeff Brown5d6443b2015-04-10 20:15:01 -0700558 + ", state=" + Display.stateToString(state) + ")");
559 }
560
Chris Phoenixbc839a32017-10-21 14:46:15 -0700561 // We must tell sidekick to stop controlling the display before we
562 // can change its power mode, so do that first.
563 if (mSidekickActive) {
564 Trace.traceBegin(Trace.TRACE_TAG_POWER,
565 "SidekickInternal#endDisplayControl");
566 try {
567 mSidekickInternal.endDisplayControl();
568 } finally {
569 Trace.traceEnd(Trace.TRACE_TAG_POWER);
570 }
571 mSidekickActive = false;
572 }
573 final int mode = getPowerModeForState(state);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700574 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800575 + "id=" + physicalDisplayId
Jeff Brown5d6443b2015-04-10 20:15:01 -0700576 + ", state=" + Display.stateToString(state) + ")");
Jeff Browne75926d2014-09-18 15:24:49 -0700577 try {
578 SurfaceControl.setDisplayPowerMode(token, mode);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100579 Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
Jeff Browne75926d2014-09-18 15:24:49 -0700580 } finally {
581 Trace.traceEnd(Trace.TRACE_TAG_POWER);
582 }
Chris Phoenixbc839a32017-10-21 14:46:15 -0700583 // If we're entering a suspended (but not OFF) power state and we
584 // have a sidekick available, tell it now that it can take control.
585 if (Display.isSuspendedState(state) && state != Display.STATE_OFF
586 && mSidekickInternal != null && !mSidekickActive) {
587 Trace.traceBegin(Trace.TRACE_TAG_POWER,
588 "SidekickInternal#startDisplayControl");
589 try {
590 mSidekickActive = mSidekickInternal.startDisplayControl(state);
591 } finally {
592 Trace.traceEnd(Trace.TRACE_TAG_POWER);
593 }
594 }
Jeff Browne75926d2014-09-18 15:24:49 -0700595 }
Jeff Brown5d6443b2015-04-10 20:15:01 -0700596
597 private void setDisplayBrightness(int brightness) {
598 if (DEBUG) {
599 Slog.d(TAG, "setDisplayBrightness("
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800600 + "id=" + physicalDisplayId
601 + ", brightness=" + brightness + ")");
Jeff Brown5d6443b2015-04-10 20:15:01 -0700602 }
603
604 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800605 + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
Jeff Brown5d6443b2015-04-10 20:15:01 -0700606 try {
607 mBacklight.setBrightness(brightness);
Michael Wrightc3e6af82017-07-25 22:31:03 +0100608 Trace.traceCounter(Trace.TRACE_TAG_POWER,
Michael Wrighta9f37ab2017-08-15 17:14:20 +0100609 "ScreenBrightness", brightness);
Jeff Brown5d6443b2015-04-10 20:15:01 -0700610 } finally {
611 Trace.traceEnd(Trace.TRACE_TAG_POWER);
612 }
613 }
Jeff Browne75926d2014-09-18 15:24:49 -0700614 };
Jeff Brown037c33e2014-04-09 00:31:55 -0700615 }
Jeff Browne75926d2014-09-18 15:24:49 -0700616 return null;
Jeff Brown9e316a12012-10-08 19:17:06 -0700617 }
618
619 @Override
Michael Wrighta3dab232019-02-22 16:54:21 +0000620 public void setRequestedColorModeLocked(int colorMode) {
621 if (requestColorModeLocked(colorMode)) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700622 updateDeviceInfoLocked();
623 }
624 }
625
Adrian Roos898ec382018-01-17 12:54:50 +0100626 @Override
Ana Krulec4f753aa2019-11-14 00:49:39 +0100627 public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
628 float maxRefreshRate, int[] modes) {
629 updateDesiredDisplayConfigSpecs(defaultModeId, minRefreshRate, maxRefreshRate);
Michael Wrighta3dab232019-02-22 16:54:21 +0000630 updateAllowedModesLocked(modes);
631 }
632
633 @Override
Adrian Roos898ec382018-01-17 12:54:50 +0100634 public void onOverlayChangedLocked() {
635 updateDeviceInfoLocked();
636 }
637
Michael Wrighta3dab232019-02-22 16:54:21 +0000638 public void onActivePhysicalDisplayModeChangedLocked(int physIndex) {
639 if (updateActiveModeLocked(physIndex)) {
640 updateDeviceInfoLocked();
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700641 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000642 }
Michael Wright58e829f2015-09-15 00:13:26 +0100643
Michael Wrighta3dab232019-02-22 16:54:21 +0000644 public boolean updateActiveModeLocked(int activePhysIndex) {
645 if (mActivePhysIndex == activePhysIndex) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700646 return false;
Michael Wright3f145a22014-07-22 19:46:03 -0700647 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000648 mActivePhysIndex = activePhysIndex;
649 mActiveModeId = findMatchingModeIdLocked(activePhysIndex);
650 mActiveModeInvalid = mActiveModeId == 0;
651 if (mActiveModeInvalid) {
652 Slog.w(TAG, "In unknown mode after setting allowed configs"
653 + ": allowedPhysIndexes=" + mAllowedPhysIndexes
654 + ", activePhysIndex=" + mActivePhysIndex);
655 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700656 return true;
657 }
658
Ana Krulec4f753aa2019-11-14 00:49:39 +0100659 // TODO(b/142507213): Remove once refresh rates are plummed through to kernel.
Michael Wrighta3dab232019-02-22 16:54:21 +0000660 public void updateAllowedModesLocked(int[] allowedModes) {
661 if (Arrays.equals(allowedModes, mAllowedModeIds) && !mAllowedModeIdsInvalid) {
662 return;
663 }
664 if (updateAllowedModesInternalLocked(allowedModes)) {
665 updateDeviceInfoLocked();
666 }
667 }
668
Ana Krulec4f753aa2019-11-14 00:49:39 +0100669 public void updateDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
670 float maxRefreshRate) {
671 if (minRefreshRate == mMinRefreshRate
672 && maxRefreshRate == mMaxRefreshRate
673 && defaultModeId == mDefaultModeId) {
674 return;
675 }
676 if (updateDesiredDisplayConfigSpecsInternalLocked(defaultModeId, minRefreshRate,
677 maxRefreshRate)) {
678 updateDeviceInfoLocked();
679 }
680 }
681
682 public boolean updateDesiredDisplayConfigSpecsInternalLocked(int defaultModeId,
683 float minRefreshRate, float maxRefreshRate) {
684 if (DEBUG) {
685 Slog.w(TAG, "updateDesiredDisplayConfigSpecsInternalLocked("
686 + "defaultModeId="
687 + Integer.toString(defaultModeId)
688 + ", minRefreshRate="
689 + Float.toString(minRefreshRate)
690 + ", maxRefreshRate="
691 + Float.toString(minRefreshRate));
692 }
693
694 final IBinder token = getDisplayTokenLocked();
Ana Krulec52f12892019-11-18 03:57:20 -0800695 SurfaceControl.setDesiredDisplayConfigSpecs(token,
696 new SurfaceControl.DesiredDisplayConfigSpecs(
697 defaultModeId, minRefreshRate, maxRefreshRate));
Ana Krulec4f753aa2019-11-14 00:49:39 +0100698 int activePhysIndex = SurfaceControl.getActiveConfig(token);
699 return updateActiveModeLocked(activePhysIndex);
700 }
701
Michael Wrighta3dab232019-02-22 16:54:21 +0000702 public boolean updateAllowedModesInternalLocked(int[] allowedModes) {
703 if (DEBUG) {
704 Slog.w(TAG, "updateAllowedModesInternalLocked(allowedModes="
705 + Arrays.toString(allowedModes) + ")");
706 }
707 int[] allowedPhysIndexes = new int[allowedModes.length];
708 int size = 0;
709 for (int modeId : allowedModes) {
710 int physIndex = findDisplayInfoIndexLocked(modeId);
711 if (physIndex < 0) {
712 Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
713 + " dropping from allowed set.");
714 } else {
715 allowedPhysIndexes[size++] = physIndex;
716 }
717 }
718
719 // If we couldn't find one or more of the suggested allowed modes then we need to
720 // shrink the array to its actual size.
721 if (size != allowedModes.length) {
722 allowedPhysIndexes = Arrays.copyOf(allowedPhysIndexes, size);
723 }
724
725 // If we found no suitable modes, then we try again with the default mode which we
726 // assume has a suitable physical config.
727 if (size == 0) {
728 if (DEBUG) {
729 Slog.w(TAG, "No valid modes allowed, falling back to default mode (id="
730 + mDefaultModeId + ")");
731 }
732 allowedModes = new int[] { mDefaultModeId };
733 allowedPhysIndexes = new int[] { findDisplayInfoIndexLocked(mDefaultModeId) };
734 }
735
736 mAllowedModeIds = allowedModes;
737 mAllowedModeIdsInvalid = false;
738
739 if (Arrays.equals(mAllowedPhysIndexes, allowedPhysIndexes)) {
740 return false;
741 }
742 mAllowedPhysIndexes = allowedPhysIndexes;
743
744 if (DEBUG) {
745 Slog.w(TAG, "Setting allowed physical configs: allowedPhysIndexes="
746 + Arrays.toString(allowedPhysIndexes));
747 }
748
749 SurfaceControl.setAllowedDisplayConfigs(getDisplayTokenLocked(), allowedPhysIndexes);
750 int activePhysIndex = SurfaceControl.getActiveConfig(getDisplayTokenLocked());
751 return updateActiveModeLocked(activePhysIndex);
752 }
753
Robert Carrae606b42018-02-15 15:36:23 -0800754 public boolean requestColorModeLocked(int colorMode) {
Michael Wright1c9977b2016-07-12 13:30:10 -0700755 if (mActiveColorMode == colorMode) {
756 return false;
757 }
758 if (!mSupportedColorModes.contains(colorMode)) {
759 Slog.w(TAG, "Unable to find color mode " + colorMode
760 + ", ignoring request.");
761 return false;
762 }
763 SurfaceControl.setActiveColorMode(getDisplayTokenLocked(), colorMode);
764 mActiveColorMode = colorMode;
765 mActiveColorModeInvalid = false;
766 return true;
Michael Wright3f145a22014-07-22 19:46:03 -0700767 }
768
769 @Override
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700770 public void dumpLocked(PrintWriter pw) {
771 super.dumpLocked(pw);
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800772 pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
Michael Wrighta3dab232019-02-22 16:54:21 +0000773 pw.println("mAllowedPhysIndexes=" + Arrays.toString(mAllowedPhysIndexes));
774 pw.println("mAllowedModeIds=" + Arrays.toString(mAllowedModeIds));
Ana Krulec4f753aa2019-11-14 00:49:39 +0100775 pw.println("mMinRefreshRate=" + mMinRefreshRate);
776 pw.println("mMaxRefreshRate=" + mMaxRefreshRate);
Michael Wrighta3dab232019-02-22 16:54:21 +0000777 pw.println("mAllowedModeIdsInvalid=" + mAllowedModeIdsInvalid);
Michael Wright58e829f2015-09-15 00:13:26 +0100778 pw.println("mActivePhysIndex=" + mActivePhysIndex);
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700779 pw.println("mActiveModeId=" + mActiveModeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700780 pw.println("mActiveColorMode=" + mActiveColorMode);
Michael Wrighta3dab232019-02-22 16:54:21 +0000781 pw.println("mDefaultModeId=" + mDefaultModeId);
Jeff Brown037c33e2014-04-09 00:31:55 -0700782 pw.println("mState=" + Display.stateToString(mState));
Jeff Brown5d6443b2015-04-10 20:15:01 -0700783 pw.println("mBrightness=" + mBrightness);
784 pw.println("mBacklight=" + mBacklight);
Michael Wright58e829f2015-09-15 00:13:26 +0100785 pw.println("mDisplayInfos=");
786 for (int i = 0; i < mDisplayInfos.length; i++) {
787 pw.println(" " + mDisplayInfos[i]);
788 }
789 pw.println("mSupportedModes=");
790 for (int i = 0; i < mSupportedModes.size(); i++) {
791 pw.println(" " + mSupportedModes.valueAt(i));
792 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700793 pw.print("mSupportedColorModes=[");
794 for (int i = 0; i < mSupportedColorModes.size(); i++) {
Michael Wright58e829f2015-09-15 00:13:26 +0100795 if (i != 0) {
796 pw.print(", ");
797 }
Michael Wright1c9977b2016-07-12 13:30:10 -0700798 pw.print(mSupportedColorModes.get(i));
Michael Wright58e829f2015-09-15 00:13:26 +0100799 }
800 pw.println("]");
801 }
802
Michael Wright1c9977b2016-07-12 13:30:10 -0700803 private int findDisplayInfoIndexLocked(int modeId) {
Michael Wright58e829f2015-09-15 00:13:26 +0100804 DisplayModeRecord record = mSupportedModes.get(modeId);
Michael Wright1c9977b2016-07-12 13:30:10 -0700805 if (record != null) {
Michael Wright58e829f2015-09-15 00:13:26 +0100806 for (int i = 0; i < mDisplayInfos.length; i++) {
807 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[i];
Michael Wright1c9977b2016-07-12 13:30:10 -0700808 if (record.hasMatchingMode(info)){
Michael Wright58e829f2015-09-15 00:13:26 +0100809 return i;
810 }
811 }
812 }
813 return -1;
Jeff Brown037c33e2014-04-09 00:31:55 -0700814 }
815
Michael Wrighta3dab232019-02-22 16:54:21 +0000816 private int findMatchingModeIdLocked(int physIndex) {
817 SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[physIndex];
818 for (int i = 0; i < mSupportedModes.size(); i++) {
819 DisplayModeRecord record = mSupportedModes.valueAt(i);
820 if (record.hasMatchingMode(info)) {
821 return record.mMode.getModeId();
822 }
823 }
824 return 0;
825 }
826
Jeff Brown037c33e2014-04-09 00:31:55 -0700827 private void updateDeviceInfoLocked() {
828 mInfo = null;
829 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700830 }
Michael Wrighta3dab232019-02-22 16:54:21 +0000831
832 private Display.Mode[] getDisplayModes(SparseArray<DisplayModeRecord> records) {
833 final int size = records.size();
834 Display.Mode[] modes = new Display.Mode[size];
835 for (int i = 0; i < size; i++) {
836 DisplayModeRecord record = records.valueAt(i);
837 modes[i] = record.mMode;
838 }
839 return modes;
840 }
Keun young Parkabf38e32019-04-23 19:18:34 -0700841
842 private boolean isDisplayPrivate(DisplayAddress.Physical physicalAddress) {
843 if (physicalAddress == null) {
844 return false;
845 }
846 final Resources res = getOverlayContext().getResources();
847 int[] ports = res.getIntArray(
848 com.android.internal.R.array.config_localPrivateDisplayPorts);
849 if (ports != null) {
Dominik Laskowski67cc7f82019-11-08 17:09:29 -0800850 int port = Byte.toUnsignedInt(physicalAddress.getPort());
Keun young Parkabf38e32019-04-23 19:18:34 -0700851 for (int p : ports) {
852 if (p == port) {
853 return true;
854 }
855 }
856 }
857 return false;
858 }
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700859 }
Michael Wright3f145a22014-07-22 19:46:03 -0700860
Adrian Roos30f53212018-01-05 16:14:34 +0100861 /** Supplies a context whose Resources apply runtime-overlays */
862 Context getOverlayContext() {
863 return ActivityThread.currentActivityThread().getSystemUiContext();
864 }
865
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700866 /**
867 * Keeps track of a display configuration.
868 */
869 private static final class DisplayModeRecord {
870 public final Display.Mode mMode;
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700871
Michael Wright58e829f2015-09-15 00:13:26 +0100872 public DisplayModeRecord(SurfaceControl.PhysicalDisplayInfo phys) {
P.Y. Laligandb3b9eb32015-05-11 15:02:07 -0700873 mMode = createMode(phys.width, phys.height, phys.refreshRate);
Michael Wright58e829f2015-09-15 00:13:26 +0100874 }
875
876 /**
877 * Returns whether the mode generated by the given PhysicalDisplayInfo matches the mode
878 * contained by the record modulo mode ID.
879 *
880 * Note that this doesn't necessarily mean the the PhysicalDisplayInfos are identical, just
881 * that they generate identical modes.
882 */
883 public boolean hasMatchingMode(SurfaceControl.PhysicalDisplayInfo info) {
884 int modeRefreshRate = Float.floatToIntBits(mMode.getRefreshRate());
885 int displayInfoRefreshRate = Float.floatToIntBits(info.refreshRate);
886 return mMode.getPhysicalWidth() == info.width
887 && mMode.getPhysicalHeight() == info.height
888 && modeRefreshRate == displayInfoRefreshRate;
889 }
890
891 public String toString() {
892 return "DisplayModeRecord{mMode=" + mMode + "}";
Michael Wright3f145a22014-07-22 19:46:03 -0700893 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700894 }
Jeff Browne87bf032012-09-20 18:30:13 -0700895
Ady Abrahama5a21f72019-02-13 16:41:59 -0800896 private final class PhysicalDisplayEventReceiver extends DisplayEventReceiver {
897 PhysicalDisplayEventReceiver(Looper looper) {
Ady Abraham9c501aa2019-06-04 16:07:44 -0700898 super(looper, VSYNC_SOURCE_APP, CONFIG_CHANGED_EVENT_DISPATCH);
Jeff Browne87bf032012-09-20 18:30:13 -0700899 }
900
901 @Override
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800902 public void onHotplug(long timestampNanos, long physicalDisplayId, boolean connected) {
Jeff Browne87bf032012-09-20 18:30:13 -0700903 synchronized (getSyncRoot()) {
Jesse Halle244db42012-11-08 11:55:14 -0800904 if (connected) {
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800905 tryConnectDisplayLocked(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -0800906 } else {
Dominik Laskowski3316a0a2019-01-25 02:56:41 -0800907 tryDisconnectDisplayLocked(physicalDisplayId);
Jesse Halle244db42012-11-08 11:55:14 -0800908 }
Jeff Browne87bf032012-09-20 18:30:13 -0700909 }
910 }
Ady Abrahama5a21f72019-02-13 16:41:59 -0800911
912 @Override
Michael Wrighta3dab232019-02-22 16:54:21 +0000913 public void onConfigChanged(long timestampNanos, long physicalDisplayId, int physIndex) {
Ady Abrahama5a21f72019-02-13 16:41:59 -0800914 if (DEBUG) {
915 Slog.d(TAG, "onConfigChanged("
916 + "timestampNanos=" + timestampNanos
Michael Wrighta3dab232019-02-22 16:54:21 +0000917 + ", physicalDisplayId=" + physicalDisplayId
918 + ", physIndex=" + physIndex + ")");
919 }
920 synchronized (getSyncRoot()) {
921 LocalDisplayDevice device = mDevices.get(physicalDisplayId);
922 if (device == null) {
923 if (DEBUG) {
924 Slog.d(TAG, "Received config change for unhandled physical display: "
925 + "physicalDisplayId=" + physicalDisplayId);
926 }
927 return;
928 }
929 device.onActivePhysicalDisplayModeChangedLocked(physIndex);
Ady Abrahama5a21f72019-02-13 16:41:59 -0800930 }
931 }
Jeff Browne87bf032012-09-20 18:30:13 -0700932 }
Dan Stoza00101052014-05-02 15:23:40 -0700933}