Merge "Make mirroring automatic based on Windows on display." into jb-mr1-dev

This commit is contained in:
Jeff Brown
2012-09-07 16:01:36 -07:00
committed by Android (Google) Code Review
4 changed files with 150 additions and 19 deletions

View File

@@ -58,7 +58,7 @@ import java.util.ArrayList;
* </p><p>
* Display adapters are only weakly coupled to the display manager service.
* Display adapters communicate changes in display device state to the display manager
* service asynchronously via a {@link DisplayAdapter.DisplayAdapterListener} registered
* service asynchronously via a {@link DisplayAdapter.Listener} registered
* by the display manager service. This separation of concerns is important for
* two main reasons. First, it neatly encapsulates the responsibilities of these
* two classes: display adapters handle individual display devices whereas
@@ -254,8 +254,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
* Returns information about the specified logical display.
*
* @param displayId The logical display id.
* @param The logical display info, or null if the display does not exist.
* This object must be treated as immutable.
* @return The logical display info, or null if the display does not exist. The
* returned object must be treated as immutable.
*/
@Override // Binder call
public DisplayInfo getDisplayInfo(int displayId) {
@@ -481,14 +481,34 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
}
private void configureDisplayInTransactionLocked(DisplayDevice device) {
// TODO: add a proper per-display mirroring control
boolean isMirroring = SystemProperties.getBoolean("debug.display.mirror", true);
/**
* Tells the display manager whether there is interesting unique content on the
* specified logical display. This is used to control automatic mirroring.
* <p>
* If the display has unique content, then the display manager arranges for it
* to be presented on a physical display if appropriate. Otherwise, the display manager
* may choose to make the physical display mirror some other logical display.
* </p>
*
* @param displayId The logical display id to update.
* @param hasContent True if the logical display has content.
*/
public void setDisplayHasContent(int displayId, boolean hasContent) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
if (display != null && display.hasContentLocked() != hasContent) {
display.setHasContentLocked(hasContent);
scheduleTraversalLocked();
}
}
}
private void configureDisplayInTransactionLocked(DisplayDevice device) {
// Find the logical display that the display device is showing.
LogicalDisplay display = null;
if (!isMirroring) {
display = findLogicalDisplayForDeviceLocked(device);
LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
if (display != null && !display.hasContentLocked()) {
display = null;
}
if (display == null) {
display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
@@ -611,8 +631,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
*/
public interface WindowManagerFuncs {
/**
* Request that the window manager call {@link #performTraversalInTransaction}
* within a surface transaction at a later time.
* Request that the window manager call
* {@link #performTraversalInTransactionFromWindowManager} within a surface
* transaction at a later time.
*/
void requestTraversal();
}

View File

@@ -63,6 +63,9 @@ final class LogicalDisplay {
private DisplayDevice mPrimaryDisplayDevice;
private DisplayDeviceInfo mPrimaryDisplayDeviceInfo;
// True if the logical display has unique content.
private boolean mHasContent;
// Temporary rectangle used when needed.
private final Rect mTempLayerStackRect = new Rect();
private final Rect mTempDisplayRect = new Rect();
@@ -126,7 +129,7 @@ final class LogicalDisplay {
/**
* Returns true if the logical display is in a valid state.
* This method should be checked after calling {@link #update} to handle the
* This method should be checked after calling {@link #updateLocked} to handle the
* case where a logical display should be removed because all of its associated
* display devices are gone or if it is otherwise no longer needed.
*
@@ -256,6 +259,29 @@ final class LogicalDisplay {
device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
}
/**
* Returns true if the logical display has unique content.
* <p>
* If the display has unique content then we will try to ensure that it is
* visible on at least its primary display device. Otherwise we will ignore the
* logical display and perhaps show mirrored content on the primary display device.
* </p>
*
* @return True if the display has unique content.
*/
public boolean hasContentLocked() {
return mHasContent;
}
/**
* Sets whether the logical display has unique content.
*
* @param hasContent True if the display has unique content.
*/
public void setHasContentLocked(boolean hasContent) {
mHasContent = hasContent;
}
public void dumpLocked(PrintWriter pw) {
pw.println("mLayerStack=" + mLayerStack);
pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?

View File

@@ -94,10 +94,13 @@ class DisplayContent {
}
DisplayInfo getDisplayInfo() {
// TODO: Add a listener for changes to Display and update mDisplayInfo when appropriate.
return mDisplayInfo;
}
public void updateDisplayInfo() {
mDisplay.getDisplayInfo(mDisplayInfo);
}
public void dump(PrintWriter pw) {
pw.print(" Display: mDisplayId="); pw.println(mDisplayId);
pw.print(" init="); pw.print(mInitialDisplayWidth); pw.print("x");
@@ -121,7 +124,7 @@ class DisplayContent {
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
pw.print(" layoutNeeded="); pw.println(layoutNeeded);
pw.print("magnificationSpec="); pw.println(mMagnificationSpec.toString());
pw.print("magnificationSpec="); pw.println(mMagnificationSpec);
pw.println();
}
}

View File

@@ -165,7 +165,7 @@ import java.util.NoSuchElementException;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
DisplayManagerService.WindowManagerFuncs {
DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean DEBUG_ADD_REMOVE = false;
@@ -782,9 +782,15 @@ public class WindowManagerService extends IWindowManager.Stub
mLimitedAlphaCompositing = context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_limitedAlpha);
mDisplayManagerService = displayManager;
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mHeadless = displayManager.isHeadless();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(this, null);
Display[] displays = mDisplayManager.getDisplays();
for (Display display : displays) {
createDisplayContent(display);
}
mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
mPowerManager = pm;
@@ -1120,6 +1126,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mAppToken != null && addToToken) {
win.mAppToken.allAppWindows.add(win);
}
if (windows.size() == 1) {
mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), true);
}
}
/** TODO(cmautner): Is this the same as {@link WindowState#canReceiveKeys()} */
@@ -2408,6 +2418,9 @@ public class WindowManagerService extends IWindowManager.Stub
final WindowList windows = win.getWindowList();
windows.remove(win);
if (windows.isEmpty()) {
mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), false);
}
mPendingRemove.remove(win);
mWindowsChanged = true;
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -7194,6 +7207,10 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NOTIFY_WINDOW_TRANSITION = 29;
public static final int NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 30;
public static final int DO_DISPLAY_ADDED = 31;
public static final int DO_DISPLAY_REMOVED = 32;
public static final int DO_DISPLAY_CHANGED = 33;
public static final int ANIMATOR_WHAT_OFFSET = 100000;
public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
public static final int CLEAR_PENDING_ACTIONS = ANIMATOR_WHAT_OFFSET + 2;
@@ -7631,18 +7648,21 @@ public class WindowManagerService extends IWindowManager.Stub
}
break;
}
case NOTIFY_ROTATION_CHANGED: {
final int displayId = msg.arg1;
final int rotation = msg.arg2;
handleNotifyRotationChanged(displayId, rotation);
break;
}
case NOTIFY_WINDOW_TRANSITION: {
final int transition = msg.arg1;
WindowInfo info = (WindowInfo) msg.obj;
handleNotifyWindowTranstion(transition, info);
break;
}
case NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
final int displayId = msg.arg1;
final boolean immediate = (msg.arg2 == 1);
@@ -7650,6 +7670,24 @@ public class WindowManagerService extends IWindowManager.Stub
handleNotifyRectangleOnScreenRequested(displayId, rectangle, immediate);
break;
}
case DO_DISPLAY_ADDED:
synchronized (mWindowMap) {
handleDisplayAddedLocked(msg.arg1);
}
break;
case DO_DISPLAY_REMOVED:
synchronized (mWindowMap) {
handleDisplayRemovedLocked(msg.arg1);
}
break;
case DO_DISPLAY_CHANGED:
synchronized (mWindowMap) {
handleDisplayChangedLocked(msg.arg1);
}
break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -8866,8 +8904,6 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
final int defaultDw = defaultInfo.logicalWidth;
final int defaultDh = defaultInfo.logicalHeight;
final int defaultInnerDw = defaultInfo.appWidth;
final int defaultInnerDh = defaultInfo.appHeight;
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
@@ -9441,6 +9477,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
@Override
public void requestTraversal() {
synchronized (mWindowMap) {
requestTraversalLocked();
@@ -10465,7 +10502,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean dumpWindows(PrintWriter pw, String name, String[] args,
int opti, boolean dumpAll) {
ArrayList<WindowState> windows = new ArrayList<WindowState>();
WindowList windows = new WindowList();
if ("visible".equals(name)) {
synchronized(mWindowMap) {
final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
@@ -10673,6 +10710,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
public void createDisplayContent(final Display display) {
if (display == null) {
throw new IllegalArgumentException("getDisplayContent: display must not be null");
}
final DisplayContent displayContent = new DisplayContent(display);
mDisplayContents.put(display.getDisplayId(), displayContent);
}
public DisplayContent getDisplayContent(final int displayId) {
DisplayContent displayContent = mDisplayContents.get(displayId);
if (displayContent == null) {
@@ -10780,4 +10825,40 @@ public class WindowManagerService extends IWindowManager.Stub
public WindowList getWindowList(final Display display) {
return getDisplayContent(display.getDisplayId()).getWindowList();
}
@Override
public void onDisplayAdded(int displayId) {
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
}
private void handleDisplayAddedLocked(int displayId) {
createDisplayContent(mDisplayManager.getDisplay(displayId));
}
@Override
public void onDisplayRemoved(int displayId) {
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
}
private void handleDisplayRemovedLocked(int displayId) {
final DisplayContent displayContent = getDisplayContent(displayId);
mDisplayContents.delete(displayId);
WindowList windows = displayContent.getWindowList();
for (int i = windows.size() - 1; i >= 0; --i) {
final WindowState win = windows.get(i);
removeWindowLocked(win.mSession, win);
}
}
@Override
public void onDisplayChanged(int displayId) {
mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
}
private void handleDisplayChangedLocked(int displayId) {
final DisplayContent displayContent = getDisplayContent(displayId);
if (displayContent != null) {
displayContent.updateDisplayInfo();
}
}
}