blob: cf835ef209b450ff78956de8c3656437f35bea86 [file] [log] [blame]
Jeff Brownfa25bf52012-07-23 19:26:30 -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
Jeff Brownbd6e1502012-08-28 03:27:37 -070019import com.android.internal.util.IndentingPrintWriter;
20
Jeff Brownfa25bf52012-07-23 19:26:30 -070021import android.Manifest;
22import android.content.Context;
23import android.content.pm.PackageManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070024import android.hardware.display.DisplayManagerGlobal;
Jeff Brownfa25bf52012-07-23 19:26:30 -070025import android.hardware.display.IDisplayManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070026import android.hardware.display.IDisplayManagerCallback;
Jeff Brownfa25bf52012-07-23 19:26:30 -070027import android.os.Binder;
Jeff Brownbd6e1502012-08-28 03:27:37 -070028import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070029import android.os.IBinder;
Jeff Brownbd6e1502012-08-28 03:27:37 -070030import android.os.Looper;
31import android.os.Message;
32import android.os.RemoteException;
33import android.os.SystemClock;
Jeff Brownfa25bf52012-07-23 19:26:30 -070034import android.os.SystemProperties;
Jeff Brownbd6e1502012-08-28 03:27:37 -070035import android.util.Slog;
36import android.util.SparseArray;
Jeff Brownfa25bf52012-07-23 19:26:30 -070037import android.view.Display;
38import android.view.DisplayInfo;
39import android.view.Surface;
40
41import java.io.FileDescriptor;
42import java.io.PrintWriter;
Jeff Brownbd6e1502012-08-28 03:27:37 -070043import java.io.StringWriter;
Jeff Brownfa25bf52012-07-23 19:26:30 -070044import java.util.ArrayList;
45
46/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070047 * Manages attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070048 * <p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070049 * The {@link DisplayManagerService} manages the global lifecycle of displays,
50 * decides how to configure logical displays based on the physical display devices currently
51 * attached, sends notifications to the system and to applications when the state
52 * changes, and so on.
53 * </p><p>
54 * The display manager service relies on a collection of {@link DisplayAdapter} components,
55 * for discovering and configuring physical display devices attached to the system.
56 * There are separate display adapters for each manner that devices are attached:
57 * one display adapter for built-in local displays, one for simulated non-functional
58 * displays when the system is headless, one for simulated overlay displays used for
59 * development, one for wifi displays, etc.
60 * </p><p>
61 * Display adapters are only weakly coupled to the display manager service.
62 * Display adapters communicate changes in display device state to the display manager
63 * service asynchronously via a {@link DisplayAdapter.DisplayAdapterListener} registered
64 * by the display manager service. This separation of concerns is important for
65 * two main reasons. First, it neatly encapsulates the responsibilities of these
66 * two classes: display adapters handle individual display devices whereas
67 * the display manager service handles the global state. Second, it eliminates
68 * the potential for deadlocks resulting from asynchronous display device discovery.
69 * </p><p>
70 * To keep things simple, display adapters and display devices are single-threaded
71 * and are only accessed on the display manager's handler thread. Of course, the
72 * display manager must be accessible by multiple thread (especially for
73 * incoming binder calls) so all of the display manager's state is synchronized
74 * and guarded by a lock.
Jeff Brownfa25bf52012-07-23 19:26:30 -070075 * </p>
76 */
77public final class DisplayManagerService extends IDisplayManager.Stub {
78 private static final String TAG = "DisplayManagerService";
Jeff Brownbd6e1502012-08-28 03:27:37 -070079 private static final boolean DEBUG = false;
Jeff Brownfa25bf52012-07-23 19:26:30 -070080
81 private static final String SYSTEM_HEADLESS = "ro.config.headless";
Jeff Brownbd6e1502012-08-28 03:27:37 -070082 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
83
84 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
85 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
86 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
Jeff Brownfa25bf52012-07-23 19:26:30 -070087
88 private final Object mLock = new Object();
89
Jeff Brown848c2dc2012-08-19 20:18:08 -070090 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -070091 private final boolean mHeadless;
Craig Mautner4f67ba62012-08-02 11:23:00 -070092
Jeff Brownbd6e1502012-08-28 03:27:37 -070093 private final DisplayManagerHandler mHandler;
94 private final DisplayAdapterListener mDisplayAdapterListener = new DisplayAdapterListener();
95 private final SparseArray<CallbackRecord> mCallbacks =
96 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -070097
Jeff Brownbd6e1502012-08-28 03:27:37 -070098 // List of all currently registered display adapters.
99 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
100
101 // List of all currently connected display devices.
102 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
103
104 // List of all logical displays, indexed by logical display id.
105 private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>();
106 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
107
108 // True if in safe mode.
109 // This option may disable certain display adapters.
110 private boolean mSafeMode;
111
112 // True if we are in a special boot mode where only core applications and
113 // services should be started. This option may disable certain display adapters.
114 private boolean mOnlyCore;
115
116 // Temporary callback list, used when sending display events to applications.
117 private ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
118
119 public DisplayManagerService(Context context, Handler uiHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700120 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700121 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700122
Jeff Brownbd6e1502012-08-28 03:27:37 -0700123 mHandler = new DisplayManagerHandler(uiHandler.getLooper());
124 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700125 }
126
Jeff Brownbd6e1502012-08-28 03:27:37 -0700127 /**
128 * Pauses the boot process to wait for the first display to be initialized.
129 */
130 public boolean waitForDefaultDisplay() {
131 synchronized (mLock) {
132 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
133 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
134 long delay = timeout - SystemClock.uptimeMillis();
135 if (delay <= 0) {
136 return false;
137 }
138 if (DEBUG) {
139 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
140 }
141 try {
142 mLock.wait(delay);
143 } catch (InterruptedException ex) {
144 }
145 }
146 }
147 return true;
148 }
149
150 /**
151 * Called when the system is ready to go.
152 */
153 public void systemReady(boolean safeMode, boolean onlyCore) {
154 synchronized (mLock) {
155 mSafeMode = safeMode;
156 mOnlyCore = onlyCore;
157 }
158 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
159 }
160
161 // Runs on handler.
Craig Mautner4f67ba62012-08-02 11:23:00 -0700162 private void registerDefaultDisplayAdapter() {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700163 // Register default display adapter.
Craig Mautner4f67ba62012-08-02 11:23:00 -0700164 if (mHeadless) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700165 registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700166 } else {
Jeff Brown64a55af2012-08-26 02:47:39 -0700167 registerDisplayAdapter(new LocalDisplayAdapter(mContext));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700168 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700169 }
170
Jeff Brownbd6e1502012-08-28 03:27:37 -0700171 // Runs on handler.
172 private void registerAdditionalDisplayAdapters() {
173 if (shouldRegisterNonEssentialDisplayAdapters()) {
174 registerDisplayAdapter(new OverlayDisplayAdapter(mContext));
175 }
176 }
177
178 private boolean shouldRegisterNonEssentialDisplayAdapters() {
179 // In safe mode, we disable non-essential display adapters to give the user
180 // an opportunity to fix broken settings or other problems that might affect
181 // system stability.
182 // In only-core mode, we disable non-essential display adapters to minimize
183 // the number of dependencies that are started while in this mode and to
184 // prevent problems that might occur due to the device being encrypted.
185 synchronized (mLock) {
186 return !mSafeMode && !mOnlyCore;
187 }
188 }
189
190 // Runs on handler.
191 private void registerDisplayAdapter(DisplayAdapter adapter) {
192 synchronized (mLock) {
193 mDisplayAdapters.add(adapter);
194 }
195
196 adapter.register(mDisplayAdapterListener);
197 }
198
Jeff Brownfa25bf52012-07-23 19:26:30 -0700199 // FIXME: this isn't the right API for the long term
Jeff Brownfa25bf52012-07-23 19:26:30 -0700200 public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
201 // hardcoded assuming 720p touch screen plugged into HDMI and USB
202 // need to redesign this
203 info.width = 1280;
204 info.height = 720;
205 }
206
Jeff Brown848c2dc2012-08-19 20:18:08 -0700207 /**
208 * Returns true if the device is headless.
209 *
210 * @return True if the device is headless.
211 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700212 public boolean isHeadless() {
213 return mHeadless;
214 }
215
Craig Mautner4f67ba62012-08-02 11:23:00 -0700216 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700217 * Sets the new logical display orientation.
218 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700219 * @param displayId The logical display id.
220 * @param orientation One of the Surface.ROTATION_* constants.
221 */
222 public void setDisplayOrientation(int displayId, int orientation) {
223 synchronized (mLock) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700224 // TODO: update mirror transforms
225 LogicalDisplay display = mLogicalDisplays.get(displayId);
226 if (display != null && display.mPrimaryDisplayDevice != null) {
227 IBinder displayToken = display.mPrimaryDisplayDevice.getDisplayToken();
228 if (displayToken != null) {
229 Surface.openTransaction();
230 try {
231 Surface.setDisplayOrientation(displayToken, orientation);
232 } finally {
233 Surface.closeTransaction();
234 }
235 }
236
237 display.mBaseDisplayInfo.rotation = orientation;
238 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
239 }
240 }
241 }
242
243 /**
244 * Overrides the display information of a particular logical display.
245 * This is used by the window manager to control the size and characteristics
246 * of the default display.
247 *
248 * @param displayId The logical display id.
249 * @param info The new data to be stored.
250 */
251 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
252 synchronized (mLock) {
253 LogicalDisplay display = mLogicalDisplays.get(displayId);
254 if (display != null) {
255 if (info != null) {
256 if (display.mOverrideDisplayInfo == null) {
257 display.mOverrideDisplayInfo = new DisplayInfo();
258 }
259 display.mOverrideDisplayInfo.copyFrom(info);
260 } else {
261 display.mOverrideDisplayInfo = null;
262 }
263
264 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
265 }
266 }
267 }
268
269 /**
270 * Returns information about the specified logical display.
271 *
272 * @param displayId The logical display id.
273 * @param The logical display info, or null if the display does not exist.
274 */
275 @Override // Binder call
276 public DisplayInfo getDisplayInfo(int displayId) {
277 synchronized (mLock) {
278 LogicalDisplay display = mLogicalDisplays.get(displayId);
279 if (display != null) {
280 if (display.mOverrideDisplayInfo != null) {
281 return new DisplayInfo(display.mOverrideDisplayInfo);
282 }
283 return new DisplayInfo(display.mBaseDisplayInfo);
284 }
285 return null;
286 }
287 }
288
289 @Override // Binder call
290 public int[] getDisplayIds() {
291 synchronized (mLock) {
292 final int count = mLogicalDisplays.size();
293 int[] displayIds = new int[count];
294 for (int i = 0; i > count; i++) {
295 displayIds[i] = mLogicalDisplays.keyAt(i);
296 }
297 return displayIds;
298 }
299 }
300
301 @Override // Binder call
302 public void registerCallback(IDisplayManagerCallback callback) {
303 if (callback == null) {
304 throw new IllegalArgumentException("listener must not be null");
305 }
306
307 synchronized (mLock) {
308 int callingPid = Binder.getCallingPid();
309 if (mCallbacks.get(callingPid) != null) {
310 throw new SecurityException("The calling process has already "
311 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700312 }
313
Jeff Brownbd6e1502012-08-28 03:27:37 -0700314 CallbackRecord record = new CallbackRecord(callingPid, callback);
315 try {
316 IBinder binder = callback.asBinder();
317 binder.linkToDeath(record, 0);
318 } catch (RemoteException ex) {
319 // give up
320 throw new RuntimeException(ex);
321 }
322
323 mCallbacks.put(callingPid, record);
324 }
325 }
326
327 private void onCallbackDied(int pid) {
328 synchronized (mLock) {
329 mCallbacks.remove(pid);
330 }
331 }
332
333 // Runs on handler.
334 private void handleDisplayDeviceAdded(DisplayDevice device) {
335 synchronized (mLock) {
336 if (mDisplayDevices.contains(device)) {
337 Slog.w(TAG, "Attempted to add already added display device: " + device);
338 return;
339 }
340
341 mDisplayDevices.add(device);
342
343 LogicalDisplay display = new LogicalDisplay(device);
344 display.updateFromPrimaryDisplayDevice();
345
346 boolean isDefault = (display.mPrimaryDisplayDeviceInfo.flags
347 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
348 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
349 Slog.w(TAG, "Attempted to add a second default device: " + device);
350 isDefault = false;
351 }
352
353 int displayId = isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
354 mLogicalDisplays.put(displayId, display);
355
356 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
357
358 // Wake up waitForDefaultDisplay.
359 if (isDefault) {
360 mLock.notifyAll();
361 }
362 }
363 }
364
365 // Runs on handler.
366 private void handleDisplayDeviceChanged(DisplayDevice device) {
367 synchronized (mLock) {
368 if (!mDisplayDevices.contains(device)) {
369 Slog.w(TAG, "Attempted to change non-existent display device: " + device);
370 return;
371 }
372
373 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
374 LogicalDisplay display = mLogicalDisplays.valueAt(i);
375 if (display.mPrimaryDisplayDevice == device) {
376 final int displayId = mLogicalDisplays.keyAt(i);
377 display.updateFromPrimaryDisplayDevice();
378 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
Jeff Brown64a55af2012-08-26 02:47:39 -0700379 }
380 }
381 }
382 }
383
Jeff Brownbd6e1502012-08-28 03:27:37 -0700384 // Runs on handler.
385 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Craig Mautner4f67ba62012-08-02 11:23:00 -0700386 synchronized (mLock) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700387 if (!mDisplayDevices.remove(device)) {
388 Slog.w(TAG, "Attempted to remove non-existent display device: " + device);
389 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700390 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700391
392 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
393 LogicalDisplay display = mLogicalDisplays.valueAt(i);
394 if (display.mPrimaryDisplayDevice == device) {
395 final int displayId = mLogicalDisplays.keyAt(i);
396 mLogicalDisplays.removeAt(i);
397 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
398 }
399 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700400 }
401 }
402
Jeff Brownbd6e1502012-08-28 03:27:37 -0700403 // Posts a message to send a display event at the next opportunity.
404 private void sendDisplayEventLocked(int displayId, int event) {
405 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
406 mHandler.sendMessage(msg);
407 }
408
409 // Runs on handler.
410 // This method actually sends display event notifications.
411 // Note that it must be very careful not to be holding the lock while sending
412 // is in progress.
413 private void deliverDisplayEvent(int displayId, int event) {
414 if (DEBUG) {
415 Slog.d(TAG, "Delivering display event: displayId=" + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700416 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700417
Jeff Brownbd6e1502012-08-28 03:27:37 -0700418 final int count;
419 synchronized (mLock) {
420 count = mCallbacks.size();
421 mTempCallbacks.clear();
422 for (int i = 0; i < count; i++) {
423 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700424 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700425 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700426
Jeff Brownbd6e1502012-08-28 03:27:37 -0700427 for (int i = 0; i < count; i++) {
428 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
429 }
430 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700431 }
432
Jeff Brownfa25bf52012-07-23 19:26:30 -0700433 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700434 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700435 if (mContext == null
436 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
437 != PackageManager.PERMISSION_GRANTED) {
438 pw.println("Permission Denial: can't dump DisplayManager from from pid="
439 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
440 return;
441 }
442
Jeff Brownbd6e1502012-08-28 03:27:37 -0700443 pw.println("DISPLAY MANAGER (dumpsys display)");
444 pw.println(" mHeadless=" + mHeadless);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700445
Jeff Brownbd6e1502012-08-28 03:27:37 -0700446 mHandler.runWithScissors(new Runnable() {
447 @Override
448 public void run() {
449 dumpLocal(pw);
450 }
451 });
452 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700453
Jeff Brownbd6e1502012-08-28 03:27:37 -0700454 // Runs on handler.
455 private void dumpLocal(PrintWriter pw) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700456 synchronized (mLock) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700457 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
458
459 pw.println();
460 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700461 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700462 pw.println(" " + adapter.getName());
463 adapter.dump(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700464 }
Craig Mautner9de49362012-08-02 14:30:30 -0700465
Jeff Brownbd6e1502012-08-28 03:27:37 -0700466 pw.println();
467 pw.println("Display Devices: size=" + mDisplayDevices.size());
468 for (DisplayDevice device : mDisplayDevices) {
469 pw.println(" " + device);
470 }
471
472 final int logicalDisplayCount = mLogicalDisplays.size();
473 pw.println();
474 pw.println("Logical Displays: size=" + logicalDisplayCount);
475 for (int i = 0; i < logicalDisplayCount; i++) {
476 int displayId = mLogicalDisplays.keyAt(i);
477 LogicalDisplay display = mLogicalDisplays.valueAt(i);
478 pw.println(" Display " + displayId + ":");
479 pw.println(" mPrimaryDisplayDevice=" + display.mPrimaryDisplayDevice);
480 pw.println(" mBaseDisplayInfo=" + display.mBaseDisplayInfo);
481 pw.println(" mOverrideDisplayInfo="
482 + display.mOverrideDisplayInfo);
483 }
484 }
485 }
486
487 private final class DisplayManagerHandler extends Handler {
488 public DisplayManagerHandler(Looper looper) {
489 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700490 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700491
Jeff Brownbd6e1502012-08-28 03:27:37 -0700492 @Override
493 public void handleMessage(Message msg) {
494 switch (msg.what) {
495 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
496 registerDefaultDisplayAdapter();
497 break;
498
499 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
500 registerAdditionalDisplayAdapters();
501 break;
502
503 case MSG_DELIVER_DISPLAY_EVENT:
504 deliverDisplayEvent(msg.arg1, msg.arg2);
505 break;
506 }
507 }
508 }
509
510 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
511 @Override
512 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
513 switch (event) {
514 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
515 handleDisplayDeviceAdded(device);
516 break;
517
518 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
519 handleDisplayDeviceChanged(device);
520 break;
521
522 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
523 handleDisplayDeviceRemoved(device);
524 break;
525 }
526 }
527 }
528
529 private final class CallbackRecord implements DeathRecipient {
530 private final int mPid;
531 private final IDisplayManagerCallback mCallback;
532
533 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
534 mPid = pid;
535 mCallback = callback;
536 }
537
538 @Override
539 public void binderDied() {
540 if (DEBUG) {
541 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
542 }
543 onCallbackDied(mPid);
544 }
545
546 public void notifyDisplayEventAsync(int displayId, int event) {
547 try {
548 mCallback.onDisplayEvent(displayId, event);
549 } catch (RemoteException ex) {
550 Slog.w(TAG, "Failed to notify process "
551 + mPid + " that displays changed, assuming it died.", ex);
552 binderDied();
553 }
554 }
555 }
556
557 /**
558 * Each logical display is primarily associated with one display device.
559 * The primary display device is nominally responsible for the basic properties
560 * of the logical display such as its size, refresh rate, and dpi.
561 *
562 * A logical display may be mirrored onto other display devices besides its
563 * primary display device, but it always remains bound to its primary.
564 * Note that the contents of a logical display may not always be visible, even
565 * on its primary display device, such as in the case where the logical display's
566 * primary display device is currently mirroring content from a different logical display.
567 */
568 private final static class LogicalDisplay {
569 public final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
570 public DisplayInfo mOverrideDisplayInfo; // set by the window manager
571
572 public final DisplayDevice mPrimaryDisplayDevice;
573 public final DisplayDeviceInfo mPrimaryDisplayDeviceInfo = new DisplayDeviceInfo();
574
575 public LogicalDisplay(DisplayDevice primaryDisplayDevice) {
576 mPrimaryDisplayDevice = primaryDisplayDevice;
577 }
578
579 public void updateFromPrimaryDisplayDevice() {
580 // Bootstrap the logical display using its associated primary physical display.
581 mPrimaryDisplayDevice.getInfo(mPrimaryDisplayDeviceInfo);
582
583 mBaseDisplayInfo.appWidth = mPrimaryDisplayDeviceInfo.width;
584 mBaseDisplayInfo.appHeight = mPrimaryDisplayDeviceInfo.height;
585 mBaseDisplayInfo.logicalWidth = mPrimaryDisplayDeviceInfo.width;
586 mBaseDisplayInfo.logicalHeight = mPrimaryDisplayDeviceInfo.height;
587 mBaseDisplayInfo.rotation = Surface.ROTATION_0;
588 mBaseDisplayInfo.refreshRate = mPrimaryDisplayDeviceInfo.refreshRate;
589 mBaseDisplayInfo.logicalDensityDpi = mPrimaryDisplayDeviceInfo.densityDpi;
590 mBaseDisplayInfo.physicalXDpi = mPrimaryDisplayDeviceInfo.xDpi;
591 mBaseDisplayInfo.physicalYDpi = mPrimaryDisplayDeviceInfo.yDpi;
592 mBaseDisplayInfo.smallestNominalAppWidth = mPrimaryDisplayDeviceInfo.width;
593 mBaseDisplayInfo.smallestNominalAppHeight = mPrimaryDisplayDeviceInfo.height;
594 mBaseDisplayInfo.largestNominalAppWidth = mPrimaryDisplayDeviceInfo.width;
595 mBaseDisplayInfo.largestNominalAppHeight = mPrimaryDisplayDeviceInfo.height;
596 }
Craig Mautner9de49362012-08-02 14:30:30 -0700597 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700598}