Move rotation flags to SF

The rotation flags are typically only used for a camera preview, which
wants to avoid changing its orientation and flicker during rotation.
Prior to this CL, the rotation flags were tied to the primary display,
meaning that if the camera preview was on another display, the rotation
flags may not be up to date. For example, if the primary display is off,
its flags will not be updated on rotation.

Ideally, the flags should be based on the display where the preview will
be shown, but this is a much larger architectural change, tracked in
b/259407931.

As a temporary workaround, associate the flags with the active display.
Store the flags in SurfaceFlinger, which knows when the active display
changes. Update when the active display switches to a different display
or when the active display rotates, matching the behavior of
mActiveDisplayTransformHint, which seems similar but is different. Store
the flags as a static variable so that LayerFE can access it. LayerFE
does not have a way to access the actual SurfaceFlinger object, and it
should not.

Access to the new flags is safe because it is only read or written from
the main thread.

Bug: 269685949
Bug: 259407931
Test: ActiveDisplayRotationFlagsTest
Change-Id: I5532e140a603be222cb3ea1ae563638317c1d745
diff --git a/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
new file mode 100644
index 0000000..7077523
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/ActiveDisplayRotationFlagsTest.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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 ActiveDisplayRotationFlagsTest : DisplayTransactionTest {
+    static constexpr bool kWithMockScheduler = false;
+    ActiveDisplayRotationFlagsTest() : DisplayTransactionTest(kWithMockScheduler) {}
+
+    void SetUp() override {
+        injectMockScheduler(kInnerDisplayId);
+
+        // Inject inner and outer displays with uninitialized power modes.
+        constexpr bool kInitPowerMode = false;
+        {
+            InnerDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+            auto injector = InnerDisplayVariant::makeFakeExistingDisplayInjector(this);
+            injector.setPowerMode(std::nullopt);
+            injector.setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector());
+            mInnerDisplay = injector.inject();
+        }
+        {
+            OuterDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
+            auto injector = OuterDisplayVariant::makeFakeExistingDisplayInjector(this);
+            injector.setPowerMode(std::nullopt);
+            mOuterDisplay = injector.inject();
+        }
+
+        mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
+        mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
+
+        // The flags are a static variable, so by modifying them in the test, we
+        // are modifying the real ones used by SurfaceFlinger. Save the original
+        // flags so we can restore them on teardown. This isn't perfect - the
+        // phone may have been rotated during the test, so we're restoring the
+        // wrong flags. But if the phone is rotated, this may also fail the test.
+        mOldRotationFlags = mFlinger.mutableActiveDisplayRotationFlags();
+
+        // Reset to the expected default state.
+        mFlinger.mutableActiveDisplayRotationFlags() = ui::Transform::ROT_0;
+    }
+
+    void TearDown() override { mFlinger.mutableActiveDisplayRotationFlags() = mOldRotationFlags; }
+
+    static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get();
+    static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get();
+
+    sp<DisplayDevice> mInnerDisplay, mOuterDisplay;
+    ui::Transform::RotationFlags mOldRotationFlags;
+};
+
+TEST_F(ActiveDisplayRotationFlagsTest, defaultRotation) {
+    ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90) {
+    auto displayToken = mInnerDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_90;
+
+    mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+    ASSERT_EQ(ui::Transform::ROT_90, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotate90_inactive) {
+    auto displayToken = mOuterDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_90;
+
+    mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+    ASSERT_EQ(ui::Transform::ROT_0, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_innerActive) {
+    auto displayToken = mInnerDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_180;
+
+    displayToken = mOuterDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_270;
+
+    mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+    ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, rotateBoth_outerActive) {
+    mFlinger.mutableActiveDisplayId() = kOuterDisplayId;
+    auto displayToken = mInnerDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_180;
+
+    displayToken = mOuterDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_270;
+
+    mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+    ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+TEST_F(ActiveDisplayRotationFlagsTest, onActiveDisplayChanged) {
+    auto displayToken = mInnerDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_180;
+
+    displayToken = mOuterDisplay->getDisplayToken().promote();
+    mFlinger.mutableDrawingState().displays.editValueFor(displayToken).orientation = ui::ROTATION_0;
+    mFlinger.mutableCurrentState().displays.editValueFor(displayToken).orientation =
+            ui::ROTATION_270;
+
+    mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+    ASSERT_EQ(ui::Transform::ROT_180, SurfaceFlinger::getActiveDisplayRotationFlags());
+
+    mFlinger.onActiveDisplayChanged(mInnerDisplay.get(), *mOuterDisplay);
+    ASSERT_EQ(ui::Transform::ROT_270, SurfaceFlinger::getActiveDisplayRotationFlags());
+}
+
+} // namespace
+} // namespace android