Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72018294 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

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

parents 7017e483 722285e1
Loading
Loading
Loading
Loading
+32 −11
Original line number Diff line number Diff line
@@ -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();
    }
+27 −1
Original line number Diff line number Diff line
@@ -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 ?
+5 −2
Original line number Diff line number Diff line
@@ -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();
    }
}
+86 −5
Original line number Diff line number Diff line
@@ -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();
        }
    }
}