DisplayManagerService.java revision bd6e1500aedc5461e832f69e76341bff0e55fa2b
1/*
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
19import com.android.internal.util.IndentingPrintWriter;
20
21import android.Manifest;
22import android.content.Context;
23import android.content.pm.PackageManager;
24import android.hardware.display.DisplayManagerGlobal;
25import android.hardware.display.IDisplayManager;
26import android.hardware.display.IDisplayManagerCallback;
27import android.os.Binder;
28import android.os.Handler;
29import android.os.IBinder;
30import android.os.Looper;
31import android.os.Message;
32import android.os.RemoteException;
33import android.os.SystemClock;
34import android.os.SystemProperties;
35import android.util.Slog;
36import android.util.SparseArray;
37import android.view.Display;
38import android.view.DisplayInfo;
39import android.view.Surface;
40
41import java.io.FileDescriptor;
42import java.io.PrintWriter;
43import java.io.StringWriter;
44import java.util.ArrayList;
45
46/**
47 * Manages attached displays.
48 * <p>
49 * 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.
75 * </p>
76 */
77public final class DisplayManagerService extends IDisplayManager.Stub {
78    private static final String TAG = "DisplayManagerService";
79    private static final boolean DEBUG = false;
80
81    private static final String SYSTEM_HEADLESS = "ro.config.headless";
82    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;
87
88    private final Object mLock = new Object();
89
90    private final Context mContext;
91    private final boolean mHeadless;
92
93    private final DisplayManagerHandler mHandler;
94    private final DisplayAdapterListener mDisplayAdapterListener = new DisplayAdapterListener();
95    private final SparseArray<CallbackRecord> mCallbacks =
96            new SparseArray<CallbackRecord>();
97
98    // 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) {
120        mContext = context;
121        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
122
123        mHandler = new DisplayManagerHandler(uiHandler.getLooper());
124        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
125    }
126
127    /**
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.
162    private void registerDefaultDisplayAdapter() {
163        // Register default display adapter.
164        if (mHeadless) {
165            registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
166        } else {
167            registerDisplayAdapter(new LocalDisplayAdapter(mContext));
168        }
169    }
170
171    // 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
199    // FIXME: this isn't the right API for the long term
200    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
207    /**
208     * Returns true if the device is headless.
209     *
210     * @return True if the device is headless.
211     */
212    public boolean isHeadless() {
213        return mHeadless;
214    }
215
216    /**
217     * Sets the new logical display orientation.
218     *
219     * @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) {
224            // 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.");
312            }
313
314            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);
379                }
380            }
381        }
382    }
383
384    // Runs on handler.
385    private void handleDisplayDeviceRemoved(DisplayDevice device) {
386        synchronized (mLock) {
387            if (!mDisplayDevices.remove(device)) {
388                Slog.w(TAG, "Attempted to remove non-existent display device: " + device);
389                return;
390            }
391
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            }
400        }
401    }
402
403    // 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);
416        }
417
418        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));
424            }
425        }
426
427        for (int i = 0; i < count; i++) {
428            mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
429        }
430        mTempCallbacks.clear();
431    }
432
433    @Override // Binder call
434    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
435        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
443        pw.println("DISPLAY MANAGER (dumpsys display)");
444        pw.println("  mHeadless=" + mHeadless);
445
446        mHandler.runWithScissors(new Runnable() {
447            @Override
448            public void run() {
449                dumpLocal(pw);
450            }
451        });
452    }
453
454    // Runs on handler.
455    private void dumpLocal(PrintWriter pw) {
456        synchronized (mLock) {
457            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
458
459            pw.println();
460            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
461            for (DisplayAdapter adapter : mDisplayAdapters) {
462                pw.println("  " + adapter.getName());
463                adapter.dump(ipw);
464            }
465
466            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*/);
490        }
491
492        @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        }
597    }
598}
599