1fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown/*
2fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Copyright (C) 2012 The Android Open Source Project
3fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
4fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * you may not use this file except in compliance with the License.
6fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * You may obtain a copy of the License at
7fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
8fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
10fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Unless required by applicable law or agreed to in writing, software
11fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * See the License for the specific language governing permissions and
14fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * limitations under the License.
15fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown */
16fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
17fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownpackage com.android.server.display;
18fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
19bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport com.android.internal.util.IndentingPrintWriter;
20bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
21fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.Manifest;
22fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.content.Context;
23fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.content.pm.PackageManager;
24bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.hardware.display.DisplayManagerGlobal;
25fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.hardware.display.IDisplayManager;
26bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.hardware.display.IDisplayManagerCallback;
27e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplayStatus;
28fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.os.Binder;
29bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Handler;
3064a55af0ac700baecb0877235eb42caac59a3560Jeff Brownimport android.os.IBinder;
31bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Looper;
32bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.Message;
33bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.RemoteException;
34bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.os.SystemClock;
35fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.os.SystemProperties;
36bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.Slog;
37bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brownimport android.util.SparseArray;
38fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.view.Display;
39fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport android.view.DisplayInfo;
40fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
41fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport java.io.FileDescriptor;
42fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport java.io.PrintWriter;
43fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownimport java.util.ArrayList;
44fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
45fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown/**
46bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Manages attached displays.
47fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * <p>
48bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * The {@link DisplayManagerService} manages the global lifecycle of displays,
49bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * decides how to configure logical displays based on the physical display devices currently
50bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * attached, sends notifications to the system and to applications when the state
51bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * changes, and so on.
52bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p><p>
53bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * The display manager service relies on a collection of {@link DisplayAdapter} components,
54bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * for discovering and configuring physical display devices attached to the system.
55bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * There are separate display adapters for each manner that devices are attached:
56bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * one display adapter for built-in local displays, one for simulated non-functional
57bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * displays when the system is headless, one for simulated overlay displays used for
58bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * development, one for wifi displays, etc.
59bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p><p>
60bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Display adapters are only weakly coupled to the display manager service.
61bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * Display adapters communicate changes in display device state to the display manager
62722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner * service asynchronously via a {@link DisplayAdapter.Listener} registered
63bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * by the display manager service.  This separation of concerns is important for
64bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * two main reasons.  First, it neatly encapsulates the responsibilities of these
65bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * two classes: display adapters handle individual display devices whereas
66bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * the display manager service handles the global state.  Second, it eliminates
67bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * the potential for deadlocks resulting from asynchronous display device discovery.
684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * </p>
694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown *
704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * <h3>Synchronization</h3>
714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * <p>
724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Because the display manager may be accessed by multiple threads, the synchronization
734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * story gets a little complicated.  In particular, the window manager may call into
744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * the display manager while holding a surface transaction with the expectation that
754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * it can apply changes immediately.  Unfortunately, that means we can't just do
764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * everything asynchronously (*grump*).
77bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown * </p><p>
784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * To make this work, all of the objects that belong to the display manager must
794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * use the same lock.  We call this lock the synchronization root and it has a unique
804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * named with the "Locked" suffix.
824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * </p><p>
834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * Where things get tricky is that the display manager is not allowed to make
844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * any potentially reentrant calls, especially into the window manager.  We generally
854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown * avoid this by making all potentially reentrant out-calls asynchronous.
86fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * </p>
87fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown */
88fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownpublic final class DisplayManagerService extends IDisplayManager.Stub {
89fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    private static final String TAG = "DisplayManagerService";
90bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final boolean DEBUG = false;
91fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
92bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown    // When this system property is set to 0, WFD is forcibly disabled on boot.
93bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown    // When this system property is set to 1, WFD is forcibly enabled on boot.
94bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown    // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
95bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown    private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
96bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown
97fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    private static final String SYSTEM_HEADLESS = "ro.config.headless";
98bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
99bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
100bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
101bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
102bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
1034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private static final int MSG_REQUEST_TRAVERSAL = 4;
104d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private static final int MSG_UPDATE_VIEWPORT = 5;
105fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
1069e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
1079e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
1089e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
1099e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
110848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown    private final Context mContext;
111fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    private final boolean mHeadless;
112bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private final DisplayManagerHandler mHandler;
1134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final Handler mUiHandler;
1144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayAdapterListener mDisplayAdapterListener;
1154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private WindowManagerFuncs mWindowManagerFuncs;
116d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private InputManagerFuncs mInputManagerFuncs;
1174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // The synchronization root for the display manager.
1194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // This lock guards most of the display manager's state.
1204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SyncRoot mSyncRoot = new SyncRoot();
1214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // True if in safe mode.
1234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // This option may disable certain display adapters.
1244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public boolean mSafeMode;
1254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
1264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // True if we are in a special boot mode where only core applications and
1274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // services should be started.  This option may disable certain display adapters.
1284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public boolean mOnlyCore;
1294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
13027f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    // True if the display manager service should pretend there is only one display
13127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    // and only tell applications about the existence of the default logical display.
13227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    // The display manager can still mirror content to secondary displays but applications
13327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    // cannot present unique content on those displays.
13427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    // Used for demonstration purposes only.
13527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    private final boolean mSingleDisplayDemoMode;
13627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown
1374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // All callback records indexed by calling process id.
1384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public final SparseArray<CallbackRecord> mCallbacks =
139bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            new SparseArray<CallbackRecord>();
140bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
141bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    // List of all currently registered display adapters.
142fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
143fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
144bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    // List of all currently connected display devices.
145bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
146bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1474ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // List of all removed display devices.
1484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
149bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // List of all logical displays indexed by logical display id.
1514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final SparseArray<LogicalDisplay> mLogicalDisplays =
1524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            new SparseArray<LogicalDisplay>();
1534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
154bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1559e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    // Set to true if all displays have been blanked by the power manager.
1569e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    private int mAllDisplayBlankStateFromPowerManager;
1579e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
1584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Set to true when there are pending display changes that have yet to be applied
1594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // to the surface flinger state.
1604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean mPendingTraversal;
161bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
162e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    // The Wifi display adapter, or null if not registered.
163e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private WifiDisplayAdapter mWifiDisplayAdapter;
164e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
165d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    // Viewports of the default display and the display that should receive touch
166d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    // input from an external source.  Used by the input system.
167d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private final DisplayViewport mDefaultViewport = new DisplayViewport();
168d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
169d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    // Persistent data store for all internal settings maintained by the display manager service.
17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
173bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    // Temporary callback list, used when sending display events to applications.
1744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // May be used outside of the lock but only on the handler thread.
1754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
176bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Temporary display info, used for comparing display configurations.
1784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
1794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
180d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    // Temporary viewports, used when sending new viewport information to the
181d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    // input system.  May be used outside of the lock but only on the handler thread.
182d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
183d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
184d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
1854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
186848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown        mContext = context;
187fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
188848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown
1894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mHandler = new DisplayManagerHandler(mainHandler.getLooper());
1904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mUiHandler = uiHandler;
1914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDisplayAdapterListener = new DisplayAdapterListener();
19227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown        mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
1934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
194bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
195bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
196bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
197bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    /**
198bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     * Pauses the boot process to wait for the first display to be initialized.
199bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     */
200bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public boolean waitForDefaultDisplay() {
2014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
202bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
203bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
204bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                long delay = timeout - SystemClock.uptimeMillis();
205bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                if (delay <= 0) {
206bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    return false;
207bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                }
208bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                if (DEBUG) {
209bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
210bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                }
211bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                try {
2124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    mSyncRoot.wait(delay);
213bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                } catch (InterruptedException ex) {
214bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                }
215bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
216bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
217bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        return true;
218bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
219bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
220bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    /**
221d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Called during initialization to associate the display manager with the
2224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * window manager.
2234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
2244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
2254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
2264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mWindowManagerFuncs = windowManagerFuncs;
22765d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            scheduleTraversalLocked(false);
2284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
2294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
232d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Called during initialization to associate the display manager with the
233d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * input manager.
234d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
235d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public void setInputManager(InputManagerFuncs inputManagerFuncs) {
236d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        synchronized (mSyncRoot) {
237d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            mInputManagerFuncs = inputManagerFuncs;
23865d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            scheduleTraversalLocked(false);
239d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        }
240d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    }
241d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
242d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
243bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     * Called when the system is ready to go.
244bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     */
245bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public void systemReady(boolean safeMode, boolean onlyCore) {
2464ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
247bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mSafeMode = safeMode;
248bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mOnlyCore = onlyCore;
249bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
250bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
2514ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
252fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    }
253fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
254848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown    /**
255848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown     * Returns true if the device is headless.
256848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown     *
257848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown     * @return True if the device is headless.
258848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown     */
259fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public boolean isHeadless() {
260fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        return mHeadless;
261fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    }
262fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
2634f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner    /**
2644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Overrides the display information of a particular logical display.
2654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * This is used by the window manager to control the size and characteristics
2664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * of the default display.  It is expected to apply the requested change
2674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * to the display information synchronously so that applications will immediately
2684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * observe the new state.
269bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     *
27064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown     * @param displayId The logical display id.
2714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * @param info The new data to be stored.
27264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown     */
2734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void setDisplayInfoOverrideFromWindowManager(
2744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            int displayId, DisplayInfo info) {
2754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
276bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            LogicalDisplay display = mLogicalDisplays.get(displayId);
2774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (display != null) {
2784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
2794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                display.setDisplayInfoOverrideFromWindowManagerLocked(info);
2804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
2814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
28265d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner                    scheduleTraversalLocked(false);
28364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown                }
28464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            }
28564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        }
28664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    }
28764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
28864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    /**
2894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Called by the window manager to perform traversals while holding a
2904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * surface flinger transaction.
2914f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner     */
2924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public void performTraversalInTransactionFromWindowManager() {
2934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
2944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!mPendingTraversal) {
2954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return;
2964f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner            }
2974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mPendingTraversal = false;
2984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            performTraversalInTransactionLocked();
3004f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner        }
3014f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner    }
3024f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner
3034f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner    /**
3049e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown     * Called by the power manager to blank all displays.
3059e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown     */
3069e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    public void blankAllDisplaysFromPowerManager() {
3079e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        synchronized (mSyncRoot) {
3089e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
3099e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
3109e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
3119e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                final int count = mDisplayDevices.size();
3129e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                for (int i = 0; i < count; i++) {
3139e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    DisplayDevice device = mDisplayDevices.get(i);
3149e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    device.blankLocked();
3159e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                }
3168ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown
3178ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown                scheduleTraversalLocked(false);
3189e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            }
3199e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        }
3209e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    }
3219e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
3229e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    /**
3239e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown     * Called by the power manager to unblank all displays.
3249e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown     */
3259e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    public void unblankAllDisplaysFromPowerManager() {
3269e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        synchronized (mSyncRoot) {
3279e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
3289e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
3299e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
3309e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                final int count = mDisplayDevices.size();
3319e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                for (int i = 0; i < count; i++) {
3329e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    DisplayDevice device = mDisplayDevices.get(i);
3339e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    device.unblankLocked();
3349e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                }
3358ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown
3368ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown                scheduleTraversalLocked(false);
3379e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            }
3389e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown        }
3399e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    }
3409e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
3419e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown    /**
342bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     * Returns information about the specified logical display.
343bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     *
344bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown     * @param displayId The logical display id.
345722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * @return The logical display info, or null if the display does not exist.  The
346722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * returned object must be treated as immutable.
3474f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner     */
348fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    @Override // Binder call
349bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public DisplayInfo getDisplayInfo(int displayId) {
3504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
351bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            LogicalDisplay display = mLogicalDisplays.get(displayId);
352bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            if (display != null) {
3534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return display.getDisplayInfoLocked();
3544f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner            }
355bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            return null;
3564f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner        }
3574f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner    }
3584f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner
3594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
3604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Returns the list of all display ids.
3614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
362bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    @Override // Binder call
363bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public int[] getDisplayIds() {
3644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
365bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            final int count = mLogicalDisplays.size();
366bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            int[] displayIds = new int[count];
3674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            for (int i = 0; i < count; i++) {
368bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                displayIds[i] = mLogicalDisplays.keyAt(i);
3694f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner            }
370bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            return displayIds;
371bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
372bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
3734f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner
374bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    @Override // Binder call
375bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public void registerCallback(IDisplayManagerCallback callback) {
376bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        if (callback == null) {
377bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            throw new IllegalArgumentException("listener must not be null");
378bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
379bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
3804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
381bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            int callingPid = Binder.getCallingPid();
382bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            if (mCallbacks.get(callingPid) != null) {
383bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                throw new SecurityException("The calling process has already "
384bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                        + "registered an IDisplayManagerCallback.");
3854f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner            }
386bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
387bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            CallbackRecord record = new CallbackRecord(callingPid, callback);
388bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            try {
389bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                IBinder binder = callback.asBinder();
390bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                binder.linkToDeath(record, 0);
391bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            } catch (RemoteException ex) {
392bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                // give up
393bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                throw new RuntimeException(ex);
394bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
395bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
396bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mCallbacks.put(callingPid, record);
397bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
3989de4936c99b979f6010440b043edc6d6142d1980Craig Mautner    }
3999de4936c99b979f6010440b043edc6d6142d1980Craig Mautner
400bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private void onCallbackDied(int pid) {
4014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
402bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mCallbacks.remove(pid);
403bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
404bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
405bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
406e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    @Override // Binder call
407e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public void scanWifiDisplays() {
408e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        final long token = Binder.clearCallingIdentity();
409e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        try {
410e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (mSyncRoot) {
41121c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                if (mWifiDisplayAdapter != null) {
41221c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                    mWifiDisplayAdapter.requestScanLocked();
41321c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                }
414e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
415e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        } finally {
416e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            Binder.restoreCallingIdentity(token);
417e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
418e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
419e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
420e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    @Override // Binder call
421e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public void connectWifiDisplay(String address) {
422e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        if (address == null) {
423e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            throw new IllegalArgumentException("address must not be null");
424e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
425e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
426bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        final boolean trusted = canCallerConfigureWifiDisplay();
427e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        final long token = Binder.clearCallingIdentity();
428e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        try {
429e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (mSyncRoot) {
43021c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                if (mWifiDisplayAdapter != null) {
431bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                    mWifiDisplayAdapter.requestConnectLocked(address, trusted);
43221c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                }
433e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
434e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        } finally {
435e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            Binder.restoreCallingIdentity(token);
436e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
437e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
438e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
439e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    @Override // Binder call
440e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public void disconnectWifiDisplay() {
441e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        final long token = Binder.clearCallingIdentity();
442e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        try {
443e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (mSyncRoot) {
44421c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                if (mWifiDisplayAdapter != null) {
44521c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                    mWifiDisplayAdapter.requestDisconnectLocked();
44621c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                }
447e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
448e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        } finally {
449e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            Binder.restoreCallingIdentity(token);
450e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
451e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
452e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
453e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    @Override // Binder call
45489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    public void renameWifiDisplay(String address, String alias) {
45589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (address == null) {
45689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            throw new IllegalArgumentException("address must not be null");
45789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
458bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        if (!canCallerConfigureWifiDisplay()) {
459bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
460bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                    + "rename a wifi display.");
461bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        }
46289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
46389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        final long token = Binder.clearCallingIdentity();
46489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        try {
46589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            synchronized (mSyncRoot) {
46689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                if (mWifiDisplayAdapter != null) {
46789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mWifiDisplayAdapter.requestRenameLocked(address, alias);
46889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                }
46989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            }
47089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        } finally {
47189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            Binder.restoreCallingIdentity(token);
47289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
47389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
47489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
47589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    @Override // Binder call
47689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    public void forgetWifiDisplay(String address) {
47789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (address == null) {
47889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            throw new IllegalArgumentException("address must not be null");
47989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
480bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        if (!canCallerConfigureWifiDisplay()) {
481bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
482bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                    + "forget a wifi display.");
483bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        }
48489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
48589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        final long token = Binder.clearCallingIdentity();
48689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        try {
48789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            synchronized (mSyncRoot) {
48889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                if (mWifiDisplayAdapter != null) {
48989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mWifiDisplayAdapter.requestForgetLocked(address);
49089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                }
49189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            }
49289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        } finally {
49389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            Binder.restoreCallingIdentity(token);
49489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
49589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
49689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
49789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    @Override // Binder call
498e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public WifiDisplayStatus getWifiDisplayStatus() {
499e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        final long token = Binder.clearCallingIdentity();
500e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        try {
501e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (mSyncRoot) {
50221c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                if (mWifiDisplayAdapter != null) {
50321c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                    return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
50421c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                } else {
50521c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                    return new WifiDisplayStatus();
50621c7153d30071dcbeb92daa1fd48ed181e42aef3Jeff Brown                }
507e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
508e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        } finally {
509e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            Binder.restoreCallingIdentity(token);
510e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
511e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
512e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
513bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown    private boolean canCallerConfigureWifiDisplay() {
514bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
515bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                == PackageManager.PERMISSION_GRANTED;
516bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown    }
517bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown
5184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void registerDefaultDisplayAdapter() {
5194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Register default display adapter.
5204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
5214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (mHeadless) {
5224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
5234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
5244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            } else {
5254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                registerDisplayAdapterLocked(new LocalDisplayAdapter(
5264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
527bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
5284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
5294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
530bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
5314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void registerAdditionalDisplayAdapters() {
5324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
5334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
53489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                registerOverlayDisplayAdapterLocked();
53589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                registerWifiDisplayAdapterLocked();
536bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
5374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
5384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
539bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
54089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private void registerOverlayDisplayAdapterLocked() {
54189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        registerDisplayAdapterLocked(new OverlayDisplayAdapter(
54289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
54389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
54489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
54589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private void registerWifiDisplayAdapterLocked() {
54689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (mContext.getResources().getBoolean(
547bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown                com.android.internal.R.bool.config_enableWifiDisplay)
548bbd28a293f84baeafed469c5e223eff82c1117c0Jeff Brown                || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
54989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            mWifiDisplayAdapter = new WifiDisplayAdapter(
55089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
55189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mPersistentDataStore);
55289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            registerDisplayAdapterLocked(mWifiDisplayAdapter);
55389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
55489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
55589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
5564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
5574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // In safe mode, we disable non-essential display adapters to give the user
5584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // an opportunity to fix broken settings or other problems that might affect
5594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // system stability.
5604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // In only-core mode, we disable non-essential display adapters to minimize
5614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // the number of dependencies that are started while in this mode and to
5624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // prevent problems that might occur due to the device being encrypted.
5634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return !mSafeMode && !mOnlyCore;
5644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
565bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
5664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
5674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mDisplayAdapters.add(adapter);
5684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        adapter.registerLocked();
5694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
570bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
5714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void handleDisplayDeviceAdded(DisplayDevice device) {
5724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
5734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (mDisplayDevices.contains(device)) {
5744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Slog.w(TAG, "Attempted to add already added display device: "
5754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                        + device.getDisplayDeviceInfoLocked());
5764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return;
577bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
5784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
579e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
580e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
5814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mDisplayDevices.add(device);
5824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            addLogicalDisplayLocked(device);
58365d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            scheduleTraversalLocked(false);
5849e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
5859e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            // Blank or unblank the display immediately to match the state requested
5869e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            // by the power manager (if known).
5879e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            switch (mAllDisplayBlankStateFromPowerManager) {
5889e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                case DISPLAY_BLANK_STATE_BLANKED:
5899e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    device.blankLocked();
5909e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    break;
5919e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                case DISPLAY_BLANK_STATE_UNBLANKED:
5929e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    device.unblankLocked();
5939e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    break;
5949e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            }
595bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
596bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
597bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
598bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private void handleDisplayDeviceChanged(DisplayDevice device) {
5994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
600bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            if (!mDisplayDevices.contains(device)) {
6014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Slog.w(TAG, "Attempted to change non-existent display device: "
6024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                        + device.getDisplayDeviceInfoLocked());
603bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                return;
604bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
605bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
606e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
607e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
6084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            device.applyPendingDisplayDeviceInfoChangesLocked();
6094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (updateLogicalDisplaysLocked()) {
61065d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner                scheduleTraversalLocked(false);
611bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
612bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
613bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
614bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
615bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private void handleDisplayDeviceRemoved(DisplayDevice device) {
6164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
617bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            if (!mDisplayDevices.remove(device)) {
6184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                Slog.w(TAG, "Attempted to remove non-existent display device: "
6194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                        + device.getDisplayDeviceInfoLocked());
620bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                return;
621bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
622bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
623e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
624e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
6254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mRemovedDisplayDevices.add(device);
6264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            updateLogicalDisplaysLocked();
62765d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            scheduleTraversalLocked(false);
6284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
6294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
6304ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Adds a new logical display based on the given display device.
6324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Sends notifications if needed.
6334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void addLogicalDisplayLocked(DisplayDevice device) {
6344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
6354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        boolean isDefault = (deviceInfo.flags
6364ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
6374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
6384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
6394ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            isDefault = false;
6404ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
6414ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
64227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown        if (!isDefault && mSingleDisplayDemoMode) {
64327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown            Slog.i(TAG, "Not creating a logical display for a secondary display "
64427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown                    + " because single display demo mode is enabled: " + deviceInfo);
64527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown            return;
64627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown        }
64727f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown
6484ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        final int displayId = assignDisplayIdLocked(isDefault);
6494ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        final int layerStack = assignLayerStackLocked(displayId);
6504ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
651d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
6524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        display.updateLocked(mDisplayDevices);
6534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!display.isValidLocked()) {
6544ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // This should never happen currently.
6554ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.w(TAG, "Ignoring display device because the logical display "
6564ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + "created from it was not considered valid: " + deviceInfo);
6574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            return;
6584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
6594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mLogicalDisplays.put(displayId, display);
6614ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6624ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Wake up waitForDefaultDisplay.
6634ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (isDefault) {
6644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mSyncRoot.notifyAll();
6654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
6664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
6684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
6694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int assignDisplayIdLocked(boolean isDefault) {
6714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
6724ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
6734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6744ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private int assignLayerStackLocked(int displayId) {
6754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Currently layer stacks and display ids are the same.
6764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // This need not be the case.
6774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return displayId;
6784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
6794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Updates all existing logical displays given the current set of display devices.
6814ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Removes invalid logical displays.
6824ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Sends notifications if needed.
6834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private boolean updateLogicalDisplaysLocked() {
6844ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        boolean changed = false;
6854ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        for (int i = mLogicalDisplays.size(); i-- > 0; ) {
6864ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            final int displayId = mLogicalDisplays.keyAt(i);
6874ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            LogicalDisplay display = mLogicalDisplays.valueAt(i);
6884ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
6894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
6904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            display.updateLocked(mDisplayDevices);
6914ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (!display.isValidLocked()) {
6924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                mLogicalDisplays.removeAt(i);
6934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
6944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                changed = true;
6954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
6964ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
6974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                changed = true;
698bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
699bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
7004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return changed;
7014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
7024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
7034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private void performTraversalInTransactionLocked() {
7044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Perform one last traversal for each removed display device.
7054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        final int removedCount = mRemovedDisplayDevices.size();
7064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        for (int i = 0; i < removedCount; i++) {
7074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            DisplayDevice device = mRemovedDisplayDevices.get(i);
7084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            device.performTraversalInTransactionLocked();
7094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
7104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        mRemovedDisplayDevices.clear();
7114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
712d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        // Clear all viewports before configuring displays so that we can keep
713d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        // track of which ones we have configured.
714d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        clearViewportsLocked();
715d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
7164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Configure each display device.
7174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        final int count = mDisplayDevices.size();
7184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        for (int i = 0; i < count; i++) {
7194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            DisplayDevice device = mDisplayDevices.get(i);
7204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            configureDisplayInTransactionLocked(device);
7214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            device.performTraversalInTransactionLocked();
7224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
723d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
724d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        // Tell the input system about these new viewports.
725d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (mInputManagerFuncs != null) {
726d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
727d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        }
7284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
7294ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
730722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner    /**
731722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * Tells the display manager whether there is interesting unique content on the
732722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * specified logical display.  This is used to control automatic mirroring.
733722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * <p>
734722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * If the display has unique content, then the display manager arranges for it
735722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * to be presented on a physical display if appropriate.  Otherwise, the display manager
736722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * may choose to make the physical display mirror some other logical display.
737722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * </p>
738722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     *
739722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * @param displayId The logical display id to update.
740722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     * @param hasContent True if the logical display has content.
74165d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner     * @param inTraversal True if called from WindowManagerService during a window traversal prior
74265d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner     * to call to performTraversalInTransactionFromWindowManager.
743722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner     */
74465d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner    public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
745722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner        synchronized (mSyncRoot) {
746722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner            LogicalDisplay display = mLogicalDisplays.get(displayId);
747722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner            if (display != null && display.hasContentLocked() != hasContent) {
748722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner                display.setHasContentLocked(hasContent);
74965d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner                scheduleTraversalLocked(inTraversal);
750722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner            }
751722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner        }
752d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    }
7534ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
754d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private void clearViewportsLocked() {
755d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        mDefaultViewport.valid = false;
756d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        mExternalTouchViewport.valid = false;
757722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner    }
758722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner
759722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner    private void configureDisplayInTransactionLocked(DisplayDevice device) {
7604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Find the logical display that the display device is showing.
761722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner        LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
762722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner        if (display != null && !display.hasContentLocked()) {
763722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner            display = null;
7644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
7654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (display == null) {
7664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
7674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
7684ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
7694ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Apply the logical display configuration to the display device.
7704ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (display == null) {
7714ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            // TODO: no logical display for the device, blank it
772d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            Slog.w(TAG, "Missing logical display to use for physical display device: "
7734ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + device.getDisplayDeviceInfoLocked());
774d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            return;
7754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        } else {
7768ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown            boolean isBlanked = (mAllDisplayBlankStateFromPowerManager
7778ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown                    == DISPLAY_BLANK_STATE_BLANKED);
7788ec0943a7963178da838e4b6b842ec1109707b35Jeff Brown            display.configureDisplayInTransactionLocked(device, isBlanked);
7794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
780d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
781d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        // Update the viewports if needed.
782d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
783d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (!mDefaultViewport.valid
784d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
785d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            setViewportLocked(mDefaultViewport, display, device);
786d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        }
787d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (!mExternalTouchViewport.valid
788d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
789d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            setViewportLocked(mExternalTouchViewport, display, device);
790d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        }
791d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    }
792d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
793d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private static void setViewportLocked(DisplayViewport viewport,
794d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            LogicalDisplay display, DisplayDevice device) {
795d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        viewport.valid = true;
796d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        viewport.displayId = display.getDisplayIdLocked();
797d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        device.populateViewportLocked(viewport);
7984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
7994ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
8004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
8014ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        final int count = mLogicalDisplays.size();
8024ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        for (int i = 0; i < count; i++) {
8034ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            LogicalDisplay display = mLogicalDisplays.valueAt(i);
8044ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            if (display.getPrimaryDisplayDeviceLocked() == device) {
8054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                return display;
8064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
8074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
8084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return null;
809bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
810bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
811bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private void sendDisplayEventLocked(int displayId, int event) {
812bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
813bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        mHandler.sendMessage(msg);
814bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
815bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
8164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Requests that performTraversalsInTransactionFromWindowManager be called at a
8174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // later time to apply changes to surfaces and displays.
81865d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner    private void scheduleTraversalLocked(boolean inTraversal) {
8194ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        if (!mPendingTraversal && mWindowManagerFuncs != null) {
8204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            mPendingTraversal = true;
82165d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            if (!inTraversal) {
82265d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner                mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
82365d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner            }
8244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
8254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
8264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
8274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Runs on Handler thread.
8284ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    // Delivers display event notifications to callbacks.
829bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private void deliverDisplayEvent(int displayId, int event) {
830bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        if (DEBUG) {
8314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            Slog.d(TAG, "Delivering display event: displayId="
8324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    + displayId + ", event=" + event);
833bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
834bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
8354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // Grab the lock and copy the callbacks.
836bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        final int count;
8374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
838bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            count = mCallbacks.size();
839bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mTempCallbacks.clear();
840bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            for (int i = 0; i < count; i++) {
841bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                mTempCallbacks.add(mCallbacks.valueAt(i));
842bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
843bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
844bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
8454ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        // After releasing the lock, send the notifications out.
846bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        for (int i = 0; i < count; i++) {
847bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
848bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
849bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        mTempCallbacks.clear();
8504f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner    }
8514f67ba6ba4e861b287a3ff0323c107aa77f66264Craig Mautner
852fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    @Override // Binder call
853bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
854fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        if (mContext == null
855fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown                || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
856fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown                        != PackageManager.PERMISSION_GRANTED) {
857fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown            pw.println("Permission Denial: can't dump DisplayManager from from pid="
858fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
859fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown            return;
860fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        }
861fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
862bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        pw.println("DISPLAY MANAGER (dumpsys display)");
863fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
8644ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        synchronized (mSyncRoot) {
8659e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mHeadless=" + mHeadless);
8669e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mOnlyCode=" + mOnlyCore);
8679e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mSafeMode=" + mSafeMode);
8689e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mPendingTraversal=" + mPendingTraversal);
8699e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mAllDisplayBlankStateFromPowerManager="
8709e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown                    + mAllDisplayBlankStateFromPowerManager);
8719e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
8729e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mDefaultViewport=" + mDefaultViewport);
8739e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown            pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
87427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown            pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
8759e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown
876bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
8774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            ipw.increaseIndent();
878bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
879bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println();
880bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
881848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown            for (DisplayAdapter adapter : mDisplayAdapters) {
882bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                pw.println("  " + adapter.getName());
8834ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                adapter.dumpLocked(ipw);
884848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown            }
8859de4936c99b979f6010440b043edc6d6142d1980Craig Mautner
886bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println();
887bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println("Display Devices: size=" + mDisplayDevices.size());
888bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            for (DisplayDevice device : mDisplayDevices) {
8894ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                pw.println("  " + device.getDisplayDeviceInfoLocked());
8904ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                device.dumpLocked(ipw);
891bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
892bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
893bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            final int logicalDisplayCount = mLogicalDisplays.size();
894bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println();
895bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            pw.println("Logical Displays: size=" + logicalDisplayCount);
896bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            for (int i = 0; i < logicalDisplayCount; i++) {
897bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                int displayId = mLogicalDisplays.keyAt(i);
898bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                LogicalDisplay display = mLogicalDisplays.valueAt(i);
899bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                pw.println("  Display " + displayId + ":");
9004ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                display.dumpLocked(ipw);
901bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
902bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
903bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
904bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
9054ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
9064ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * This is the object that everything in the display manager locks on.
9074ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * We make it an inner class within the {@link DisplayManagerService} to so that it is
9084ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * clear that the object belongs to the display manager service and that it is
9094ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * a unique object with a special purpose.
9104ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
9114ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public static final class SyncRoot {
9124ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
9134ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
9144ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
9154ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Private interface to the window manager.
9164ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
9174ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public interface WindowManagerFuncs {
9184ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        /**
919722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner         * Request that the window manager call
920722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner         * {@link #performTraversalInTransactionFromWindowManager} within a surface
921722285e199a9fc74b9b3343b7505c00666848c88Craig Mautner         * transaction at a later time.
9224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown         */
9234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        void requestTraversal();
9244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
9254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
926d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
927d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Private interface to the input manager.
928d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
929d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public interface InputManagerFuncs {
930d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        /**
931d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown         * Sets information about the displays as needed by the input system.
932d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown         * The input system should copy this information if required.
933d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown         */
934d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        void setDisplayViewports(DisplayViewport defaultViewport,
935d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                DisplayViewport externalTouchViewport);
936d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    }
937d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
938bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private final class DisplayManagerHandler extends Handler {
939bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public DisplayManagerHandler(Looper looper) {
940bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            super(looper, null, true /*async*/);
941848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown        }
942bf5740e75efd87ae0213486e78e029403804c6f0Jeff Brown
943bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        @Override
944bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public void handleMessage(Message msg) {
945bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            switch (msg.what) {
946bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
947bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    registerDefaultDisplayAdapter();
948bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
949bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
950bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
951bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    registerAdditionalDisplayAdapters();
952bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
953bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
954bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case MSG_DELIVER_DISPLAY_EVENT:
955bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    deliverDisplayEvent(msg.arg1, msg.arg2);
956bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
9574ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
9584ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                case MSG_REQUEST_TRAVERSAL:
9594ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    mWindowManagerFuncs.requestTraversal();
9604ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown                    break;
961d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
962d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                case MSG_UPDATE_VIEWPORT: {
963d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    synchronized (mSyncRoot) {
964d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                        mTempDefaultViewport.copyFrom(mDefaultViewport);
965d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                        mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
966d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    }
967d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    mInputManagerFuncs.setDisplayViewports(
968d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                            mTempDefaultViewport, mTempExternalTouchViewport);
969d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                    break;
970d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                }
971bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
972bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
973bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
974bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
975bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private final class DisplayAdapterListener implements DisplayAdapter.Listener {
976bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        @Override
977bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
978bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            switch (event) {
979bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
980bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    handleDisplayDeviceAdded(device);
981bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
982bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
983bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
984bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    handleDisplayDeviceChanged(device);
985bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
986bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
987bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
988bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    handleDisplayDeviceRemoved(device);
989bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                    break;
990bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
991bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
9924ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
9934ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        @Override
9944ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        public void onTraversalRequested() {
9954ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            synchronized (mSyncRoot) {
99665d11b3eeff395011a2c6b56eb117fd3c4881c1aCraig Mautner                scheduleTraversalLocked(false);
9974ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown            }
9984ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        }
999bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
1000bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1001bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private final class CallbackRecord implements DeathRecipient {
1002bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        private final int mPid;
1003bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        private final IDisplayManagerCallback mCallback;
1004bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1005bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1006bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mPid = pid;
1007bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            mCallback = callback;
1008bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
1009bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1010bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        @Override
1011bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public void binderDied() {
1012bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            if (DEBUG) {
1013bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1014bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
1015bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            onCallbackDied(mPid);
1016bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
1017bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
1018bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        public void notifyDisplayEventAsync(int displayId, int event) {
1019bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            try {
1020bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                mCallback.onDisplayEvent(displayId, event);
1021bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            } catch (RemoteException ex) {
1022bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                Slog.w(TAG, "Failed to notify process "
1023bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                        + mPid + " that displays changed, assuming it died.", ex);
1024bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown                binderDied();
1025bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            }
1026bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
1027bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
1028fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown}
1029