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

Commit 80cd1380 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve testability for WindowLayoutComponentImpl." into main

parents 3b7526e1 78e5f484
Loading
Loading
Loading
Loading
+2 −13
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.annotation.SuppressLint;
import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.RotationUtils;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -31,7 +30,6 @@ import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
import androidx.annotation.VisibleForTesting;

/**
 * Util class for both Sidecar and Extensions.
@@ -46,24 +44,15 @@ public final class ExtensionHelper {
     * Rotates the input rectangle specified in default display orientation to the current display
     * rotation.
     *
     * @param displayId the display id.
     * @param displayInfo the display information.
     * @param rotation the target rotation relative to the default display orientation.
     * @param inOutRect the input/output Rect as specified in the default display orientation.
     */
    public static void rotateRectToDisplayRotation(
            int displayId, @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
        final DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
        final DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);

        rotateRectToDisplayRotation(displayInfo, rotation, inOutRect);
    }

    // We suppress the Lint error CheckResult for Rect#intersect because in case the displayInfo and
    // folding features are out of sync, e.g. when a foldable devices is unfolding, it is acceptable
    // to provide the original folding feature Rect even if they don't intersect.
    @SuppressLint("RectIntersectReturnValueIgnored")
    @VisibleForTesting
    static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
    public static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
            @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
        // The inOutRect is specified in the default display orientation, so here we need to get
        // the display width and height in the default orientation to perform the intersection and
+37 −3
Original line number Diff line number Diff line
@@ -34,11 +34,14 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Bundle;
import android.os.IBinder;
import android.os.StrictMode;
import android.util.ArrayMap;
import android.util.Log;
import android.view.DisplayInfo;
import android.view.Surface;

import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -96,8 +99,29 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {

    private final SupportedWindowFeatures mSupportedWindowFeatures;

    private final DisplayStateProvider mDisplayStateProvider;

    public WindowLayoutComponentImpl(@NonNull Context context,
            @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) {
        this(context, foldingFeatureProducer, new DisplayStateProvider() {
            @Override
            public int getDisplayRotation(@NonNull WindowConfiguration windowConfiguration) {
                return windowConfiguration.getDisplayRotation();
            }

            @NonNull
            @Override
            public DisplayInfo getDisplayInfo(int displayId) {
                return DisplayManagerGlobal.getInstance().getDisplayInfo(displayId);
            }
        });
    }

    @VisibleForTesting
    WindowLayoutComponentImpl(@NonNull Context context,
            @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer,
            @NonNull DisplayStateProvider displayStateProvider) {
        mDisplayStateProvider = displayStateProvider;
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
        mFoldingFeatureProducer = foldingFeatureProducer;
@@ -401,15 +425,16 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {

        // We will transform the feature bounds to the Activity window, so using the rotation
        // from the same source (WindowConfiguration) to make sure they are synchronized.
        final int rotation = windowConfiguration.getDisplayRotation();
        final int rotation = mDisplayStateProvider.getDisplayRotation(windowConfiguration);
        final DisplayInfo displayInfo = mDisplayStateProvider.getDisplayInfo(displayId);

        for (CommonFoldingFeature baseFeature : storedFeatures) {
            Integer state = convertToExtensionState(baseFeature.getState());
            if (state == null) {
                continue;
            }
            Rect featureRect = baseFeature.getRect();
            rotateRectToDisplayRotation(displayId, rotation, featureRect);
            final Rect featureRect = baseFeature.getRect();
            rotateRectToDisplayRotation(displayInfo, rotation, featureRect);
            transformToWindowSpaceRect(windowConfiguration, featureRect);

            if (isZero(featureRect)) {
@@ -530,4 +555,13 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
        public void onLowMemory() {
        }
    }

    @VisibleForTesting
    interface DisplayStateProvider {
        @Surface.Rotation
        int getDisplayRotation(@NonNull WindowConfiguration windowConfiguration);

        @NonNull
        DisplayInfo getDisplayInfo(int displayId);
    }
}
+9 −2
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@ import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityThread;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
import android.view.DisplayInfo;

import androidx.window.common.layout.CommonFoldingFeature;

@@ -96,13 +98,18 @@ class SidecarHelper {
            return Collections.emptyList();
        }

        final List<SidecarDisplayFeature> features = new ArrayList<>();
        // We will transform the feature bounds to the Activity window, so using the rotation
        // from the same source (WindowConfiguration) to make sure they are synchronized.
        final int rotation = activity.getResources().getConfiguration().windowConfiguration
                .getDisplayRotation();
        final DisplayInfo displayInfo =
                DisplayManagerGlobal.getInstance().getDisplayInfo(displayId);

        final List<SidecarDisplayFeature> features = new ArrayList<>();
        for (CommonFoldingFeature baseFeature : featureList) {
            final SidecarDisplayFeature feature = new SidecarDisplayFeature();
            final Rect featureRect = baseFeature.getRect();
            rotateRectToDisplayRotation(displayId, rotation, featureRect);
            rotateRectToDisplayRotation(displayInfo, rotation, featureRect);
            transformToWindowSpaceRect(activity, featureRect);
            feature.setRect(featureRect);
            feature.setType(baseFeature.getType());
+25 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.content.ContextWrapper;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;

import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
@@ -88,6 +90,29 @@ public class WindowLayoutComponentImplTest {
        final WindowConfiguration windowConfiguration =
                testUiContext.getResources().getConfiguration().windowConfiguration;
        final Rect featureRect = windowConfiguration.getBounds();
        // Mock DisplayStateProvider to control rotation and DisplayInfo, preventing dependency on
        // the real device orientation or display configuration. This improves test reliability on
        // devices like foldables or tablets that might have varying configurations.
        final WindowLayoutComponentImpl.DisplayStateProvider displayStateProvider =
                new WindowLayoutComponentImpl.DisplayStateProvider() {
                    @Override
                    public int getDisplayRotation(
                            @NonNull WindowConfiguration windowConfiguration) {
                        return Surface.ROTATION_0;
                    }

                    @NonNull
                    @Override
                    public DisplayInfo getDisplayInfo(int displayId) {
                        final DisplayInfo displayInfo = new DisplayInfo();
                        displayInfo.logicalWidth = featureRect.width();
                        displayInfo.logicalHeight = featureRect.height();
                        return displayInfo;
                    }
                };
        mWindowLayoutComponent = new WindowLayoutComponentImpl(mAppContext,
                mock(DeviceStateManagerFoldingFeatureProducer.class),
                displayStateProvider);
        final CommonFoldingFeature foldingFeature = new CommonFoldingFeature(
                CommonFoldingFeature.COMMON_TYPE_HINGE,
                CommonFoldingFeature.COMMON_STATE_FLAT,