2222import android .hardware .display .IDisplayManager ;
2323import android .os .Binder ;
2424import android .os .SystemProperties ;
25+ import android .util .Slog ;
26+ import android .util .SparseArray ;
2527import android .view .Display ;
2628import android .view .DisplayInfo ;
2729import android .view .Surface ;
@@ -47,28 +49,34 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
4749
4850 private Context mContext ;
4951 private final boolean mHeadless ;
52+
53+ private int mDisplayIdSeq = Display .DEFAULT_DISPLAY ;
54+
55+ /** All registered DisplayAdapters. */
5056 private final ArrayList <DisplayAdapter > mDisplayAdapters = new ArrayList <DisplayAdapter >();
5157
52- // TODO: represent this as a map between logical and physical devices
53- private DisplayInfo mDefaultDisplayInfo ;
54- private DisplayDevice mDefaultDisplayDevice ;
55- private DisplayDeviceInfo mDefaultDisplayDeviceInfo ;
58+ /** All the DisplayAdapters showing the given displayId. */
59+ private final SparseArray <ArrayList <DisplayAdapter >> mLogicalToPhysicals =
60+ new SparseArray <ArrayList <DisplayAdapter >>();
61+
62+ /** All the DisplayInfos in the system indexed by deviceId */
63+ private final SparseArray <DisplayInfo > mDisplayInfos = new SparseArray <DisplayInfo >();
5664
5765 public DisplayManagerService () {
5866 mHeadless = SystemProperties .get (SYSTEM_HEADLESS ).equals ("1" );
59- registerDisplayAdapters ();
60- initializeDefaultDisplay ();
67+ registerDefaultDisplayAdapter ();
6168 }
6269
63- public void setContext (Context context ) {
64- mContext = context ;
70+ private void registerDefaultDisplayAdapter () {
71+ if (mHeadless ) {
72+ registerDisplayAdapter (new HeadlessDisplayAdapter ());
73+ } else {
74+ registerDisplayAdapter (new SurfaceFlingerDisplayAdapter ());
75+ }
6576 }
6677
67- // FIXME: this isn't the right API for the long term
68- public void setDefaultDisplayInfo (DisplayInfo info ) {
69- synchronized (mLock ) {
70- mDefaultDisplayInfo .copyFrom (info );
71- }
78+ public void setContext (Context context ) {
79+ mContext = context ;
7280 }
7381
7482 // FIXME: this isn't the right API for the long term
@@ -83,17 +91,187 @@ public boolean isHeadless() {
8391 return mHeadless ;
8492 }
8593
94+ /**
95+ * Save away new DisplayInfo data.
96+ * @param displayId The local DisplayInfo to store the new data in.
97+ * @param info The new data to be stored.
98+ */
99+ public void setDisplayInfo (int displayId , DisplayInfo info ) {
100+ synchronized (mLock ) {
101+ DisplayInfo localInfo = mDisplayInfos .get (displayId );
102+ if (localInfo == null ) {
103+ localInfo = new DisplayInfo ();
104+ mDisplayInfos .put (displayId , localInfo );
105+ }
106+ localInfo .copyFrom (info );
107+ }
108+ }
109+
110+ /**
111+ * Return requested DisplayInfo.
112+ * @param displayId The data to retrieve.
113+ * @param outInfo The structure to receive the data.
114+ */
86115 @ Override // Binder call
87116 public boolean getDisplayInfo (int displayId , DisplayInfo outInfo ) {
88117 synchronized (mLock ) {
89- if (displayId == Display .DEFAULT_DISPLAY ) {
90- outInfo .copyFrom (mDefaultDisplayInfo );
91- return true ;
118+ DisplayInfo localInfo = mDisplayInfos .get (displayId );
119+ if (localInfo == null ) {
120+ return false ;
121+ }
122+ outInfo .copyFrom (localInfo );
123+ return true ;
124+ }
125+ }
126+
127+ /**
128+ * Inform the service of a new physical display. A new logical displayId is created and the new
129+ * physical display is immediately bound to it. Use removeAdapterFromDisplay to disconnect it.
130+ *
131+ * @param adapter The wrapper for information associated with the physical display.
132+ */
133+ public void registerDisplayAdapter (DisplayAdapter adapter ) {
134+ synchronized (mLock ) {
135+ int displayId = mDisplayIdSeq ++;
136+ adapter .setDisplayId (displayId );
137+
138+ createDisplayInfoLocked (displayId , adapter );
139+
140+ ArrayList <DisplayAdapter > list = new ArrayList <DisplayAdapter >();
141+ list .add (adapter );
142+ mLogicalToPhysicals .put (displayId , list );
143+
144+ mDisplayAdapters .add (adapter );
145+ }
146+
147+ // TODO: Notify SurfaceFlinger of new addition.
148+ }
149+
150+ /**
151+ * Connect a logical display to a physical display. Will remove the physical display from any
152+ * logical display it is currently attached to.
153+ *
154+ * @param displayId The logical display. Will be created if it does not already exist.
155+ * @param adapter The physical display.
156+ */
157+ public void addAdapterToDisplay (int displayId , DisplayAdapter adapter ) {
158+ if (adapter == null ) {
159+ // TODO: Or throw NPE?
160+ Slog .e (TAG , "addDeviceToDisplay: Attempt to add null adapter" );
161+ return ;
162+ }
163+
164+ synchronized (mLock ) {
165+ if (!mDisplayAdapters .contains (adapter )) {
166+ // TOOD: Handle unregistered adapter with exception or return value.
167+ Slog .e (TAG , "addDeviceToDisplay: Attempt to add an unregistered adapter" );
168+ return ;
169+ }
170+
171+ DisplayInfo displayInfo = mDisplayInfos .get (displayId );
172+ if (displayInfo == null ) {
173+ createDisplayInfoLocked (displayId , adapter );
174+ }
175+
176+ Integer oldDisplayId = adapter .getDisplayId ();
177+ if (oldDisplayId != Display .NO_DISPLAY ) {
178+ if (oldDisplayId == displayId ) {
179+ // adapter already added to displayId.
180+ return ;
181+ }
182+
183+ removeAdapterLocked (adapter );
184+ }
185+
186+ ArrayList <DisplayAdapter > list = mLogicalToPhysicals .get (displayId );
187+ if (list == null ) {
188+ list = new ArrayList <DisplayAdapter >();
189+ mLogicalToPhysicals .put (displayId , list );
190+ }
191+
192+ list .add (adapter );
193+ adapter .setDisplayId (displayId );
194+ }
195+
196+ // TODO: Notify SurfaceFlinger of new addition.
197+ }
198+
199+ /**
200+ * Disconnect the physical display from whichever logical display it is attached to.
201+ * @param adapter The physical display to detach.
202+ */
203+ public void removeAdapterFromDisplay (DisplayAdapter adapter ) {
204+ if (adapter == null ) {
205+ // TODO: Or throw NPE?
206+ return ;
207+ }
208+
209+ synchronized (mLock ) {
210+ if (!mDisplayAdapters .contains (adapter )) {
211+ // TOOD: Handle unregistered adapter with exception or return value.
212+ Slog .e (TAG , "removeDeviceFromDisplay: Attempt to remove an unregistered adapter" );
213+ return ;
214+ }
215+
216+ removeAdapterLocked (adapter );
217+ }
218+
219+ // TODO: Notify SurfaceFlinger of removal.
220+ }
221+
222+ /**
223+ * Create a new logical DisplayInfo and fill it in with information from the physical display.
224+ * @param displayId The logical identifier.
225+ * @param adapter The physical display for initial values.
226+ */
227+ private void createDisplayInfoLocked (int displayId , DisplayAdapter adapter ) {
228+ DisplayInfo displayInfo = new DisplayInfo ();
229+ DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo ();
230+ adapter .getDisplayDevice ().getInfo (deviceInfo );
231+ copyDisplayInfoFromDeviceInfo (displayInfo , deviceInfo );
232+ mDisplayInfos .put (displayId , displayInfo );
233+ }
234+
235+ /**
236+ * Disconnect a physical display from its logical display. If there are no more physical
237+ * displays attached to the logical display, delete the logical display.
238+ * @param adapter The physical display to detach.
239+ */
240+ void removeAdapterLocked (DisplayAdapter adapter ) {
241+ int displayId = adapter .getDisplayId ();
242+ adapter .setDisplayId (Display .NO_DISPLAY );
243+
244+ ArrayList <DisplayAdapter > list = mLogicalToPhysicals .get (displayId );
245+ if (list != null ) {
246+ list .remove (adapter );
247+ if (list .isEmpty ()) {
248+ mLogicalToPhysicals .remove (displayId );
249+ // TODO: Keep count of Windows attached to logical display and don't delete if
250+ // there are any outstanding. Also, what keeps the WindowManager from continuing
251+ // to use the logical display?
252+ mDisplayInfos .remove (displayId );
92253 }
93- return false ;
94254 }
95255 }
96256
257+ private void copyDisplayInfoFromDeviceInfo (DisplayInfo displayInfo ,
258+ DisplayDeviceInfo deviceInfo ) {
259+ // Bootstrap the logical display using the physical display.
260+ displayInfo .appWidth = deviceInfo .width ;
261+ displayInfo .appHeight = deviceInfo .height ;
262+ displayInfo .logicalWidth = deviceInfo .width ;
263+ displayInfo .logicalHeight = deviceInfo .height ;
264+ displayInfo .rotation = Surface .ROTATION_0 ;
265+ displayInfo .refreshRate = deviceInfo .refreshRate ;
266+ displayInfo .logicalDensityDpi = deviceInfo .densityDpi ;
267+ displayInfo .physicalXDpi = deviceInfo .xDpi ;
268+ displayInfo .physicalYDpi = deviceInfo .yDpi ;
269+ displayInfo .smallestNominalAppWidth = deviceInfo .width ;
270+ displayInfo .smallestNominalAppHeight = deviceInfo .height ;
271+ displayInfo .largestNominalAppWidth = deviceInfo .width ;
272+ displayInfo .largestNominalAppHeight = deviceInfo .height ;
273+ }
274+
97275 @ Override // Binder call
98276 public void dump (FileDescriptor fd , PrintWriter pw , String [] args ) {
99277 if (mContext == null
@@ -110,46 +288,11 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
110288
111289 DisplayDeviceInfo info = new DisplayDeviceInfo ();
112290 for (DisplayAdapter adapter : mDisplayAdapters ) {
113- pw .println ("Displays for adapter " + adapter .getName ());
114- for (DisplayDevice device : adapter .getDisplayDevices ()) {
115- device .getInfo (info );
116- pw .print (" " );
117- pw .println (info );
118- }
291+ pw .println ("Display for adapter " + adapter .getName ());
292+ DisplayDevice device = adapter .getDisplayDevice ();
293+ pw .print (" " );
294+ device .getInfo (info );
295+ pw .println (info );
119296 }
120297 }
121-
122- private void registerDisplayAdapters () {
123- if (mHeadless ) {
124- registerDisplayAdapter (new HeadlessDisplayAdapter ());
125- } else {
126- registerDisplayAdapter (new SurfaceFlingerDisplayAdapter ());
127- }
128- }
129-
130- private void registerDisplayAdapter (DisplayAdapter adapter ) {
131- // TODO: do this dynamically
132- mDisplayAdapters .add (adapter );
133- mDefaultDisplayDevice = adapter .getDisplayDevices ()[0 ];
134- mDefaultDisplayDeviceInfo = new DisplayDeviceInfo ();
135- mDefaultDisplayDevice .getInfo (mDefaultDisplayDeviceInfo );
136- }
137-
138- private void initializeDefaultDisplay () {
139- // Bootstrap the default logical display using the default physical display.
140- mDefaultDisplayInfo = new DisplayInfo ();
141- mDefaultDisplayInfo .appWidth = mDefaultDisplayDeviceInfo .width ;
142- mDefaultDisplayInfo .appHeight = mDefaultDisplayDeviceInfo .height ;
143- mDefaultDisplayInfo .logicalWidth = mDefaultDisplayDeviceInfo .width ;
144- mDefaultDisplayInfo .logicalHeight = mDefaultDisplayDeviceInfo .height ;
145- mDefaultDisplayInfo .rotation = Surface .ROTATION_0 ;
146- mDefaultDisplayInfo .refreshRate = mDefaultDisplayDeviceInfo .refreshRate ;
147- mDefaultDisplayInfo .logicalDensityDpi = mDefaultDisplayDeviceInfo .densityDpi ;
148- mDefaultDisplayInfo .physicalXDpi = mDefaultDisplayDeviceInfo .xDpi ;
149- mDefaultDisplayInfo .physicalYDpi = mDefaultDisplayDeviceInfo .yDpi ;
150- mDefaultDisplayInfo .smallestNominalAppWidth = mDefaultDisplayDeviceInfo .width ;
151- mDefaultDisplayInfo .smallestNominalAppHeight = mDefaultDisplayDeviceInfo .height ;
152- mDefaultDisplayInfo .largestNominalAppWidth = mDefaultDisplayDeviceInfo .width ;
153- mDefaultDisplayInfo .largestNominalAppHeight = mDefaultDisplayDeviceInfo .height ;
154- }
155298}
0 commit comments