blob: f3ebd7f36fd60810ab2d046b7a66eba451a99da7 [file] [log] [blame]
Jeff Brownbd6e1502012-08-28 03:27:37 -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 android.hardware.display;
18
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010019import android.annotation.UnsupportedAppUsage;
Jeff Brownbd6e1502012-08-28 03:27:37 -070020import android.content.Context;
Kenny Guy22bd0442017-10-26 00:15:54 +010021import android.content.pm.ParceledListSlice;
Bryce Lee609bf652017-02-09 16:50:13 -080022import android.content.res.Resources;
Peiyong Lin277eaff2019-01-16 16:18:22 -080023import android.graphics.ColorSpace;
Michael Wrighteedcbf12017-08-16 23:14:54 +010024import android.graphics.Point;
Jeff Brownbd6e1502012-08-28 03:27:37 -070025import android.hardware.display.DisplayManager.DisplayListener;
Michael Wrightc39d47a2014-07-08 18:07:36 -070026import android.media.projection.IMediaProjection;
Santos Cordonee8931e2017-04-05 10:31:15 -070027import android.media.projection.MediaProjection;
Jeff Brownbd6e1502012-08-28 03:27:37 -070028import android.os.Handler;
29import android.os.IBinder;
30import android.os.Looper;
31import android.os.Message;
32import android.os.RemoteException;
33import android.os.ServiceManager;
Jeff Browna506a6e2013-06-04 00:02:38 -070034import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070035import android.util.Log;
Dan Gittik122df862018-03-28 16:59:22 +010036import android.util.Pair;
Jeff Brownbd6e1502012-08-28 03:27:37 -070037import android.util.SparseArray;
Jeff Brownbd6e1502012-08-28 03:27:37 -070038import android.view.Display;
Santos Cordonee8931e2017-04-05 10:31:15 -070039import android.view.DisplayAdjustments;
Jeff Brownbd6e1502012-08-28 03:27:37 -070040import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070041import android.view.Surface;
Jeff Brownbd6e1502012-08-28 03:27:37 -070042
43import java.util.ArrayList;
Kenny Guy22bd0442017-10-26 00:15:54 +010044import java.util.Collections;
45import java.util.List;
Jeff Brownbd6e1502012-08-28 03:27:37 -070046
47/**
48 * Manager communication with the display manager service on behalf of
49 * an application process. You're probably looking for {@link DisplayManager}.
50 *
51 * @hide
52 */
53public final class DisplayManagerGlobal {
54 private static final String TAG = "DisplayManager";
55 private static final boolean DEBUG = false;
56
Jeff Brown4ed8fe72012-08-30 18:18:29 -070057 // True if display info and display ids should be cached.
58 //
59 // FIXME: The cache is currently disabled because it's unclear whether we have the
60 // necessary guarantees that the caches will always be flushed before clients
61 // attempt to observe their new state. For example, depending on the order
62 // in which the binder transactions take place, we might have a problem where
63 // an application could start processing a configuration change due to a display
64 // orientation change before the display info cache has actually been invalidated.
65 private static final boolean USE_CACHE = false;
66
Jeff Brownbd6e1502012-08-28 03:27:37 -070067 public static final int EVENT_DISPLAY_ADDED = 1;
68 public static final int EVENT_DISPLAY_CHANGED = 2;
69 public static final int EVENT_DISPLAY_REMOVED = 3;
70
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010071 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -070072 private static DisplayManagerGlobal sInstance;
73
74 private final Object mLock = new Object();
75
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010076 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -070077 private final IDisplayManager mDm;
78
79 private DisplayManagerCallback mCallback;
80 private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
81 new ArrayList<DisplayListenerDelegate>();
82
83 private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
Peiyong Lin277eaff2019-01-16 16:18:22 -080084 private final ColorSpace mWideColorSpace;
Jeff Brownbd6e1502012-08-28 03:27:37 -070085 private int[] mDisplayIdCache;
86
Jeff Brownce468a32013-11-21 16:42:03 -080087 private int mWifiDisplayScanNestCount;
88
Jeff Brownbd6e1502012-08-28 03:27:37 -070089 private DisplayManagerGlobal(IDisplayManager dm) {
90 mDm = dm;
Peiyong Lin277eaff2019-01-16 16:18:22 -080091 try {
92 mWideColorSpace =
93 ColorSpace.get(
94 ColorSpace.Named.values()[mDm.getPreferredWideGamutColorSpaceId()]);
95 } catch (RemoteException ex) {
96 throw ex.rethrowFromSystemServer();
97 }
Jeff Brownbd6e1502012-08-28 03:27:37 -070098 }
99
100 /**
101 * Gets an instance of the display manager global singleton.
102 *
103 * @return The display manager instance, may be null early in system startup
104 * before the display manager has been fully initialized.
105 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100106 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700107 public static DisplayManagerGlobal getInstance() {
108 synchronized (DisplayManagerGlobal.class) {
109 if (sInstance == null) {
110 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
111 if (b != null) {
112 sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
113 }
114 }
115 return sInstance;
116 }
117 }
118
119 /**
120 * Get information about a particular logical display.
121 *
122 * @param displayId The logical display id.
123 * @return Information about the specified display, or null if it does not exist.
124 * This object belongs to an internal cache and should be treated as if it were immutable.
125 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100126 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700127 public DisplayInfo getDisplayInfo(int displayId) {
128 try {
129 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700130 DisplayInfo info;
131 if (USE_CACHE) {
132 info = mDisplayInfoCache.get(displayId);
133 if (info != null) {
134 return info;
135 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700136 }
137
138 info = mDm.getDisplayInfo(displayId);
139 if (info == null) {
140 return null;
141 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700142
143 if (USE_CACHE) {
144 mDisplayInfoCache.put(displayId, info);
145 }
146 registerCallbackIfNeededLocked();
147
Jeff Brownbd6e1502012-08-28 03:27:37 -0700148 if (DEBUG) {
149 Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
150 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700151 return info;
152 }
153 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700154 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700155 }
156 }
157
158 /**
159 * Gets all currently valid logical display ids.
160 *
161 * @return An array containing all display ids.
162 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100163 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700164 public int[] getDisplayIds() {
165 try {
166 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700167 if (USE_CACHE) {
168 if (mDisplayIdCache != null) {
169 return mDisplayIdCache;
170 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700171 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700172
173 int[] displayIds = mDm.getDisplayIds();
174 if (USE_CACHE) {
175 mDisplayIdCache = displayIds;
176 }
177 registerCallbackIfNeededLocked();
178 return displayIds;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700179 }
180 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700181 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700182 }
183 }
184
185 /**
186 * Gets information about a logical display.
187 *
188 * The display metrics may be adjusted to provide compatibility
Craig Mautner48d0d182013-06-11 07:53:06 -0700189 * for legacy applications or limited screen areas.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700190 *
191 * @param displayId The logical display id.
Craig Mautner48d0d182013-06-11 07:53:06 -0700192 * @param daj The compatibility info and activityToken.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700193 * @return The display object, or null if there is no display with the given id.
194 */
Craig Mautner48d0d182013-06-11 07:53:06 -0700195 public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700196 DisplayInfo displayInfo = getDisplayInfo(displayId);
197 if (displayInfo == null) {
198 return null;
199 }
Craig Mautner48d0d182013-06-11 07:53:06 -0700200 return new Display(this, displayId, displayInfo, daj);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700201 }
202
203 /**
Bryce Lee609bf652017-02-09 16:50:13 -0800204 * Gets information about a logical display.
205 *
206 * The display metrics may be adjusted to provide compatibility
207 * for legacy applications or limited screen areas.
208 *
209 * @param displayId The logical display id.
210 * @param resources Resources providing compatibility info.
211 * @return The display object, or null if there is no display with the given id.
212 */
213 public Display getCompatibleDisplay(int displayId, Resources resources) {
214 DisplayInfo displayInfo = getDisplayInfo(displayId);
215 if (displayInfo == null) {
216 return null;
217 }
218 return new Display(this, displayId, displayInfo, resources);
219 }
220
221 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700222 * Gets information about a logical display without applying any compatibility metrics.
223 *
224 * @param displayId The logical display id.
225 * @return The display object, or null if there is no display with the given id.
226 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100227 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700228 public Display getRealDisplay(int displayId) {
Craig Mautner48d0d182013-06-11 07:53:06 -0700229 return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
230 }
231
Jeff Brownbd6e1502012-08-28 03:27:37 -0700232 public void registerDisplayListener(DisplayListener listener, Handler handler) {
233 if (listener == null) {
234 throw new IllegalArgumentException("listener must not be null");
235 }
236
237 synchronized (mLock) {
238 int index = findDisplayListenerLocked(listener);
239 if (index < 0) {
240 mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
241 registerCallbackIfNeededLocked();
242 }
243 }
244 }
245
246 public void unregisterDisplayListener(DisplayListener listener) {
247 if (listener == null) {
248 throw new IllegalArgumentException("listener must not be null");
249 }
250
251 synchronized (mLock) {
252 int index = findDisplayListenerLocked(listener);
253 if (index >= 0) {
254 DisplayListenerDelegate d = mDisplayListeners.get(index);
255 d.clearEvents();
256 mDisplayListeners.remove(index);
257 }
258 }
259 }
260
261 private int findDisplayListenerLocked(DisplayListener listener) {
262 final int numListeners = mDisplayListeners.size();
263 for (int i = 0; i < numListeners; i++) {
264 if (mDisplayListeners.get(i).mListener == listener) {
265 return i;
266 }
267 }
268 return -1;
269 }
270
271 private void registerCallbackIfNeededLocked() {
272 if (mCallback == null) {
273 mCallback = new DisplayManagerCallback();
274 try {
275 mDm.registerCallback(mCallback);
276 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700277 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700278 }
279 }
280 }
281
282 private void handleDisplayEvent(int displayId, int event) {
283 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700284 if (USE_CACHE) {
285 mDisplayInfoCache.remove(displayId);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700286
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700287 if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
288 mDisplayIdCache = null;
289 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700290 }
291
292 final int numListeners = mDisplayListeners.size();
293 for (int i = 0; i < numListeners; i++) {
294 mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
295 }
296 }
297 }
298
Jeff Brownce468a32013-11-21 16:42:03 -0800299 public void startWifiDisplayScan() {
300 synchronized (mLock) {
301 if (mWifiDisplayScanNestCount++ == 0) {
302 registerCallbackIfNeededLocked();
303 try {
304 mDm.startWifiDisplayScan();
305 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700306 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800307 }
308 }
309 }
310 }
311
312 public void stopWifiDisplayScan() {
313 synchronized (mLock) {
314 if (--mWifiDisplayScanNestCount == 0) {
315 try {
316 mDm.stopWifiDisplayScan();
317 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700318 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800319 }
320 } else if (mWifiDisplayScanNestCount < 0) {
321 Log.wtf(TAG, "Wifi display scan nest count became negative: "
322 + mWifiDisplayScanNestCount);
323 mWifiDisplayScanNestCount = 0;
324 }
Jeff Browne08ae382012-09-07 20:36:36 -0700325 }
326 }
327
328 public void connectWifiDisplay(String deviceAddress) {
329 if (deviceAddress == null) {
330 throw new IllegalArgumentException("deviceAddress must not be null");
331 }
332
333 try {
334 mDm.connectWifiDisplay(deviceAddress);
335 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700336 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700337 }
338 }
339
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700340 public void pauseWifiDisplay() {
341 try {
342 mDm.pauseWifiDisplay();
343 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700344 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700345 }
346 }
347
348 public void resumeWifiDisplay() {
349 try {
350 mDm.resumeWifiDisplay();
351 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700352 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700353 }
354 }
355
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100356 @UnsupportedAppUsage
Jeff Browne08ae382012-09-07 20:36:36 -0700357 public void disconnectWifiDisplay() {
358 try {
359 mDm.disconnectWifiDisplay();
360 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700361 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700362 }
363 }
364
Jeff Brown89d55462012-09-19 11:33:42 -0700365 public void renameWifiDisplay(String deviceAddress, String alias) {
366 if (deviceAddress == null) {
367 throw new IllegalArgumentException("deviceAddress must not be null");
368 }
369
370 try {
371 mDm.renameWifiDisplay(deviceAddress, alias);
372 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700373 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700374 }
375 }
376
377 public void forgetWifiDisplay(String deviceAddress) {
378 if (deviceAddress == null) {
379 throw new IllegalArgumentException("deviceAddress must not be null");
380 }
381
382 try {
383 mDm.forgetWifiDisplay(deviceAddress);
384 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700385 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700386 }
387 }
388
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100389 @UnsupportedAppUsage
Jeff Browne08ae382012-09-07 20:36:36 -0700390 public WifiDisplayStatus getWifiDisplayStatus() {
391 try {
392 return mDm.getWifiDisplayStatus();
393 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700394 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700395 }
396 }
397
Michael Wright1c9977b2016-07-12 13:30:10 -0700398 public void requestColorMode(int displayId, int colorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100399 try {
Michael Wright1c9977b2016-07-12 13:30:10 -0700400 mDm.requestColorMode(displayId, colorMode);
Michael Wright58e829f2015-09-15 00:13:26 +0100401 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700402 throw ex.rethrowFromSystemServer();
Michael Wright58e829f2015-09-15 00:13:26 +0100403 }
404 }
405
Michael Wrightc39d47a2014-07-08 18:07:36 -0700406 public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
407 String name, int width, int height, int densityDpi, Surface surface, int flags,
Santos Cordonee8931e2017-04-05 10:31:15 -0700408 VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700409 if (TextUtils.isEmpty(name)) {
410 throw new IllegalArgumentException("name must be non-null and non-empty");
411 }
412 if (width <= 0 || height <= 0 || densityDpi <= 0) {
413 throw new IllegalArgumentException("width, height, and densityDpi must be "
414 + "greater than 0");
415 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700416
Michael Wright75ee9fc2014-09-01 19:55:22 -0700417 VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
Michael Wrightc39d47a2014-07-08 18:07:36 -0700418 IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
Jeff Browna506a6e2013-06-04 00:02:38 -0700419 int displayId;
420 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700421 displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
Santos Cordonee8931e2017-04-05 10:31:15 -0700422 context.getPackageName(), name, width, height, densityDpi, surface, flags,
423 uniqueId);
Jeff Browna506a6e2013-06-04 00:02:38 -0700424 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700425 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700426 }
427 if (displayId < 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700428 Log.e(TAG, "Could not create virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700429 return null;
430 }
431 Display display = getRealDisplay(displayId);
432 if (display == null) {
433 Log.wtf(TAG, "Could not obtain display info for newly created "
Jeff Brown7d00aff2013-08-02 19:03:49 -0700434 + "virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700435 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700436 mDm.releaseVirtualDisplay(callbackWrapper);
Jeff Browna506a6e2013-06-04 00:02:38 -0700437 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700438 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700439 }
440 return null;
441 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700442 return new VirtualDisplay(this, display, callbackWrapper, surface);
Jeff Brown92207df2014-04-16 13:16:07 -0700443 }
444
Michael Wright75ee9fc2014-09-01 19:55:22 -0700445 public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
Jeff Brown92207df2014-04-16 13:16:07 -0700446 try {
447 mDm.setVirtualDisplaySurface(token, surface);
chaviwda4c6942018-11-07 15:52:56 -0800448 setVirtualDisplayState(token, surface != null);
Jeff Brown92207df2014-04-16 13:16:07 -0700449 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700450 throw ex.rethrowFromSystemServer();
Jeff Brown92207df2014-04-16 13:16:07 -0700451 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700452 }
453
Michael Wright75ee9fc2014-09-01 19:55:22 -0700454 public void resizeVirtualDisplay(IVirtualDisplayCallback token,
Michael Wright01e840f2014-06-26 16:03:25 -0700455 int width, int height, int densityDpi) {
456 try {
457 mDm.resizeVirtualDisplay(token, width, height, densityDpi);
458 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700459 throw ex.rethrowFromSystemServer();
Michael Wright01e840f2014-06-26 16:03:25 -0700460 }
461 }
462
Michael Wright75ee9fc2014-09-01 19:55:22 -0700463 public void releaseVirtualDisplay(IVirtualDisplayCallback token) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700464 try {
465 mDm.releaseVirtualDisplay(token);
466 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700467 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700468 }
469 }
470
chaviwda4c6942018-11-07 15:52:56 -0800471 void setVirtualDisplayState(IVirtualDisplayCallback token, boolean isOn) {
472 try {
473 mDm.setVirtualDisplayState(token, isOn);
474 } catch (RemoteException ex) {
475 throw ex.rethrowFromSystemServer();
476 }
477 }
478
Michael Wrighteedcbf12017-08-16 23:14:54 +0100479 /**
480 * Gets the stable device display size, in pixels.
481 */
482 public Point getStableDisplaySize() {
483 try {
484 return mDm.getStableDisplaySize();
485 } catch (RemoteException ex) {
486 throw ex.rethrowFromSystemServer();
487 }
488 }
489
Kenny Guy22bd0442017-10-26 00:15:54 +0100490 /**
491 * Retrieves brightness change events.
492 */
Kenny Guy29aa30e2017-11-30 13:43:46 +0000493 public List<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
Kenny Guy22bd0442017-10-26 00:15:54 +0100494 try {
Kenny Guy29aa30e2017-11-30 13:43:46 +0000495 ParceledListSlice<BrightnessChangeEvent> events =
496 mDm.getBrightnessEvents(callingPackage);
Kenny Guy22bd0442017-10-26 00:15:54 +0100497 if (events == null) {
498 return Collections.emptyList();
499 }
500 return events.getList();
501 } catch (RemoteException ex) {
502 throw ex.rethrowFromSystemServer();
503 }
504 }
505
506 /**
Peiyong Lin277eaff2019-01-16 16:18:22 -0800507 * Gets the preferred wide gamut color space for all displays.
508 * The wide gamut color space is returned from composition pipeline
509 * based on hardware capability.
510 *
511 * @hide
512 */
513 public ColorSpace getPreferredWideGamutColorSpace() {
514 return mWideColorSpace;
515 }
516
517 /**
Michael Wrighteef0e132017-11-21 17:57:52 +0000518 * Sets the global brightness configuration for a given user.
519 *
520 * @hide
521 */
Kenny Guy05ce8092018-01-17 13:44:20 +0000522 public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId,
523 String packageName) {
Michael Wrighteef0e132017-11-21 17:57:52 +0000524 try {
Kenny Guy05ce8092018-01-17 13:44:20 +0000525 mDm.setBrightnessConfigurationForUser(c, userId, packageName);
Michael Wrighteef0e132017-11-21 17:57:52 +0000526 } catch (RemoteException ex) {
527 throw ex.rethrowFromSystemServer();
528 }
529 }
530
Michael Wrightd8460232018-01-16 18:04:59 +0000531 /**
Kenny Guy6d1009f2018-03-14 14:28:23 +0000532 * Gets the global brightness configuration for a given user or null if one hasn't been set.
533 *
534 * @hide
535 */
536 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
537 try {
538 return mDm.getBrightnessConfigurationForUser(userId);
539 } catch (RemoteException ex) {
540 throw ex.rethrowFromSystemServer();
541 }
542 }
543
544 /**
545 * Gets the default brightness configuration or null if one hasn't been configured.
546 *
547 * @hide
548 */
549 public BrightnessConfiguration getDefaultBrightnessConfiguration() {
550 try {
551 return mDm.getDefaultBrightnessConfiguration();
552 } catch (RemoteException ex) {
553 throw ex.rethrowFromSystemServer();
554 }
555 }
556
557 /**
Michael Wrightd8460232018-01-16 18:04:59 +0000558 * Temporarily sets the brightness of the display.
559 * <p>
560 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
561 * </p>
562 *
563 * @param brightness The brightness value from 0 to 255.
564 *
565 * @hide Requires signature permission.
566 */
567 public void setTemporaryBrightness(int brightness) {
568 try {
569 mDm.setTemporaryBrightness(brightness);
570 } catch (RemoteException ex) {
571 throw ex.rethrowFromSystemServer();
572 }
573 }
574
575 /**
576 * Temporarily sets the auto brightness adjustment factor.
577 * <p>
578 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
579 * </p>
580 *
581 * @param adjustment The adjustment factor from -1.0 to 1.0.
582 *
583 * @hide Requires signature permission.
584 */
585 public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
586 try {
587 mDm.setTemporaryAutoBrightnessAdjustment(adjustment);
588 } catch (RemoteException ex) {
589 throw ex.rethrowFromSystemServer();
590 }
591 }
592
Peeyush Agarwalcc155dd2018-01-10 11:51:33 +0000593 /**
Dan Gittik122df862018-03-28 16:59:22 +0100594 * Returns the minimum brightness curve, which guarantess that any brightness curve that dips
595 * below it is rejected by the system.
596 * This prevent auto-brightness from setting the screen so dark as to prevent the user from
597 * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
598 * in that ambient brightness.
599 *
600 * @return The minimum brightness curve (as lux values and their corresponding nits values).
601 */
602 public Pair<float[], float[]> getMinimumBrightnessCurve() {
603 try {
604 Curve curve = mDm.getMinimumBrightnessCurve();
605 return Pair.create(curve.getX(), curve.getY());
606 } catch (RemoteException ex) {
607 throw ex.rethrowFromSystemServer();
608 }
609 }
610
611 /**
Peeyush Agarwalcc155dd2018-01-10 11:51:33 +0000612 * Retrieves ambient brightness stats.
613 */
614 public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
615 try {
616 ParceledListSlice<AmbientBrightnessDayStats> stats = mDm.getAmbientBrightnessStats();
617 if (stats == null) {
618 return Collections.emptyList();
619 }
620 return stats.getList();
621 } catch (RemoteException ex) {
622 throw ex.rethrowFromSystemServer();
623 }
624 }
625
Jeff Brownbd6e1502012-08-28 03:27:37 -0700626 private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
627 @Override
628 public void onDisplayEvent(int displayId, int event) {
629 if (DEBUG) {
630 Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
631 }
632 handleDisplayEvent(displayId, event);
633 }
634 }
635
636 private static final class DisplayListenerDelegate extends Handler {
637 public final DisplayListener mListener;
638
639 public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
640 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
641 mListener = listener;
642 }
643
644 public void sendDisplayEvent(int displayId, int event) {
645 Message msg = obtainMessage(event, displayId, 0);
646 sendMessage(msg);
647 }
648
649 public void clearEvents() {
650 removeCallbacksAndMessages(null);
651 }
652
653 @Override
654 public void handleMessage(Message msg) {
655 switch (msg.what) {
656 case EVENT_DISPLAY_ADDED:
657 mListener.onDisplayAdded(msg.arg1);
658 break;
659 case EVENT_DISPLAY_CHANGED:
660 mListener.onDisplayChanged(msg.arg1);
661 break;
662 case EVENT_DISPLAY_REMOVED:
663 mListener.onDisplayRemoved(msg.arg1);
664 break;
665 }
666 }
667 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700668
Michael Wright75ee9fc2014-09-01 19:55:22 -0700669 private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
670 private VirtualDisplayCallbackDelegate mDelegate;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700671
Michael Wright75ee9fc2014-09-01 19:55:22 -0700672 public VirtualDisplayCallback(VirtualDisplay.Callback callback, Handler handler) {
673 if (callback != null) {
674 mDelegate = new VirtualDisplayCallbackDelegate(callback, handler);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700675 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700676 }
677
678 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700679 public void onPaused() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700680 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700681 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_PAUSED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700682 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700683 }
684
685 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700686 public void onResumed() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700687 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700688 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_RESUMED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700689 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700690 }
691
692 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700693 public void onStopped() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700694 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700695 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_STOPPED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700696 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700697 }
698 }
699
Michael Wright75ee9fc2014-09-01 19:55:22 -0700700 private final static class VirtualDisplayCallbackDelegate extends Handler {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700701 public static final int MSG_DISPLAY_PAUSED = 0;
702 public static final int MSG_DISPLAY_RESUMED = 1;
703 public static final int MSG_DISPLAY_STOPPED = 2;
704
Michael Wright75ee9fc2014-09-01 19:55:22 -0700705 private final VirtualDisplay.Callback mCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700706
Michael Wright75ee9fc2014-09-01 19:55:22 -0700707 public VirtualDisplayCallbackDelegate(VirtualDisplay.Callback callback,
Michael Wrightc39d47a2014-07-08 18:07:36 -0700708 Handler handler) {
709 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
Michael Wright75ee9fc2014-09-01 19:55:22 -0700710 mCallback = callback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700711 }
712
713 @Override
714 public void handleMessage(Message msg) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700715 switch (msg.what) {
716 case MSG_DISPLAY_PAUSED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700717 mCallback.onPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700718 break;
719 case MSG_DISPLAY_RESUMED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700720 mCallback.onResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700721 break;
722 case MSG_DISPLAY_STOPPED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700723 mCallback.onStopped();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700724 break;
725 }
726 }
727 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700728}