blob: 00ab72d4a44191c96b389a6c514d9948fb1f2cd2 [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;
Michael Wrighteedcbf12017-08-16 23:14:54 +010023import android.graphics.Point;
Jeff Brownbd6e1502012-08-28 03:27:37 -070024import android.hardware.display.DisplayManager.DisplayListener;
Michael Wrightc39d47a2014-07-08 18:07:36 -070025import android.media.projection.IMediaProjection;
Santos Cordonee8931e2017-04-05 10:31:15 -070026import android.media.projection.MediaProjection;
Jeff Brownbd6e1502012-08-28 03:27:37 -070027import android.os.Handler;
28import android.os.IBinder;
29import android.os.Looper;
30import android.os.Message;
31import android.os.RemoteException;
32import android.os.ServiceManager;
Jeff Browna506a6e2013-06-04 00:02:38 -070033import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070034import android.util.Log;
Dan Gittik122df862018-03-28 16:59:22 +010035import android.util.Pair;
Jeff Brownbd6e1502012-08-28 03:27:37 -070036import android.util.SparseArray;
Jeff Brownbd6e1502012-08-28 03:27:37 -070037import android.view.Display;
Santos Cordonee8931e2017-04-05 10:31:15 -070038import android.view.DisplayAdjustments;
Jeff Brownbd6e1502012-08-28 03:27:37 -070039import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070040import android.view.Surface;
Jeff Brownbd6e1502012-08-28 03:27:37 -070041
42import java.util.ArrayList;
Kenny Guy22bd0442017-10-26 00:15:54 +010043import java.util.Collections;
44import java.util.List;
Jeff Brownbd6e1502012-08-28 03:27:37 -070045
46/**
47 * Manager communication with the display manager service on behalf of
48 * an application process. You're probably looking for {@link DisplayManager}.
49 *
50 * @hide
51 */
52public final class DisplayManagerGlobal {
53 private static final String TAG = "DisplayManager";
54 private static final boolean DEBUG = false;
55
Jeff Brown4ed8fe72012-08-30 18:18:29 -070056 // True if display info and display ids should be cached.
57 //
58 // FIXME: The cache is currently disabled because it's unclear whether we have the
59 // necessary guarantees that the caches will always be flushed before clients
60 // attempt to observe their new state. For example, depending on the order
61 // in which the binder transactions take place, we might have a problem where
62 // an application could start processing a configuration change due to a display
63 // orientation change before the display info cache has actually been invalidated.
64 private static final boolean USE_CACHE = false;
65
Jeff Brownbd6e1502012-08-28 03:27:37 -070066 public static final int EVENT_DISPLAY_ADDED = 1;
67 public static final int EVENT_DISPLAY_CHANGED = 2;
68 public static final int EVENT_DISPLAY_REMOVED = 3;
69
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010070 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -070071 private static DisplayManagerGlobal sInstance;
72
73 private final Object mLock = new Object();
74
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010075 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -070076 private final IDisplayManager mDm;
77
78 private DisplayManagerCallback mCallback;
79 private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
80 new ArrayList<DisplayListenerDelegate>();
81
82 private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
83 private int[] mDisplayIdCache;
84
Jeff Brownce468a32013-11-21 16:42:03 -080085 private int mWifiDisplayScanNestCount;
86
Jeff Brownbd6e1502012-08-28 03:27:37 -070087 private DisplayManagerGlobal(IDisplayManager dm) {
88 mDm = dm;
89 }
90
91 /**
92 * Gets an instance of the display manager global singleton.
93 *
94 * @return The display manager instance, may be null early in system startup
95 * before the display manager has been fully initialized.
96 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010097 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -070098 public static DisplayManagerGlobal getInstance() {
99 synchronized (DisplayManagerGlobal.class) {
100 if (sInstance == null) {
101 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
102 if (b != null) {
103 sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
104 }
105 }
106 return sInstance;
107 }
108 }
109
110 /**
111 * Get information about a particular logical display.
112 *
113 * @param displayId The logical display id.
114 * @return Information about the specified display, or null if it does not exist.
115 * This object belongs to an internal cache and should be treated as if it were immutable.
116 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100117 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700118 public DisplayInfo getDisplayInfo(int displayId) {
119 try {
120 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700121 DisplayInfo info;
122 if (USE_CACHE) {
123 info = mDisplayInfoCache.get(displayId);
124 if (info != null) {
125 return info;
126 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700127 }
128
129 info = mDm.getDisplayInfo(displayId);
130 if (info == null) {
131 return null;
132 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700133
134 if (USE_CACHE) {
135 mDisplayInfoCache.put(displayId, info);
136 }
137 registerCallbackIfNeededLocked();
138
Jeff Brownbd6e1502012-08-28 03:27:37 -0700139 if (DEBUG) {
140 Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
141 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700142 return info;
143 }
144 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700145 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700146 }
147 }
148
149 /**
150 * Gets all currently valid logical display ids.
151 *
152 * @return An array containing all display ids.
153 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100154 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700155 public int[] getDisplayIds() {
156 try {
157 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700158 if (USE_CACHE) {
159 if (mDisplayIdCache != null) {
160 return mDisplayIdCache;
161 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700162 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700163
164 int[] displayIds = mDm.getDisplayIds();
165 if (USE_CACHE) {
166 mDisplayIdCache = displayIds;
167 }
168 registerCallbackIfNeededLocked();
169 return displayIds;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700170 }
171 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700172 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700173 }
174 }
175
176 /**
177 * Gets information about a logical display.
178 *
179 * The display metrics may be adjusted to provide compatibility
Craig Mautner48d0d182013-06-11 07:53:06 -0700180 * for legacy applications or limited screen areas.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700181 *
182 * @param displayId The logical display id.
Craig Mautner48d0d182013-06-11 07:53:06 -0700183 * @param daj The compatibility info and activityToken.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700184 * @return The display object, or null if there is no display with the given id.
185 */
Craig Mautner48d0d182013-06-11 07:53:06 -0700186 public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700187 DisplayInfo displayInfo = getDisplayInfo(displayId);
188 if (displayInfo == null) {
189 return null;
190 }
Craig Mautner48d0d182013-06-11 07:53:06 -0700191 return new Display(this, displayId, displayInfo, daj);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700192 }
193
194 /**
Bryce Lee609bf652017-02-09 16:50:13 -0800195 * Gets information about a logical display.
196 *
197 * The display metrics may be adjusted to provide compatibility
198 * for legacy applications or limited screen areas.
199 *
200 * @param displayId The logical display id.
201 * @param resources Resources providing compatibility info.
202 * @return The display object, or null if there is no display with the given id.
203 */
204 public Display getCompatibleDisplay(int displayId, Resources resources) {
205 DisplayInfo displayInfo = getDisplayInfo(displayId);
206 if (displayInfo == null) {
207 return null;
208 }
209 return new Display(this, displayId, displayInfo, resources);
210 }
211
212 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700213 * Gets information about a logical display without applying any compatibility metrics.
214 *
215 * @param displayId The logical display id.
216 * @return The display object, or null if there is no display with the given id.
217 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100218 @UnsupportedAppUsage
Jeff Brownbd6e1502012-08-28 03:27:37 -0700219 public Display getRealDisplay(int displayId) {
Craig Mautner48d0d182013-06-11 07:53:06 -0700220 return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
221 }
222
Jeff Brownbd6e1502012-08-28 03:27:37 -0700223 public void registerDisplayListener(DisplayListener listener, Handler handler) {
224 if (listener == null) {
225 throw new IllegalArgumentException("listener must not be null");
226 }
227
228 synchronized (mLock) {
229 int index = findDisplayListenerLocked(listener);
230 if (index < 0) {
231 mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
232 registerCallbackIfNeededLocked();
233 }
234 }
235 }
236
237 public void unregisterDisplayListener(DisplayListener listener) {
238 if (listener == null) {
239 throw new IllegalArgumentException("listener must not be null");
240 }
241
242 synchronized (mLock) {
243 int index = findDisplayListenerLocked(listener);
244 if (index >= 0) {
245 DisplayListenerDelegate d = mDisplayListeners.get(index);
246 d.clearEvents();
247 mDisplayListeners.remove(index);
248 }
249 }
250 }
251
252 private int findDisplayListenerLocked(DisplayListener listener) {
253 final int numListeners = mDisplayListeners.size();
254 for (int i = 0; i < numListeners; i++) {
255 if (mDisplayListeners.get(i).mListener == listener) {
256 return i;
257 }
258 }
259 return -1;
260 }
261
262 private void registerCallbackIfNeededLocked() {
263 if (mCallback == null) {
264 mCallback = new DisplayManagerCallback();
265 try {
266 mDm.registerCallback(mCallback);
267 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700268 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700269 }
270 }
271 }
272
273 private void handleDisplayEvent(int displayId, int event) {
274 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700275 if (USE_CACHE) {
276 mDisplayInfoCache.remove(displayId);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700277
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700278 if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
279 mDisplayIdCache = null;
280 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700281 }
282
283 final int numListeners = mDisplayListeners.size();
284 for (int i = 0; i < numListeners; i++) {
285 mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
286 }
287 }
288 }
289
Jeff Brownce468a32013-11-21 16:42:03 -0800290 public void startWifiDisplayScan() {
291 synchronized (mLock) {
292 if (mWifiDisplayScanNestCount++ == 0) {
293 registerCallbackIfNeededLocked();
294 try {
295 mDm.startWifiDisplayScan();
296 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700297 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800298 }
299 }
300 }
301 }
302
303 public void stopWifiDisplayScan() {
304 synchronized (mLock) {
305 if (--mWifiDisplayScanNestCount == 0) {
306 try {
307 mDm.stopWifiDisplayScan();
308 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700309 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800310 }
311 } else if (mWifiDisplayScanNestCount < 0) {
312 Log.wtf(TAG, "Wifi display scan nest count became negative: "
313 + mWifiDisplayScanNestCount);
314 mWifiDisplayScanNestCount = 0;
315 }
Jeff Browne08ae382012-09-07 20:36:36 -0700316 }
317 }
318
319 public void connectWifiDisplay(String deviceAddress) {
320 if (deviceAddress == null) {
321 throw new IllegalArgumentException("deviceAddress must not be null");
322 }
323
324 try {
325 mDm.connectWifiDisplay(deviceAddress);
326 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700327 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700328 }
329 }
330
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700331 public void pauseWifiDisplay() {
332 try {
333 mDm.pauseWifiDisplay();
334 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700335 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700336 }
337 }
338
339 public void resumeWifiDisplay() {
340 try {
341 mDm.resumeWifiDisplay();
342 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700343 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700344 }
345 }
346
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100347 @UnsupportedAppUsage
Jeff Browne08ae382012-09-07 20:36:36 -0700348 public void disconnectWifiDisplay() {
349 try {
350 mDm.disconnectWifiDisplay();
351 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700352 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700353 }
354 }
355
Jeff Brown89d55462012-09-19 11:33:42 -0700356 public void renameWifiDisplay(String deviceAddress, String alias) {
357 if (deviceAddress == null) {
358 throw new IllegalArgumentException("deviceAddress must not be null");
359 }
360
361 try {
362 mDm.renameWifiDisplay(deviceAddress, alias);
363 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700364 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700365 }
366 }
367
368 public void forgetWifiDisplay(String deviceAddress) {
369 if (deviceAddress == null) {
370 throw new IllegalArgumentException("deviceAddress must not be null");
371 }
372
373 try {
374 mDm.forgetWifiDisplay(deviceAddress);
375 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700376 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700377 }
378 }
379
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100380 @UnsupportedAppUsage
Jeff Browne08ae382012-09-07 20:36:36 -0700381 public WifiDisplayStatus getWifiDisplayStatus() {
382 try {
383 return mDm.getWifiDisplayStatus();
384 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700385 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700386 }
387 }
388
Michael Wright1c9977b2016-07-12 13:30:10 -0700389 public void requestColorMode(int displayId, int colorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100390 try {
Michael Wright1c9977b2016-07-12 13:30:10 -0700391 mDm.requestColorMode(displayId, colorMode);
Michael Wright58e829f2015-09-15 00:13:26 +0100392 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700393 throw ex.rethrowFromSystemServer();
Michael Wright58e829f2015-09-15 00:13:26 +0100394 }
395 }
396
Bryan Mawhinney462e29d2018-03-22 15:52:41 +0000397 /**
398 * Set the level of color saturation to apply to the display.
399 */
400 public void setSaturationLevel(float level) {
401 try {
402 mDm.setSaturationLevel(level);
403 } catch (RemoteException ex) {
404 throw ex.rethrowFromSystemServer();
405 }
406 }
407
Michael Wrightc39d47a2014-07-08 18:07:36 -0700408 public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
409 String name, int width, int height, int densityDpi, Surface surface, int flags,
Santos Cordonee8931e2017-04-05 10:31:15 -0700410 VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700411 if (TextUtils.isEmpty(name)) {
412 throw new IllegalArgumentException("name must be non-null and non-empty");
413 }
414 if (width <= 0 || height <= 0 || densityDpi <= 0) {
415 throw new IllegalArgumentException("width, height, and densityDpi must be "
416 + "greater than 0");
417 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700418
Michael Wright75ee9fc2014-09-01 19:55:22 -0700419 VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
Michael Wrightc39d47a2014-07-08 18:07:36 -0700420 IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
Jeff Browna506a6e2013-06-04 00:02:38 -0700421 int displayId;
422 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700423 displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
Santos Cordonee8931e2017-04-05 10:31:15 -0700424 context.getPackageName(), name, width, height, densityDpi, surface, flags,
425 uniqueId);
Jeff Browna506a6e2013-06-04 00:02:38 -0700426 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700427 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700428 }
429 if (displayId < 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700430 Log.e(TAG, "Could not create virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700431 return null;
432 }
433 Display display = getRealDisplay(displayId);
434 if (display == null) {
435 Log.wtf(TAG, "Could not obtain display info for newly created "
Jeff Brown7d00aff2013-08-02 19:03:49 -0700436 + "virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700437 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700438 mDm.releaseVirtualDisplay(callbackWrapper);
Jeff Browna506a6e2013-06-04 00:02:38 -0700439 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700440 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700441 }
442 return null;
443 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700444 return new VirtualDisplay(this, display, callbackWrapper, surface);
Jeff Brown92207df2014-04-16 13:16:07 -0700445 }
446
Michael Wright75ee9fc2014-09-01 19:55:22 -0700447 public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
Jeff Brown92207df2014-04-16 13:16:07 -0700448 try {
449 mDm.setVirtualDisplaySurface(token, surface);
chaviwda4c6942018-11-07 15:52:56 -0800450 setVirtualDisplayState(token, surface != null);
Jeff Brown92207df2014-04-16 13:16:07 -0700451 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700452 throw ex.rethrowFromSystemServer();
Jeff Brown92207df2014-04-16 13:16:07 -0700453 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700454 }
455
Michael Wright75ee9fc2014-09-01 19:55:22 -0700456 public void resizeVirtualDisplay(IVirtualDisplayCallback token,
Michael Wright01e840f2014-06-26 16:03:25 -0700457 int width, int height, int densityDpi) {
458 try {
459 mDm.resizeVirtualDisplay(token, width, height, densityDpi);
460 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700461 throw ex.rethrowFromSystemServer();
Michael Wright01e840f2014-06-26 16:03:25 -0700462 }
463 }
464
Michael Wright75ee9fc2014-09-01 19:55:22 -0700465 public void releaseVirtualDisplay(IVirtualDisplayCallback token) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700466 try {
467 mDm.releaseVirtualDisplay(token);
468 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700469 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700470 }
471 }
472
chaviwda4c6942018-11-07 15:52:56 -0800473 void setVirtualDisplayState(IVirtualDisplayCallback token, boolean isOn) {
474 try {
475 mDm.setVirtualDisplayState(token, isOn);
476 } catch (RemoteException ex) {
477 throw ex.rethrowFromSystemServer();
478 }
479 }
480
Michael Wrighteedcbf12017-08-16 23:14:54 +0100481 /**
482 * Gets the stable device display size, in pixels.
483 */
484 public Point getStableDisplaySize() {
485 try {
486 return mDm.getStableDisplaySize();
487 } catch (RemoteException ex) {
488 throw ex.rethrowFromSystemServer();
489 }
490 }
491
Kenny Guy22bd0442017-10-26 00:15:54 +0100492 /**
493 * Retrieves brightness change events.
494 */
Kenny Guy29aa30e2017-11-30 13:43:46 +0000495 public List<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
Kenny Guy22bd0442017-10-26 00:15:54 +0100496 try {
Kenny Guy29aa30e2017-11-30 13:43:46 +0000497 ParceledListSlice<BrightnessChangeEvent> events =
498 mDm.getBrightnessEvents(callingPackage);
Kenny Guy22bd0442017-10-26 00:15:54 +0100499 if (events == null) {
500 return Collections.emptyList();
501 }
502 return events.getList();
503 } catch (RemoteException ex) {
504 throw ex.rethrowFromSystemServer();
505 }
506 }
507
508 /**
Michael Wrighteef0e132017-11-21 17:57:52 +0000509 * Sets the global brightness configuration for a given user.
510 *
511 * @hide
512 */
Kenny Guy05ce8092018-01-17 13:44:20 +0000513 public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId,
514 String packageName) {
Michael Wrighteef0e132017-11-21 17:57:52 +0000515 try {
Kenny Guy05ce8092018-01-17 13:44:20 +0000516 mDm.setBrightnessConfigurationForUser(c, userId, packageName);
Michael Wrighteef0e132017-11-21 17:57:52 +0000517 } catch (RemoteException ex) {
518 throw ex.rethrowFromSystemServer();
519 }
520 }
521
Michael Wrightd8460232018-01-16 18:04:59 +0000522 /**
Kenny Guy6d1009f2018-03-14 14:28:23 +0000523 * Gets the global brightness configuration for a given user or null if one hasn't been set.
524 *
525 * @hide
526 */
527 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
528 try {
529 return mDm.getBrightnessConfigurationForUser(userId);
530 } catch (RemoteException ex) {
531 throw ex.rethrowFromSystemServer();
532 }
533 }
534
535 /**
536 * Gets the default brightness configuration or null if one hasn't been configured.
537 *
538 * @hide
539 */
540 public BrightnessConfiguration getDefaultBrightnessConfiguration() {
541 try {
542 return mDm.getDefaultBrightnessConfiguration();
543 } catch (RemoteException ex) {
544 throw ex.rethrowFromSystemServer();
545 }
546 }
547
548 /**
Michael Wrightd8460232018-01-16 18:04:59 +0000549 * Temporarily sets the brightness of the display.
550 * <p>
551 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
552 * </p>
553 *
554 * @param brightness The brightness value from 0 to 255.
555 *
556 * @hide Requires signature permission.
557 */
558 public void setTemporaryBrightness(int brightness) {
559 try {
560 mDm.setTemporaryBrightness(brightness);
561 } catch (RemoteException ex) {
562 throw ex.rethrowFromSystemServer();
563 }
564 }
565
566 /**
567 * Temporarily sets the auto brightness adjustment factor.
568 * <p>
569 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
570 * </p>
571 *
572 * @param adjustment The adjustment factor from -1.0 to 1.0.
573 *
574 * @hide Requires signature permission.
575 */
576 public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
577 try {
578 mDm.setTemporaryAutoBrightnessAdjustment(adjustment);
579 } catch (RemoteException ex) {
580 throw ex.rethrowFromSystemServer();
581 }
582 }
583
Peeyush Agarwalcc155dd2018-01-10 11:51:33 +0000584 /**
Dan Gittik122df862018-03-28 16:59:22 +0100585 * Returns the minimum brightness curve, which guarantess that any brightness curve that dips
586 * below it is rejected by the system.
587 * This prevent auto-brightness from setting the screen so dark as to prevent the user from
588 * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
589 * in that ambient brightness.
590 *
591 * @return The minimum brightness curve (as lux values and their corresponding nits values).
592 */
593 public Pair<float[], float[]> getMinimumBrightnessCurve() {
594 try {
595 Curve curve = mDm.getMinimumBrightnessCurve();
596 return Pair.create(curve.getX(), curve.getY());
597 } catch (RemoteException ex) {
598 throw ex.rethrowFromSystemServer();
599 }
600 }
601
602 /**
Peeyush Agarwalcc155dd2018-01-10 11:51:33 +0000603 * Retrieves ambient brightness stats.
604 */
605 public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
606 try {
607 ParceledListSlice<AmbientBrightnessDayStats> stats = mDm.getAmbientBrightnessStats();
608 if (stats == null) {
609 return Collections.emptyList();
610 }
611 return stats.getList();
612 } catch (RemoteException ex) {
613 throw ex.rethrowFromSystemServer();
614 }
615 }
616
Jeff Brownbd6e1502012-08-28 03:27:37 -0700617 private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
618 @Override
619 public void onDisplayEvent(int displayId, int event) {
620 if (DEBUG) {
621 Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
622 }
623 handleDisplayEvent(displayId, event);
624 }
625 }
626
627 private static final class DisplayListenerDelegate extends Handler {
628 public final DisplayListener mListener;
629
630 public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
631 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
632 mListener = listener;
633 }
634
635 public void sendDisplayEvent(int displayId, int event) {
636 Message msg = obtainMessage(event, displayId, 0);
637 sendMessage(msg);
638 }
639
640 public void clearEvents() {
641 removeCallbacksAndMessages(null);
642 }
643
644 @Override
645 public void handleMessage(Message msg) {
646 switch (msg.what) {
647 case EVENT_DISPLAY_ADDED:
648 mListener.onDisplayAdded(msg.arg1);
649 break;
650 case EVENT_DISPLAY_CHANGED:
651 mListener.onDisplayChanged(msg.arg1);
652 break;
653 case EVENT_DISPLAY_REMOVED:
654 mListener.onDisplayRemoved(msg.arg1);
655 break;
656 }
657 }
658 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700659
Michael Wright75ee9fc2014-09-01 19:55:22 -0700660 private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
661 private VirtualDisplayCallbackDelegate mDelegate;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700662
Michael Wright75ee9fc2014-09-01 19:55:22 -0700663 public VirtualDisplayCallback(VirtualDisplay.Callback callback, Handler handler) {
664 if (callback != null) {
665 mDelegate = new VirtualDisplayCallbackDelegate(callback, handler);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700666 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700667 }
668
669 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700670 public void onPaused() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700671 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700672 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_PAUSED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700673 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700674 }
675
676 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700677 public void onResumed() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700678 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700679 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_RESUMED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700680 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700681 }
682
683 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700684 public void onStopped() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700685 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700686 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_STOPPED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700687 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700688 }
689 }
690
Michael Wright75ee9fc2014-09-01 19:55:22 -0700691 private final static class VirtualDisplayCallbackDelegate extends Handler {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700692 public static final int MSG_DISPLAY_PAUSED = 0;
693 public static final int MSG_DISPLAY_RESUMED = 1;
694 public static final int MSG_DISPLAY_STOPPED = 2;
695
Michael Wright75ee9fc2014-09-01 19:55:22 -0700696 private final VirtualDisplay.Callback mCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700697
Michael Wright75ee9fc2014-09-01 19:55:22 -0700698 public VirtualDisplayCallbackDelegate(VirtualDisplay.Callback callback,
Michael Wrightc39d47a2014-07-08 18:07:36 -0700699 Handler handler) {
700 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
Michael Wright75ee9fc2014-09-01 19:55:22 -0700701 mCallback = callback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700702 }
703
704 @Override
705 public void handleMessage(Message msg) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700706 switch (msg.what) {
707 case MSG_DISPLAY_PAUSED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700708 mCallback.onPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700709 break;
710 case MSG_DISPLAY_RESUMED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700711 mCallback.onResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700712 break;
713 case MSG_DISPLAY_STOPPED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700714 mCallback.onStopped();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700715 break;
716 }
717 }
718 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700719}