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

Commit 3aab7961 authored by Nick Chameyev's avatar Nick Chameyev
Browse files

Prepare an interface for deferred display updates

Adds a DisplayUpdater interface that will allow
to defer DisplayInfo updates from DisplayManager.
This CL should not change any behavior,
it uses default implementation that immediately
applies the changes.

Bug: 259220649
Bug: 277866717
Test: atest PhysicalDisplaySwitchTransitionLauncherTest
Test: atest DisplayContentTests
Test: manual fold/unfold
Change-Id: I40343d9a54094ac602c6216754d2ece87f8d1b17
parent 951fd41d
Loading
Loading
Loading
Loading
+5 −18
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.display;

import static com.android.server.display.DisplayDeviceInfo.TOUCH_NONE;
import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELDS;
import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,6 +35,7 @@ import android.view.SurfaceControl;

import com.android.server.display.layout.Layout;
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.wm.utils.DisplayInfoOverrides;
import com.android.server.wm.utils.InsetUtils;

import java.io.PrintWriter;
@@ -252,24 +255,8 @@ final class LogicalDisplay {
    public DisplayInfo getDisplayInfoLocked() {
        if (mInfo.get() == null) {
            DisplayInfo info = new DisplayInfo();
            info.copyFrom(mBaseDisplayInfo);
            if (mOverrideDisplayInfo != null) {
                info.appWidth = mOverrideDisplayInfo.appWidth;
                info.appHeight = mOverrideDisplayInfo.appHeight;
                info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
                info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
                info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
                info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
                info.logicalWidth = mOverrideDisplayInfo.logicalWidth;
                info.logicalHeight = mOverrideDisplayInfo.logicalHeight;
                info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
                info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
                info.rotation = mOverrideDisplayInfo.rotation;
                info.displayCutout = mOverrideDisplayInfo.displayCutout;
                info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
                info.roundedCorners = mOverrideDisplayInfo.roundedCorners;
                info.displayShape = mOverrideDisplayInfo.displayShape;
            }
            copyDisplayInfoFields(info, mBaseDisplayInfo, mOverrideDisplayInfo,
                    WM_OVERRIDE_FIELDS);
            mInfo.set(info);
        }
        return mInfo.get();
+51 −16
Original line number Diff line number Diff line
@@ -158,6 +158,8 @@ import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELDS;
import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields;
import static com.android.server.wm.utils.RegionUtils.forEachRectReverse;
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
import static com.android.window.flags.Flags.explicitRefreshRateHints;
@@ -464,11 +466,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    boolean mDisplayScalingDisabled;
    final Display mDisplay;
    private final DisplayInfo mDisplayInfo = new DisplayInfo();

    /**
     * Contains the last DisplayInfo override that was sent to DisplayManager or null if we haven't
     * set an override yet
     */
    @Nullable
    private DisplayInfo mLastDisplayInfoOverride;

    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
    private final DisplayPolicy mDisplayPolicy;
    private final DisplayRotation mDisplayRotation;
    @Nullable final DisplayRotationCompatPolicy mDisplayRotationCompatPolicy;
    DisplayFrames mDisplayFrames;
    private final DisplayUpdater mDisplayUpdater;

    private boolean mInTouchMode;

@@ -622,7 +633,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    @VisibleForTesting
    final DeviceStateController mDeviceStateController;
    final Consumer<DeviceStateController.DeviceState> mDeviceStateConsumer;
    private final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
    final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
    final RemoteDisplayChangeController mRemoteDisplayChangeController;

    /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
@@ -1146,6 +1157,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mDisplay = display;
        mDisplayId = display.getDisplayId();
        mCurrentUniqueDisplayId = display.getUniqueId();
        mDisplayUpdater = new ImmediateDisplayUpdater(this);
        mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
        mWallpaperController = new WallpaperController(mWmService, this);
        mWallpaperController.resetLargestDisplay(display);
@@ -2303,8 +2315,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

        computeSizeRanges(mDisplayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig);

        mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
                mDisplayInfo);
        setDisplayInfoOverride();

        if (isDefaultDisplay) {
            mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
@@ -2316,6 +2327,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return mDisplayInfo;
    }

    /**
     * Sets the current DisplayInfo in DisplayContent as an override to DisplayManager
     */
    private void setDisplayInfoOverride() {
        mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
                mDisplayInfo);

        if (mLastDisplayInfoOverride == null) {
            mLastDisplayInfoOverride = new DisplayInfo();
        }

        mLastDisplayInfoOverride.copyFrom(mDisplayInfo);
    }

    DisplayCutout calculateDisplayCutoutForRotation(int rotation) {
        return mDisplayCutoutCache.getOrCompute(
                mIsSizeForced ? mBaseDisplayCutout : mInitialDisplayCutout, rotation)
@@ -2887,12 +2912,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return orientation;
    }

    void updateDisplayInfo() {
    void updateDisplayInfo(@NonNull DisplayInfo newDisplayInfo) {
        // Check if display metrics changed and update base values if needed.
        updateBaseDisplayMetricsIfNeeded();
        updateBaseDisplayMetricsIfNeeded(newDisplayInfo);

        mDisplay.getDisplayInfo(mDisplayInfo);
        mDisplay.getMetrics(mDisplayMetrics);
        // Update mDisplayInfo with (newDisplayInfo + mLastDisplayInfoOverride) as
        // updateBaseDisplayMetricsIfNeeded could have updated mLastDisplayInfoOverride
        copyDisplayInfoFields(/* out= */ mDisplayInfo, /* base= */ newDisplayInfo,
                /* override= */ mLastDisplayInfoOverride, /* fields= */ WM_OVERRIDE_FIELDS);
        mDisplayInfo.getAppMetrics(mDisplayMetrics, mDisplay.getDisplayAdjustments());

        onDisplayInfoChanged();
        onDisplayChanged(this);
@@ -2978,9 +3006,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     * If display metrics changed, overrides are not set and it's not just a rotation - update base
     * values.
     */
    private void updateBaseDisplayMetricsIfNeeded() {
    private void updateBaseDisplayMetricsIfNeeded(DisplayInfo newDisplayInfo) {
        // Get real display metrics without overrides from WM.
        mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
        mDisplayInfo.copyFrom(newDisplayInfo);
        final int currentRotation = getRotation();
        final int orientation = mDisplayInfo.rotation;
        final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
@@ -3012,7 +3040,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                // metrics are updated as rotation settings might depend on them
                mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this,
                        /* includeRotationSettings */ false);
                mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
                mDisplayUpdater.onDisplayContentDisplayPropertiesPreChanged(mDisplayId,
                        mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
                mDisplayRotation.physicalDisplayChanged();
                mDisplayPolicy.physicalDisplayChanged();
@@ -3048,8 +3076,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

            if (physicalDisplayChanged) {
                mDisplayPolicy.physicalDisplayUpdated();
                mDisplaySwitchTransitionLauncher.onDisplayUpdated(currentRotation, getRotation(),
                        getDisplayAreaInfo());
                mDisplayUpdater.onDisplayContentDisplayPropertiesPostChanged(currentRotation,
                        getRotation(), getDisplayAreaInfo());
            }
        }
    }
@@ -5496,8 +5524,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mDisplayReady = true;

            if (mWmService.mDisplayManagerInternal != null) {
                mWmService.mDisplayManagerInternal
                        .setDisplayInfoOverrideFromWindowManager(mDisplayId, getDisplayInfo());
                setDisplayInfoOverride();
                configureDisplayPolicy();
            }

@@ -6134,9 +6161,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return mMetricsLogger;
    }

    void onDisplayChanged() {
    /**
     * Triggers an update of DisplayInfo from DisplayManager
     * @param onDisplayChangeApplied callback that is called when the changes are applied
     */
    void requestDisplayUpdate(@NonNull Runnable onDisplayChangeApplied) {
        mDisplayUpdater.updateDisplayInfo(onDisplayChangeApplied);
    }

    void onDisplayInfoUpdated(@NonNull DisplayInfo newDisplayInfo) {
        final int lastDisplayState = mDisplayInfo.state;
        updateDisplayInfo();
        updateDisplayInfo(newDisplayInfo);

        // The window policy is responsible for stopping activities on the default display.
        final int displayId = mDisplay.getDisplayId();
+6 −5
Original line number Diff line number Diff line
@@ -1717,11 +1717,12 @@ public class DisplayPolicy {
    void onOverlayChanged() {
        updateCurrentUserResources();
        // Update the latest display size, cutout.
        mDisplayContent.updateDisplayInfo();
        mDisplayContent.requestDisplayUpdate(() -> {
            onConfigurationChanged();
            if (!CLIENT_TRANSIENT) {
                mSystemGestures.onConfigurationChanged();
            }
        });
    }

    /**
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 android.annotation.NonNull;
import android.view.Surface;
import android.window.DisplayAreaInfo;

/**
 * Interface for a helper class that manages updates of DisplayInfo coming from DisplayManager
 */
interface DisplayUpdater {
    /**
     * Reads the latest display parameters from the display manager and returns them in a callback.
     * If there are pending display updates, it will wait for them to finish first and only then it
     * will call the callback with the latest display parameters.
     *
     * @param callback is called when all pending display updates are finished
     */
    void updateDisplayInfo(@NonNull Runnable callback);

    /**
     * Called when physical display has changed and before DisplayContent has applied new display
     * properties
     */
    default void onDisplayContentDisplayPropertiesPreChanged(int displayId, int initialDisplayWidth,
            int initialDisplayHeight, int newWidth, int newHeight) {
    }

    /**
     * Called after physical display has changed and after DisplayContent applied new display
     * properties
     */
    default void onDisplayContentDisplayPropertiesPostChanged(
            @Surface.Rotation int previousRotation, @Surface.Rotation int newRotation,
            @NonNull DisplayAreaInfo newDisplayAreaInfo) {
    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 android.annotation.NonNull;
import android.view.DisplayInfo;
import android.window.DisplayAreaInfo;

/**
 * DisplayUpdater that immediately applies new DisplayInfo properties
 */
public class ImmediateDisplayUpdater implements DisplayUpdater {

    private final DisplayContent mDisplayContent;
    private final DisplayInfo mDisplayInfo = new DisplayInfo();

    public ImmediateDisplayUpdater(@NonNull DisplayContent displayContent) {
        mDisplayContent = displayContent;
    }

    @Override
    public void updateDisplayInfo(Runnable callback) {
        mDisplayContent.mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(
                mDisplayContent.mDisplayId, mDisplayInfo);
        mDisplayContent.onDisplayInfoUpdated(mDisplayInfo);
        callback.run();
    }

    @Override
    public void onDisplayContentDisplayPropertiesPreChanged(int displayId, int initialDisplayWidth,
            int initialDisplayHeight, int newWidth, int newHeight) {
        mDisplayContent.mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(
                displayId, initialDisplayWidth, initialDisplayHeight, newWidth, newHeight);
    }

    @Override
    public void onDisplayContentDisplayPropertiesPostChanged(int previousRotation, int newRotation,
            DisplayAreaInfo newDisplayAreaInfo) {
        mDisplayContent.mDisplaySwitchTransitionLauncher.onDisplayUpdated(previousRotation,
                newRotation,
                newDisplayAreaInfo);
    }
}
Loading