Skip to content

Commit 2a642a4

Browse files
Craig MautnerAndroid (Google) Code Review
authored andcommitted
Merge "Refactor DisplayManagerService to be functional." into jb-mr1-dev
2 parents 9866d60 + 4f67ba6 commit 2a642a4

File tree

7 files changed

+264
-89
lines changed

7 files changed

+264
-89
lines changed

core/java/android/view/Display.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ public final class Display {
7272
*/
7373
public static final int DEFAULT_DISPLAY = 0;
7474

75+
/**
76+
* Uninitialized display.
77+
* @hide
78+
*/
79+
public static final int NO_DISPLAY = -1;
80+
7581
/**
7682
* Internal method to create a display.
7783
* Applications should use {@link android.view.WindowManager#getDefaultDisplay()}

services/java/com/android/server/display/DisplayAdapter.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,38 @@
1616

1717
package com.android.server.display;
1818

19+
import android.view.Display;
20+
1921
/**
20-
* A display adapter makes one or more display devices available to the system.
22+
* A display adapter makes a single display devices available to the system.
2123
* <p>
2224
* For now, all display adapters are registered in the system server but
2325
* in principle it could be done from other processes.
2426
* </p>
2527
*/
2628
public abstract class DisplayAdapter {
29+
/** The current logical Display assignment for this adapter. Will change if other logical
30+
* display is assigned to this adapter */
31+
private int mDisplayId = Display.NO_DISPLAY;
32+
33+
/** Assign the displayId
34+
* @hide */
35+
public void setDisplayId(int displayId) {
36+
mDisplayId = displayId;
37+
}
38+
39+
/** Retrieve the displayId
40+
* @hide */
41+
public int getDisplayId() {
42+
return mDisplayId;
43+
}
44+
2745
/**
2846
* Gets the display adapter name.
2947
* @return The display adapter name.
3048
*/
3149
public abstract String getName();
3250

3351
// TODO: dynamically register display devices
34-
public abstract DisplayDevice[] getDisplayDevices();
52+
public abstract DisplayDevice getDisplayDevice();
3553
}

services/java/com/android/server/display/DisplayManagerService.java

Lines changed: 200 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import android.hardware.display.IDisplayManager;
2323
import android.os.Binder;
2424
import android.os.SystemProperties;
25+
import android.util.Slog;
26+
import android.util.SparseArray;
2527
import android.view.Display;
2628
import android.view.DisplayInfo;
2729
import 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
}

services/java/com/android/server/display/HeadlessDisplayAdapter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public String getName() {
4040
}
4141

4242
@Override
43-
public DisplayDevice[] getDisplayDevices() {
44-
return new DisplayDevice[] { mDefaultDisplay };
43+
public DisplayDevice getDisplayDevice() {
44+
return mDefaultDisplay;
4545
}
4646
}

services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public String getName() {
3535
}
3636

3737
@Override
38-
public DisplayDevice[] getDisplayDevices() {
39-
return new DisplayDevice[] { mDefaultDisplay };
38+
public DisplayDevice getDisplayDevice() {
39+
return mDefaultDisplay;
4040
}
4141
}

services/java/com/android/server/wm/DisplayContent.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import android.view.DisplayInfo;
2020

21+
import com.android.server.display.DisplayManagerService;
22+
2123
import java.io.PrintWriter;
2224
import java.util.ArrayList;
2325

@@ -56,10 +58,13 @@ class DisplayContent {
5658
int mInitialDisplayHeight = 0;
5759
int mBaseDisplayWidth = 0;
5860
int mBaseDisplayHeight = 0;
61+
final DisplayManagerService mDisplayManager;
5962
final DisplayInfo mDisplayInfo = new DisplayInfo();
6063

61-
DisplayContent(final int displayId) {
64+
DisplayContent(DisplayManagerService displayManager, final int displayId) {
65+
mDisplayManager = displayManager;
6266
mDisplayId = displayId;
67+
displayManager.getDisplayInfo(displayId, mDisplayInfo);
6368
}
6469

6570
int getDisplayId() {

0 commit comments

Comments
 (0)