Skip to content

Commit 7201829

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Make mirroring automatic based on Windows on display." into jb-mr1-dev
2 parents 7017e48 + 722285e commit 7201829

File tree

4 files changed

+150
-19
lines changed

4 files changed

+150
-19
lines changed

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

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
* </p><p>
5959
* Display adapters are only weakly coupled to the display manager service.
6060
* Display adapters communicate changes in display device state to the display manager
61-
* service asynchronously via a {@link DisplayAdapter.DisplayAdapterListener} registered
61+
* service asynchronously via a {@link DisplayAdapter.Listener} registered
6262
* by the display manager service. This separation of concerns is important for
6363
* two main reasons. First, it neatly encapsulates the responsibilities of these
6464
* two classes: display adapters handle individual display devices whereas
@@ -254,8 +254,8 @@ public void performTraversalInTransactionFromWindowManager() {
254254
* Returns information about the specified logical display.
255255
*
256256
* @param displayId The logical display id.
257-
* @param The logical display info, or null if the display does not exist.
258-
* This object must be treated as immutable.
257+
* @return The logical display info, or null if the display does not exist. The
258+
* returned object must be treated as immutable.
259259
*/
260260
@Override // Binder call
261261
public DisplayInfo getDisplayInfo(int displayId) {
@@ -481,14 +481,34 @@ private void performTraversalInTransactionLocked() {
481481
}
482482
}
483483

484-
private void configureDisplayInTransactionLocked(DisplayDevice device) {
485-
// TODO: add a proper per-display mirroring control
486-
boolean isMirroring = SystemProperties.getBoolean("debug.display.mirror", true);
484+
/**
485+
* Tells the display manager whether there is interesting unique content on the
486+
* specified logical display. This is used to control automatic mirroring.
487+
* <p>
488+
* If the display has unique content, then the display manager arranges for it
489+
* to be presented on a physical display if appropriate. Otherwise, the display manager
490+
* may choose to make the physical display mirror some other logical display.
491+
* </p>
492+
*
493+
* @param displayId The logical display id to update.
494+
* @param hasContent True if the logical display has content.
495+
*/
496+
public void setDisplayHasContent(int displayId, boolean hasContent) {
497+
synchronized (mSyncRoot) {
498+
LogicalDisplay display = mLogicalDisplays.get(displayId);
499+
if (display != null && display.hasContentLocked() != hasContent) {
500+
display.setHasContentLocked(hasContent);
501+
scheduleTraversalLocked();
502+
}
503+
}
487504

505+
}
506+
507+
private void configureDisplayInTransactionLocked(DisplayDevice device) {
488508
// Find the logical display that the display device is showing.
489-
LogicalDisplay display = null;
490-
if (!isMirroring) {
491-
display = findLogicalDisplayForDeviceLocked(device);
509+
LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
510+
if (display != null && !display.hasContentLocked()) {
511+
display = null;
492512
}
493513
if (display == null) {
494514
display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
@@ -611,8 +631,9 @@ public static final class SyncRoot {
611631
*/
612632
public interface WindowManagerFuncs {
613633
/**
614-
* Request that the window manager call {@link #performTraversalInTransaction}
615-
* within a surface transaction at a later time.
634+
* Request that the window manager call
635+
* {@link #performTraversalInTransactionFromWindowManager} within a surface
636+
* transaction at a later time.
616637
*/
617638
void requestTraversal();
618639
}

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ final class LogicalDisplay {
6363
private DisplayDevice mPrimaryDisplayDevice;
6464
private DisplayDeviceInfo mPrimaryDisplayDeviceInfo;
6565

66+
// True if the logical display has unique content.
67+
private boolean mHasContent;
68+
6669
// Temporary rectangle used when needed.
6770
private final Rect mTempLayerStackRect = new Rect();
6871
private final Rect mTempDisplayRect = new Rect();
@@ -126,7 +129,7 @@ public void setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
126129

127130
/**
128131
* Returns true if the logical display is in a valid state.
129-
* This method should be checked after calling {@link #update} to handle the
132+
* This method should be checked after calling {@link #updateLocked} to handle the
130133
* case where a logical display should be removed because all of its associated
131134
* display devices are gone or if it is otherwise no longer needed.
132135
*
@@ -256,6 +259,29 @@ public void configureDisplayInTransactionLocked(DisplayDevice device) {
256259
device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
257260
}
258261

262+
/**
263+
* Returns true if the logical display has unique content.
264+
* <p>
265+
* If the display has unique content then we will try to ensure that it is
266+
* visible on at least its primary display device. Otherwise we will ignore the
267+
* logical display and perhaps show mirrored content on the primary display device.
268+
* </p>
269+
*
270+
* @return True if the display has unique content.
271+
*/
272+
public boolean hasContentLocked() {
273+
return mHasContent;
274+
}
275+
276+
/**
277+
* Sets whether the logical display has unique content.
278+
*
279+
* @param hasContent True if the display has unique content.
280+
*/
281+
public void setHasContentLocked(boolean hasContent) {
282+
mHasContent = hasContent;
283+
}
284+
259285
public void dumpLocked(PrintWriter pw) {
260286
pw.println("mLayerStack=" + mLayerStack);
261287
pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,13 @@ Display getDisplay() {
9494
}
9595

9696
DisplayInfo getDisplayInfo() {
97-
// TODO: Add a listener for changes to Display and update mDisplayInfo when appropriate.
9897
return mDisplayInfo;
9998
}
10099

100+
public void updateDisplayInfo() {
101+
mDisplay.getDisplayInfo(mDisplayInfo);
102+
}
103+
101104
public void dump(PrintWriter pw) {
102105
pw.print(" Display: mDisplayId="); pw.println(mDisplayId);
103106
pw.print(" init="); pw.print(mInitialDisplayWidth); pw.print("x");
@@ -121,7 +124,7 @@ public void dump(PrintWriter pw) {
121124
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
122125
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
123126
pw.print(" layoutNeeded="); pw.println(layoutNeeded);
124-
pw.print("magnificationSpec="); pw.println(mMagnificationSpec.toString());
127+
pw.print("magnificationSpec="); pw.println(mMagnificationSpec);
125128
pw.println();
126129
}
127130
}

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

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
/** {@hide} */
166166
public class WindowManagerService extends IWindowManager.Stub
167167
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
168-
DisplayManagerService.WindowManagerFuncs {
168+
DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
169169
static final String TAG = "WindowManager";
170170
static final boolean DEBUG = false;
171171
static final boolean DEBUG_ADD_REMOVE = false;
@@ -782,9 +782,15 @@ private WindowManagerService(Context context, PowerManagerService pm,
782782
mLimitedAlphaCompositing = context.getResources().getBoolean(
783783
com.android.internal.R.bool.config_sf_limitedAlpha);
784784
mDisplayManagerService = displayManager;
785-
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
786785
mHeadless = displayManager.isHeadless();
787786

787+
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
788+
mDisplayManager.registerDisplayListener(this, null);
789+
Display[] displays = mDisplayManager.getDisplays();
790+
for (Display display : displays) {
791+
createDisplayContent(display);
792+
}
793+
788794
mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
789795

790796
mPowerManager = pm;
@@ -1120,6 +1126,10 @@ private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
11201126
if (win.mAppToken != null && addToToken) {
11211127
win.mAppToken.allAppWindows.add(win);
11221128
}
1129+
1130+
if (windows.size() == 1) {
1131+
mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), true);
1132+
}
11231133
}
11241134

11251135
/** TODO(cmautner): Is this the same as {@link WindowState#canReceiveKeys()} */
@@ -2408,6 +2418,9 @@ private void removeWindowInnerLocked(Session session, WindowState win) {
24082418

24092419
final WindowList windows = win.getWindowList();
24102420
windows.remove(win);
2421+
if (windows.isEmpty()) {
2422+
mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), false);
2423+
}
24112424
mPendingRemove.remove(win);
24122425
mWindowsChanged = true;
24132426
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -7194,6 +7207,10 @@ final class H extends Handler {
71947207
public static final int NOTIFY_WINDOW_TRANSITION = 29;
71957208
public static final int NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 30;
71967209

7210+
public static final int DO_DISPLAY_ADDED = 31;
7211+
public static final int DO_DISPLAY_REMOVED = 32;
7212+
public static final int DO_DISPLAY_CHANGED = 33;
7213+
71977214
public static final int ANIMATOR_WHAT_OFFSET = 100000;
71987215
public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
71997216
public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2;
@@ -7631,25 +7648,46 @@ public void handleMessage(Message msg) {
76317648
}
76327649
break;
76337650
}
7651+
76347652
case NOTIFY_ROTATION_CHANGED: {
76357653
final int displayId = msg.arg1;
76367654
final int rotation = msg.arg2;
76377655
handleNotifyRotationChanged(displayId, rotation);
76387656
break;
76397657
}
7658+
76407659
case NOTIFY_WINDOW_TRANSITION: {
76417660
final int transition = msg.arg1;
76427661
WindowInfo info = (WindowInfo) msg.obj;
76437662
handleNotifyWindowTranstion(transition, info);
76447663
break;
76457664
}
7665+
76467666
case NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
76477667
final int displayId = msg.arg1;
76487668
final boolean immediate = (msg.arg2 == 1);
76497669
Rect rectangle = (Rect) msg.obj;
76507670
handleNotifyRectangleOnScreenRequested(displayId, rectangle, immediate);
76517671
break;
76527672
}
7673+
7674+
case DO_DISPLAY_ADDED:
7675+
synchronized (mWindowMap) {
7676+
handleDisplayAddedLocked(msg.arg1);
7677+
}
7678+
break;
7679+
7680+
case DO_DISPLAY_REMOVED:
7681+
synchronized (mWindowMap) {
7682+
handleDisplayRemovedLocked(msg.arg1);
7683+
}
7684+
break;
7685+
7686+
case DO_DISPLAY_CHANGED:
7687+
synchronized (mWindowMap) {
7688+
handleDisplayChangedLocked(msg.arg1);
7689+
}
7690+
break;
76537691
}
76547692
if (DEBUG_WINDOW_TRACE) {
76557693
Slog.v(TAG, "handleMessage: exit");
@@ -8866,8 +8904,6 @@ private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMe
88668904
final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
88678905
final int defaultDw = defaultInfo.logicalWidth;
88688906
final int defaultDh = defaultInfo.logicalHeight;
8869-
final int defaultInnerDw = defaultInfo.appWidth;
8870-
final int defaultInnerDh = defaultInfo.appHeight;
88718907

88728908
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
88738909
">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
@@ -9441,6 +9477,7 @@ void setHoldScreenLocked(final Session newHoldScreen) {
94419477
}
94429478
}
94439479

9480+
@Override
94449481
public void requestTraversal() {
94459482
synchronized (mWindowMap) {
94469483
requestTraversalLocked();
@@ -10465,7 +10502,7 @@ void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
1046510502

1046610503
boolean dumpWindows(PrintWriter pw, String name, String[] args,
1046710504
int opti, boolean dumpAll) {
10468-
ArrayList<WindowState> windows = new ArrayList<WindowState>();
10505+
WindowList windows = new WindowList();
1046910506
if ("visible".equals(name)) {
1047010507
synchronized(mWindowMap) {
1047110508
final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
@@ -10673,6 +10710,14 @@ void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
1067310710
}
1067410711
}
1067510712

10713+
public void createDisplayContent(final Display display) {
10714+
if (display == null) {
10715+
throw new IllegalArgumentException("getDisplayContent: display must not be null");
10716+
}
10717+
final DisplayContent displayContent = new DisplayContent(display);
10718+
mDisplayContents.put(display.getDisplayId(), displayContent);
10719+
}
10720+
1067610721
public DisplayContent getDisplayContent(final int displayId) {
1067710722
DisplayContent displayContent = mDisplayContents.get(displayId);
1067810723
if (displayContent == null) {
@@ -10780,4 +10825,40 @@ public DisplayInfo getDefaultDisplayInfo() {
1078010825
public WindowList getWindowList(final Display display) {
1078110826
return getDisplayContent(display.getDisplayId()).getWindowList();
1078210827
}
10828+
10829+
@Override
10830+
public void onDisplayAdded(int displayId) {
10831+
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10832+
}
10833+
10834+
private void handleDisplayAddedLocked(int displayId) {
10835+
createDisplayContent(mDisplayManager.getDisplay(displayId));
10836+
}
10837+
10838+
@Override
10839+
public void onDisplayRemoved(int displayId) {
10840+
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10841+
}
10842+
10843+
private void handleDisplayRemovedLocked(int displayId) {
10844+
final DisplayContent displayContent = getDisplayContent(displayId);
10845+
mDisplayContents.delete(displayId);
10846+
WindowList windows = displayContent.getWindowList();
10847+
for (int i = windows.size() - 1; i >= 0; --i) {
10848+
final WindowState win = windows.get(i);
10849+
removeWindowLocked(win.mSession, win);
10850+
}
10851+
}
10852+
10853+
@Override
10854+
public void onDisplayChanged(int displayId) {
10855+
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10856+
}
10857+
10858+
private void handleDisplayChangedLocked(int displayId) {
10859+
final DisplayContent displayContent = getDisplayContent(displayId);
10860+
if (displayContent != null) {
10861+
displayContent.updateDisplayInfo();
10862+
}
10863+
}
1078310864
}

0 commit comments

Comments
 (0)