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

Commit 06e5db05 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Rewrite test for leader display designation

Bug: 259436835
Fixes: 262417075
Test: MultiDisplayLeaderTest.foldable
Change-Id: Icfe2bf1dedcfbdd09f98caf6db24c6b121afbf1c
parent 2b1037b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ cc_test {
        "SurfaceFlinger_DisplayTransactionCommitTest.cpp",
        "SurfaceFlinger_GetDisplayNativePrimariesTest.cpp",
        "SurfaceFlinger_HotplugTest.cpp",
        "SurfaceFlinger_MultiDisplayLeaderTest.cpp",
        "SurfaceFlinger_NotifyPowerBoostTest.cpp",
        "SurfaceFlinger_OnInitializeDisplaysTest.cpp",
        "SurfaceFlinger_PowerHintTest.cpp",
+16 −5
Original line number Diff line number Diff line
@@ -503,14 +503,16 @@ struct PrimaryDisplay {
    static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
};

template <bool hasIdentificationData>
struct ExternalDisplay {
    static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External;
template <ui::DisplayConnectionType connectionType, bool hasIdentificationData>
struct SecondaryDisplay {
    static constexpr auto CONNECTION_TYPE = connectionType;
    static constexpr Primary PRIMARY = Primary::FALSE;
    static constexpr uint8_t PORT = 254;
    static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
    static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
    static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
    static constexpr auto GET_IDENTIFICATION_DATA =
            connectionType == ui::DisplayConnectionType::Internal ? getInternalEdid
                                                                  : getExternalEdid;
};

struct TertiaryDisplay {
@@ -521,7 +523,16 @@ struct TertiaryDisplay {
};

using PrimaryDisplayVariant = PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160>;
using ExternalDisplayVariant = PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280>;

using InnerDisplayVariant = PhysicalDisplayVariant<PrimaryDisplay<true>, 1840, 2208>;
using OuterDisplayVariant =
        PhysicalDisplayVariant<SecondaryDisplay<ui::DisplayConnectionType::Internal, true>, 1080,
                               2092>;

using ExternalDisplayVariant =
        PhysicalDisplayVariant<SecondaryDisplay<ui::DisplayConnectionType::External, false>, 1920,
                               1280>;

using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200>;

// A virtual display not supported by the HWC.
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"

#include "DisplayTransactionTestHelpers.h"

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace android {
namespace {

struct MultiDisplayLeaderTest : DisplayTransactionTest {
    static constexpr bool kWithMockScheduler = false;
    MultiDisplayLeaderTest() : DisplayTransactionTest(kWithMockScheduler) {}
};

TEST_F(MultiDisplayLeaderTest, foldable) {
    injectMockScheduler(InnerDisplayVariant::DISPLAY_ID::get());

    // Inject inner and outer displays with uninitialized power modes.
    sp<DisplayDevice> innerDisplay, outerDisplay;
    constexpr bool kInitPowerMode = false;
    {
        InnerDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
        auto injector = InnerDisplayVariant::makeFakeExistingDisplayInjector(this);
        injector.setPowerMode(std::nullopt);
        injector.setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector());
        innerDisplay = injector.inject();
    }
    {
        OuterDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
        auto injector = OuterDisplayVariant::makeFakeExistingDisplayInjector(this);
        injector.setPowerMode(std::nullopt);
        outerDisplay = injector.inject();
    }

    // When the device boots, the inner display should be the leader.
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), innerDisplay->getPhysicalId());

    // ...and should still be after powering on.
    mFlinger.setPowerModeInternal(innerDisplay, PowerMode::ON);
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), innerDisplay->getPhysicalId());

    // The outer display should become the leader after folding.
    mFlinger.setPowerModeInternal(innerDisplay, PowerMode::OFF);
    mFlinger.setPowerModeInternal(outerDisplay, PowerMode::ON);
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), outerDisplay->getPhysicalId());

    // The inner display should become the leader after unfolding.
    mFlinger.setPowerModeInternal(outerDisplay, PowerMode::OFF);
    mFlinger.setPowerModeInternal(innerDisplay, PowerMode::ON);
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), innerDisplay->getPhysicalId());

    // The inner display should stay the leader if both are powered on.
    // TODO(b/256196556): The leader should depend on the displays' VSYNC phases.
    mFlinger.setPowerModeInternal(outerDisplay, PowerMode::ON);
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), innerDisplay->getPhysicalId());

    // The outer display should become the leader if designated.
    mFlinger.scheduler()->setLeaderDisplay(outerDisplay->getPhysicalId());
    ASSERT_EQ(mFlinger.scheduler()->leaderDisplayId(), outerDisplay->getPhysicalId());
}

} // namespace
} // namespace android
+0 −33
Original line number Diff line number Diff line
@@ -484,38 +484,5 @@ TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownExternalDispla
    transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToUnknownVariant>>();
}

// TODO(b/262417075)
TEST_F(SetPowerModeInternalTest, DISABLED_designatesLeaderDisplay) {
    using Case = SimplePrimaryDisplayCase;

    // --------------------------------------------------------------------
    // Preconditions

    // Inject a primary display with uninitialized power mode.
    constexpr bool kInitPowerMode = false;
    Case::Display::injectHwcDisplay<kInitPowerMode>(this);
    auto injector = Case::Display::makeFakeExistingDisplayInjector(this);
    injector.setPowerMode(std::nullopt);
    const auto display = injector.inject();

    // --------------------------------------------------------------------
    // Invocation

    // FakeDisplayDeviceInjector registers the display with Scheduler, so it has already been
    // designated as the leader. Set an arbitrary leader to verify that `setPowerModeInternal`
    // designates a leader regardless of any preceding `Scheduler::registerDisplay` call(s).
    constexpr PhysicalDisplayId kPlaceholderId = PhysicalDisplayId::fromPort(42);
    ASSERT_NE(display->getPhysicalId(), kPlaceholderId);
    mFlinger.scheduler()->setLeaderDisplay(kPlaceholderId);

    mFlinger.setPowerModeInternal(display, PowerMode::ON);

    // --------------------------------------------------------------------
    // Postconditions

    // The primary display should be designated as the leader.
    EXPECT_EQ(mFlinger.scheduler()->leaderDisplayId(), display->getPhysicalId());
}

} // namespace
} // namespace android