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

Commit 5ce4bb33 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Support rotation on secondary displays (3/N)

Move major operations of rotation/orientation from
PhoneWindowManager to DisplayRotation.

Create DisplayPolicy and move partial fields which
have dependency with rotation.

Bug: 111361251
Test: go/wm-smoke
Test: atest FrameworksServicesTests:AppWindowTokenTests
Test: atest FrameworksServicesTests:PhoneWindowManagerLayoutTest
Test: atest CtsActivityManagerDeviceTestCases:ActivityManagerMultiDisplayTests
Change-Id: I2dfd15ffcc41e10a9074087e6aa15975c92b4979
parent ad256a1e
Loading
Loading
Loading
Loading
+105 −726

File changed.

Preview size limit exceeded, changes collapsed.

+5 −34
Original line number Diff line number Diff line
@@ -690,6 +690,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     * the user. */
    public final int USER_ROTATION_LOCKED = 1;

    /**
     * Set the default display content to provide basic functions for the policy.
     */
    public void setDefaultDisplay(DisplayContentInfo displayContentInfo);

    /**
     * Perform initialization of the policy.
     *
@@ -698,18 +703,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs);

    /**
     * @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true.
     */
    public boolean isDefaultOrientationForced();

    /**
     * Called by window manager once it has the initial, default native
     * display dimensions.
     */
    public void setInitialDisplaySize(DisplayRotation displayRotation, int width, int height,
            int density);

    /**
     * Check permissions when adding a window.
     *
@@ -1432,28 +1425,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {

    public boolean isShowingDreamLw();

    /**
     * Given an orientation constant, returns the appropriate surface rotation,
     * taking into account sensors, docking mode, rotation lock, and other factors.
     *
     * @param orientation An orientation constant, such as
     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
     * @param lastRotation The most recently used rotation.
     * @param defaultDisplay Flag indicating whether the rotation is computed for the default
     *                       display. Currently for all non-default displays sensors, docking mode,
     *                       rotation lock and other factors are ignored.
     * @return The surface rotation to use.
     */
    public int rotationForOrientationLw(DisplayRotation displayRotation,
            @ActivityInfo.ScreenOrientation int orientation, int lastRotation);

    public void updateOrientationListener();

    /**
     * Get rotation source for the given display id.
     */
    public RotationSource getRotationSource(int displayId);

    /**
     * Called when the system is mostly done booting to set whether
     * the system should go into safe mode.
+4 −0
Original line number Diff line number Diff line
@@ -204,6 +204,10 @@ public abstract class WindowOrientationListener {
        }
    }

    public Handler getHandler() {
        return mHandler;
    }

    /**
     * Sets the current rotation.
     *
+57 −11
Original line number Diff line number Diff line
@@ -235,7 +235,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    private final DisplayInfo mDisplayInfo = new DisplayInfo();
    private final Display mDisplay;
    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
    final DisplayRotation mDisplayRotation;
    private final DisplayPolicy mDisplayPolicy;
    private DisplayRotation mDisplayRotation;
    DisplayFrames mDisplayFrames;

    /**
@@ -306,8 +307,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    private boolean mLayoutNeeded;
    int pendingLayoutChanges;
    int mDeferredRotationPauseCount;

    // TODO(multi-display): remove some of the usages.
    @VisibleForTesting
    boolean isDefaultDisplay;

    /**
     * Flag indicating whether WindowManager should override info for this display in
     * DisplayManager.
@@ -764,7 +768,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
                calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
        initializeDisplayBaseInfo();
        mDisplayRotation = new DisplayRotation(this, mService.mPolicy, mService.mContext);
        mDisplayPolicy = new DisplayPolicy(service);
        mDisplayRotation = new DisplayRotation(service, this);
        if (isDefaultDisplay) {
            // The policy may be invoked right after here, so it requires the necessary default
            // fields of this display content.
            mService.mPolicy.setDefaultDisplay(this);
        }
        mDividerControllerLocked = new DockedStackDividerController(service, this);
        mPinnedStackControllerLocked = new PinnedStackController(service, this);

@@ -921,11 +931,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        return mDisplayMetrics;
    }

    DisplayPolicy getDisplayPolicy() {
        return mDisplayPolicy;
    }

    @Override
    public DisplayRotation getDisplayRotation() {
        return mDisplayRotation;
    }

    @VisibleForTesting
    void setDisplayRotation(DisplayRotation displayRotation) {
        mDisplayRotation = displayRotation;
    }

    int getRotation() {
        return mRotation;
    }
@@ -979,10 +998,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

        mDeferredRotationPauseCount--;
        if (mDeferredRotationPauseCount == 0) {
            final boolean changed = updateRotationUnchecked();
            if (changed) {
                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
            }
            updateRotationAndSendNewConfigIfNeeded();
        }
    }

@@ -998,8 +1014,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        final int oldRotation = getRotation();
        final boolean oldAltOrientation = getAltOrientation();

        final int rotation = mService.mPolicy.rotationForOrientationLw(
                mDisplayRotation, lastOrientation, oldRotation);
        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
                lastOrientation, rotation);
        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
@@ -1008,6 +1023,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        return true;
    }

    /**
     * Update rotation of the display and send configuration if the rotation is changed.
     *
     * @return {@code true} if the rotation has been changed and the new config is sent.
     */
    boolean updateRotationAndSendNewConfigIfNeeded() {
        final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
        if (changed) {
            mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
        }
        return changed;
    }

    /**
     * Update rotation of the display.
     *
@@ -1066,8 +1094,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        final int oldRotation = mRotation;
        final int lastOrientation = mLastOrientation;
        final boolean oldAltOrientation = mAltOrientation;
        final int rotation = mService.mPolicy.rotationForOrientationLw(mDisplayRotation,
                lastOrientation, oldRotation);
        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
        if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
                + mDisplayId + " based on lastOrientation=" + lastOrientation
                + " and oldRotation=" + oldRotation);
@@ -1220,7 +1247,24 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

    void configureDisplayPolicy() {
        mDisplayRotation.configure();
        final int width = mBaseDisplayWidth;
        final int height = mBaseDisplayHeight;
        final int shortSize;
        final int longSize;
        if (width > height) {
            shortSize = height;
            longSize = width;
        } else {
            shortSize = width;
            longSize = height;
        }

        final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
        final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;

        mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
        mDisplayPolicy.configure(width, height, shortSizeDp);

        mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
    }
@@ -2394,6 +2438,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        pw.println();
        mDisplayFrames.dump(prefix, pw);
        pw.println();
        mDisplayPolicy.dump(prefix, pw);
        pw.println();
        mDisplayRotation.dump(prefix, pw);
        pw.println();
        mInputMonitor.dump(pw, "  ");
+260 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.content.Intent;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;

import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;

import java.io.PrintWriter;

/**
 * The policy that provides the basic behaviors and states of a display to show UI.
 */
public class DisplayPolicy {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;

    private final WindowManagerService mService;
    private final Object mLock;

    private final boolean mCarDockEnablesAccelerometer;
    private final boolean mDeskDockEnablesAccelerometer;

    private volatile int mLidState = LID_ABSENT;
    private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    private volatile boolean mHdmiPlugged;

    private volatile boolean mHasNavigationBar;
    // Can the navigation bar ever move to the side?
    private volatile boolean mNavigationBarCanMove;

    // Written by vr manager thread, only read in this class.
    private volatile boolean mPersistentVrModeEnabled;

    private volatile boolean mAwake;
    private volatile boolean mScreenOnEarly;
    private volatile boolean mScreenOnFully;
    private volatile ScreenOnListener mScreenOnListener;

    private volatile boolean mKeyguardDrawComplete;
    private volatile boolean mWindowManagerDrawComplete;

    DisplayPolicy(WindowManagerService service) {
        mService = service;
        mLock = service.getWindowManagerLock();
        mCarDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
        mDeskDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
    }

    void configure(int width, int height, int shortSizeDp) {
        // Allow the navigation bar to move on non-square small devices (phones).
        mNavigationBarCanMove = width != height && shortSizeDp < 600;

        mHasNavigationBar = mService.mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_showNavigationBar);

        // Allow a system property to override this. Used by the emulator.
        // See also hasNavigationBar().
        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
        if ("1".equals(navBarOverride)) {
            mHasNavigationBar = false;
        } else if ("0".equals(navBarOverride)) {
            mHasNavigationBar = true;
        }
    }

    public void setHdmiPlugged(boolean plugged) {
        setHdmiPlugged(plugged, false /* force */);
    }

    public void setHdmiPlugged(boolean plugged, boolean force) {
        if (force || mHdmiPlugged != plugged) {
            mHdmiPlugged = plugged;
            mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
            final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
            mService.mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        }
    }

    boolean isHdmiPlugged() {
        return mHdmiPlugged;
    }

    boolean isCarDockEnablesAccelerometer() {
        return mCarDockEnablesAccelerometer;
    }

    boolean isDeskDockEnablesAccelerometer() {
        return mDeskDockEnablesAccelerometer;
    }

    public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
        mPersistentVrModeEnabled = persistentVrModeEnabled;
    }

    public boolean isPersistentVrModeEnabled() {
        return mPersistentVrModeEnabled;
    }

    public void setDockMode(int dockMode) {
        mDockMode = dockMode;
    }

    public int getDockMode() {
        return mDockMode;
    }

    public boolean hasNavigationBar() {
        return mHasNavigationBar;
    }

    public boolean navigationBarCanMove() {
        return mNavigationBarCanMove;
    }

    public void setLidState(int lidState) {
        mLidState = lidState;
    }

    public int getLidState() {
        return mLidState;
    }

    public void setAwake(boolean awake) {
        mAwake = awake;
    }

    public boolean isAwake() {
        return mAwake;
    }

    public boolean isScreenOnEarly() {
        return mScreenOnEarly;
    }

    public boolean isScreenOnFully() {
        return mScreenOnFully;
    }

    public boolean isKeyguardDrawComplete() {
        return mKeyguardDrawComplete;
    }

    public boolean isWindowManagerDrawComplete() {
        return mWindowManagerDrawComplete;
    }

    public ScreenOnListener getScreenOnListener() {
        return mScreenOnListener;
    }

    public void screenTurnedOn(ScreenOnListener screenOnListener) {
        synchronized (mLock) {
            mScreenOnEarly = true;
            mScreenOnFully = false;
            mKeyguardDrawComplete = false;
            mWindowManagerDrawComplete = false;
            mScreenOnListener = screenOnListener;
        }
    }

    public void screenTurnedOff() {
        synchronized (mLock) {
            mScreenOnEarly = false;
            mScreenOnFully = false;
            mKeyguardDrawComplete = false;
            mWindowManagerDrawComplete = false;
            mScreenOnListener = null;
        }
    }

    /** Return false if we are not awake yet or we have already informed of this event. */
    public boolean finishKeyguardDrawn() {
        synchronized (mLock) {
            if (!mScreenOnEarly || mKeyguardDrawComplete) {
                return false;
            }

            mKeyguardDrawComplete = true;
            mWindowManagerDrawComplete = false;
        }
        return true;
    }

    /** Return false if screen is not turned on or we did already handle this case earlier. */
    public boolean finishWindowsDrawn() {
        synchronized (mLock) {
            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
                return false;
            }

            mWindowManagerDrawComplete = true;
        }
        return true;
    }

    /** Return false if it is not ready to turn on. */
    public boolean finishScreenTurningOn() {
        synchronized (mLock) {
            if (DEBUG_SCREEN_ON) Slog.d(TAG,
                    "finishScreenTurningOn: mAwake=" + mAwake
                            + ", mScreenOnEarly=" + mScreenOnEarly
                            + ", mScreenOnFully=" + mScreenOnFully
                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);

            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
                    || (mAwake && !mKeyguardDrawComplete)) {
                return false;
            }

            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Finished screen turning on...");
            mScreenOnListener = null;
            mScreenOnFully = true;
        }
        return true;
    }

    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "DisplayPolicy");
        pw.print(prefix + "  mCarDockEnablesAccelerometer=" + mCarDockEnablesAccelerometer);
        pw.println(" mDeskDockEnablesAccelerometer=" + mDeskDockEnablesAccelerometer);
        pw.print(prefix + "  mDockMode=" + Intent.dockStateToString(mDockMode));
        pw.println(" mLidState=" + WindowManagerFuncs.lidStateToString(mLidState));
        pw.print(prefix + "  mAwake=" + mAwake);
        pw.print(" mScreenOnEarly=" + mScreenOnEarly);
        pw.println(" mScreenOnFully=" + mScreenOnFully);
        pw.print(prefix + "  mKeyguardDrawComplete=" + mKeyguardDrawComplete);
        pw.println(" mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
        pw.println(prefix + "  mHdmiPlugged=" + mHdmiPlugged);
    }
}
Loading