SF: Introduce DisplaySnapshot
DisplaySnapshot stores the immutable state of a physical display,
captured on hotplug. The SurfaceFlinger class stores a map from
PhysicalDisplayId to PhysicalDisplay, a new class that augments
this state with the sp<DisplayToken>.
Later, DisplayDevice will be removed, and SF::mDisplays will map
wp<DisplayToken> to compositionengine::Display.
Bug: 241285876
Test: libsurfaceflinger_unittest
Test: dumpsys SurfaceFlinger --displays
Change-Id: I172df87c4a7a9cf64659ff9cfbd6df195ee4bc8d
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
index 9120972..d0c03fe 100644
--- a/libs/ui/include/ui/DisplayId.h
+++ b/libs/ui/include/ui/DisplayId.h
@@ -17,9 +17,10 @@
#pragma once
#include <cstdint>
-#include <optional>
#include <string>
+#include <ftl/optional.h>
+
namespace android {
// ID of a physical or a virtual display. This class acts as a type safe wrapper around uint64_t.
@@ -68,7 +69,7 @@
// DisplayId of a physical display, such as the internal display or externally connected display.
struct PhysicalDisplayId : DisplayId {
- static constexpr std::optional<PhysicalDisplayId> tryCast(DisplayId id) {
+ static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) {
if (id.value & FLAG_VIRTUAL) {
return std::nullopt;
}
diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h
index 566e417..83da821 100644
--- a/libs/ui/include/ui/StaticDisplayInfo.h
+++ b/libs/ui/include/ui/StaticDisplayInfo.h
@@ -23,7 +23,7 @@
namespace android::ui {
-enum class DisplayConnectionType { Internal, External };
+enum class DisplayConnectionType { Internal, External, ftl_last = External };
// Immutable information about physical display.
struct StaticDisplayInfo {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5e9fe65..3348cec 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -141,19 +141,20 @@
name: "libsurfaceflinger_sources",
srcs: [
"BackgroundExecutor.cpp",
- "ClientCache.cpp",
"Client.cpp",
- "EffectLayer.cpp",
+ "ClientCache.cpp",
+ "Display/DisplaySnapshot.cpp",
"DisplayDevice.cpp",
"DisplayHardware/AidlComposerHal.cpp",
- "DisplayHardware/HidlComposerHal.cpp",
"DisplayHardware/ComposerHal.cpp",
"DisplayHardware/FramebufferSurface.cpp",
"DisplayHardware/HWC2.cpp",
"DisplayHardware/HWComposer.cpp",
+ "DisplayHardware/HidlComposerHal.cpp",
"DisplayHardware/PowerAdvisor.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
"DisplayRenderArea.cpp",
+ "EffectLayer.cpp",
"Effects/Daltonizer.cpp",
"EventLog/EventLog.cpp",
"FlagManager.cpp",
diff --git a/services/surfaceflinger/Display/DisplayMap.h b/services/surfaceflinger/Display/DisplayMap.h
new file mode 100644
index 0000000..baf0da9
--- /dev/null
+++ b/services/surfaceflinger/Display/DisplayMap.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <ftl/small_map.h>
+
+namespace android::display {
+
+// The static capacities were chosen to exceed a typical number of physical and/or virtual displays.
+
+template <typename Key, typename Value>
+using DisplayMap = ftl::SmallMap<Key, Value, 5>;
+
+template <typename Key, typename Value>
+using PhysicalDisplayMap = ftl::SmallMap<Key, Value, 3>;
+
+} // namespace android::display
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.cpp b/services/surfaceflinger/Display/DisplaySnapshot.cpp
new file mode 100644
index 0000000..b4f104a
--- /dev/null
+++ b/services/surfaceflinger/Display/DisplaySnapshot.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#include <functional>
+#include <utility>
+
+#include <ftl/algorithm.h>
+#include <ftl/enum.h>
+
+#include "DisplaySnapshot.h"
+
+namespace android::display {
+
+DisplaySnapshot::DisplaySnapshot(PhysicalDisplayId displayId,
+ ui::DisplayConnectionType connectionType,
+ DisplayModes&& displayModes,
+ std::optional<DeviceProductInfo>&& deviceProductInfo)
+ : mDisplayId(displayId),
+ mConnectionType(connectionType),
+ mDisplayModes(std::move(displayModes)),
+ mDeviceProductInfo(std::move(deviceProductInfo)) {}
+
+std::optional<DisplayModeId> DisplaySnapshot::translateModeId(hal::HWConfigId hwcId) const {
+ return ftl::find_if(mDisplayModes,
+ [hwcId](const DisplayModes::value_type& pair) {
+ return pair.second->getHwcId() == hwcId;
+ })
+ .transform(&ftl::to_key<DisplayModes>);
+}
+
+void DisplaySnapshot::dump(std::string& out) const {
+ using namespace std::string_literals;
+
+ out += " connectionType="s;
+ out += ftl::enum_string(mConnectionType);
+
+ out += "\n deviceProductInfo="s;
+ if (mDeviceProductInfo) {
+ mDeviceProductInfo->dump(out);
+ } else {
+ out += "{}"s;
+ }
+}
+
+} // namespace android::display
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.h b/services/surfaceflinger/Display/DisplaySnapshot.h
new file mode 100644
index 0000000..0279220
--- /dev/null
+++ b/services/surfaceflinger/Display/DisplaySnapshot.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <optional>
+#include <string>
+
+#include <ui/DisplayId.h>
+#include <ui/StaticDisplayInfo.h>
+
+#include "../DisplayHardware/DisplayMode.h"
+
+namespace android::display {
+
+// Immutable state of a physical display, captured on hotplug.
+class DisplaySnapshot {
+public:
+ DisplaySnapshot(PhysicalDisplayId, ui::DisplayConnectionType, DisplayModes&&,
+ std::optional<DeviceProductInfo>&&);
+
+ DisplaySnapshot(const DisplaySnapshot&) = delete;
+ DisplaySnapshot(DisplaySnapshot&&) = default;
+
+ PhysicalDisplayId displayId() const { return mDisplayId; }
+ ui::DisplayConnectionType connectionType() const { return mConnectionType; }
+
+ std::optional<DisplayModeId> translateModeId(hal::HWConfigId) const;
+
+ const auto& displayModes() const { return mDisplayModes; }
+ const auto& deviceProductInfo() const { return mDeviceProductInfo; }
+
+ void dump(std::string&) const;
+
+private:
+ const PhysicalDisplayId mDisplayId;
+ const ui::DisplayConnectionType mConnectionType;
+
+ // Effectively const except in move constructor.
+ DisplayModes mDisplayModes;
+ std::optional<DeviceProductInfo> mDeviceProductInfo;
+};
+
+} // namespace android::display
diff --git a/services/surfaceflinger/Display/PhysicalDisplay.h b/services/surfaceflinger/Display/PhysicalDisplay.h
new file mode 100644
index 0000000..cba1014
--- /dev/null
+++ b/services/surfaceflinger/Display/PhysicalDisplay.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <utility>
+
+#include <binder/IBinder.h>
+#include <ui/DisplayId.h>
+#include <utils/StrongPointer.h>
+
+#include "DisplayMap.h"
+#include "DisplaySnapshot.h"
+
+namespace android::display {
+
+// TODO(b/229877597): Replace with AIDL type.
+using DisplayToken = IBinder;
+
+class PhysicalDisplay {
+public:
+ template <typename... Args>
+ PhysicalDisplay(sp<DisplayToken> token, Args&&... args)
+ : mToken(std::move(token)), mSnapshot(std::forward<Args>(args)...) {}
+
+ PhysicalDisplay(const PhysicalDisplay&) = delete;
+ PhysicalDisplay(PhysicalDisplay&&) = default;
+
+ const sp<DisplayToken>& token() const { return mToken; }
+ const DisplaySnapshot& snapshot() const { return mSnapshot; }
+
+ // Transformers for PhysicalDisplays::get.
+
+ using SnapshotRef = std::reference_wrapper<const DisplaySnapshot>;
+ SnapshotRef snapshotRef() const { return std::cref(mSnapshot); }
+
+ bool isInternal() const {
+ return mSnapshot.connectionType() == ui::DisplayConnectionType::Internal;
+ }
+
+ // Predicate for ftl::find_if on PhysicalDisplays.
+ static constexpr auto hasToken(const sp<DisplayToken>& token) {
+ return [&token](const std::pair<const PhysicalDisplayId, PhysicalDisplay>& pair) {
+ return pair.second.token() == token;
+ };
+ }
+
+private:
+ const sp<DisplayToken> mToken;
+
+ // Effectively const except in move constructor.
+ DisplaySnapshot mSnapshot;
+};
+
+using PhysicalDisplays = PhysicalDisplayMap<PhysicalDisplayId, PhysicalDisplay>;
+
+// Combinator for ftl::Optional<PhysicalDisplayId>::and_then.
+constexpr auto getPhysicalDisplay(const PhysicalDisplays& displays) {
+ return [&](PhysicalDisplayId id) { return displays.get(id); };
+}
+
+} // namespace android::display
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2866a34..ebaf35a 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -39,6 +39,7 @@
#include <system/window.h>
#include <ui/GraphicTypes.h>
+#include "Display/DisplaySnapshot.h"
#include "DisplayDevice.h"
#include "Layer.h"
#include "RefreshRateOverlay.h"
@@ -63,12 +64,10 @@
mHwComposer(args.hwComposer),
mDisplayToken(args.displayToken),
mSequenceId(args.sequenceId),
- mConnectionType(args.connectionType),
mCompositionDisplay{args.compositionDisplay},
mActiveModeFPSTrace("ActiveModeFPS -" + to_string(getId())),
mActiveModeFPSHwcTrace("ActiveModeFPS_HWC -" + to_string(getId())),
mPhysicalOrientation(args.physicalOrientation),
- mSupportedModes(std::move(args.supportedModes)),
mIsPrimary(args.isPrimary),
mRefreshRateConfigs(std::move(args.refreshRateConfigs)) {
mCompositionDisplay->editState().isSecure = args.isSecure;
@@ -132,10 +131,6 @@
}
}
-void DisplayDevice::setDeviceProductInfo(std::optional<DeviceProductInfo> info) {
- mDeviceProductInfo = std::move(info);
-}
-
auto DisplayDevice::getInputInfo() const -> InputInfo {
gui::DisplayInfo info;
info.displayId = getLayerStack().id;
@@ -187,16 +182,20 @@
return mPowerMode && *mPowerMode != hal::PowerMode::OFF;
}
-void DisplayDevice::setActiveMode(DisplayModeId id) {
- const auto mode = getMode(id);
- LOG_FATAL_IF(!mode, "Cannot set active mode which is not supported.");
- ATRACE_INT(mActiveModeFPSTrace.c_str(), mode->getFps().getIntValue());
- mActiveMode = mode;
+void DisplayDevice::setActiveMode(DisplayModeId modeId, const display::DisplaySnapshot& snapshot) {
+ const auto modeOpt = snapshot.displayModes().get(modeId);
+ LOG_ALWAYS_FATAL_IF(!modeOpt, "Unknown mode");
+
+ mActiveMode = modeOpt->get();
+ const Fps fps = mActiveMode->getFps();
+
+ ATRACE_INT(mActiveModeFPSTrace.c_str(), fps.getIntValue());
+
if (mRefreshRateConfigs) {
- mRefreshRateConfigs->setActiveModeId(mActiveMode->getId());
+ mRefreshRateConfigs->setActiveModeId(modeId);
}
if (mRefreshRateOverlay) {
- mRefreshRateOverlay->changeRefreshRate(mActiveMode->getFps());
+ mRefreshRateOverlay->changeRefreshRate(fps);
}
}
@@ -220,25 +219,6 @@
return mActiveMode;
}
-const DisplayModes& DisplayDevice::getSupportedModes() const {
- return mSupportedModes;
-}
-
-DisplayModePtr DisplayDevice::getMode(DisplayModeId modeId) const {
- const DisplayModePtr nullMode;
- return mSupportedModes.get(modeId).value_or(std::cref(nullMode));
-}
-
-std::optional<DisplayModeId> DisplayDevice::translateModeId(hal::HWConfigId hwcId) const {
- const auto it =
- std::find_if(mSupportedModes.begin(), mSupportedModes.end(),
- [hwcId](const auto& pair) { return pair.second->getHwcId() == hwcId; });
- if (it != mSupportedModes.end()) {
- return it->second->getId();
- }
- return {};
-}
-
nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
const auto physicalId = getPhysicalId();
if (!mHwComposer.isConnected(physicalId)) {
@@ -268,10 +248,10 @@
return mCompositionDisplay->getState().dataspace;
}
-void DisplayDevice::setLayerStack(ui::LayerStack stack) {
- mCompositionDisplay->setLayerFilter({stack, isInternal()});
+void DisplayDevice::setLayerFilter(ui::LayerFilter filter) {
+ mCompositionDisplay->setLayerFilter(filter);
if (mRefreshRateOverlay) {
- mRefreshRateOverlay->setLayerStack(stack);
+ mRefreshRateOverlay->setLayerStack(filter.layerStack);
}
}
@@ -343,11 +323,7 @@
std::string name = "Display "s + to_string(getId()) + " ("s;
- if (mConnectionType) {
- name += isInternal() ? "internal"s : "external"s;
- } else {
- name += "virtual"s;
- }
+ name += isVirtual() ? "virtual"s : "physical"s;
if (isPrimary()) {
name += ", primary"s;
@@ -361,15 +337,6 @@
result += getDebugName();
- if (!isVirtual()) {
- result += "\n deviceProductInfo="s;
- if (mDeviceProductInfo) {
- mDeviceProductInfo->dump(result);
- } else {
- result += "{}"s;
- }
- }
-
result += "\n powerMode="s;
result += mPowerMode.has_value() ? to_string(mPowerMode.value()) : "OFF(reset)";
result += '\n';
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 3eead17..d79a6b5 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -65,6 +65,10 @@
class DisplaySurface;
} // namespace compositionengine
+namespace display {
+class DisplaySnapshot;
+} // namespace display
+
class DisplayDevice : public RefBase {
public:
constexpr static float sDefaultMinLumiance = 0.0;
@@ -80,11 +84,8 @@
return mCompositionDisplay;
}
- std::optional<ui::DisplayConnectionType> getConnectionType() const { return mConnectionType; }
-
- bool isVirtual() const { return !mConnectionType; }
+ bool isVirtual() const { return VirtualDisplayId::tryCast(getId()).has_value(); }
bool isPrimary() const { return mIsPrimary; }
- bool isInternal() const { return mConnectionType == ui::DisplayConnectionType::Internal; }
// isSecure indicates whether this display can be trusted to display
// secure surfaces.
@@ -94,7 +95,7 @@
int getHeight() const;
ui::Size getSize() const { return {getWidth(), getHeight()}; }
- void setLayerStack(ui::LayerStack);
+ void setLayerFilter(ui::LayerFilter);
void setDisplaySize(int width, int height);
void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
void stageBrightness(float brightness) REQUIRES(kMainThreadContext);
@@ -164,11 +165,6 @@
void setDisplayName(const std::string& displayName);
const std::string& getDisplayName() const { return mDisplayName; }
- void setDeviceProductInfo(std::optional<DeviceProductInfo> info);
- const std::optional<DeviceProductInfo>& getDeviceProductInfo() const {
- return mDeviceProductInfo;
- }
-
struct InputInfo {
gui::DisplayInfo info;
ui::Transform transform;
@@ -211,24 +207,14 @@
return mUpcomingActiveMode;
}
- void setActiveMode(DisplayModeId) REQUIRES(kMainThreadContext);
+ // Precondition: DisplaySnapshot must contain a mode with DisplayModeId.
+ void setActiveMode(DisplayModeId, const display::DisplaySnapshot&) REQUIRES(kMainThreadContext);
+
status_t initiateModeChange(const ActiveModeInfo&,
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline)
REQUIRES(kMainThreadContext);
- // Return the immutable list of supported display modes. The HWC may report different modes
- // after a hotplug reconnect event, in which case the DisplayDevice object will be recreated.
- // Hotplug reconnects are common for external displays.
- const DisplayModes& getSupportedModes() const;
-
- // Returns nullptr if the given mode ID is not supported. A previously
- // supported mode may be no longer supported for some devices like TVs and
- // set-top boxes after a hotplug reconnect.
- DisplayModePtr getMode(DisplayModeId) const;
-
- std::optional<DisplayModeId> translateModeId(hal::HWConfigId) const;
-
// Returns the refresh rate configs for this display.
scheduler::RefreshRateConfigs& refreshRateConfigs() const { return *mRefreshRateConfigs; }
@@ -267,7 +253,6 @@
HWComposer& mHwComposer;
const wp<IBinder> mDisplayToken;
const int32_t mSequenceId;
- const std::optional<ui::DisplayConnectionType> mConnectionType;
const std::shared_ptr<compositionengine::Display> mCompositionDisplay;
@@ -285,7 +270,6 @@
DisplayModePtr mActiveMode;
std::optional<float> mStagedBrightness = std::nullopt;
float mBrightness = -1.f;
- const DisplayModes mSupportedModes;
std::atomic<nsecs_t> mLastHwVsync = 0;
@@ -294,8 +278,6 @@
uint32_t mFlags = 0;
- std::optional<DeviceProductInfo> mDeviceProductInfo;
-
std::vector<ui::Hdr> mOverrideHdrTypes;
std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
@@ -313,14 +295,11 @@
struct DisplayDeviceState {
struct Physical {
PhysicalDisplayId id;
- ui::DisplayConnectionType type;
hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
- std::optional<DeviceProductInfo> deviceProductInfo;
- DisplayModes supportedModes;
DisplayModePtr activeMode;
bool operator==(const Physical& other) const {
- return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
+ return id == other.id && hwcDisplayId == other.hwcDisplayId;
}
};
@@ -356,7 +335,6 @@
std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs;
int32_t sequenceId{0};
- std::optional<ui::DisplayConnectionType> connectionType;
bool isSecure{false};
sp<ANativeWindow> nativeWindow;
sp<compositionengine::DisplaySurface> displaySurface;
@@ -367,7 +345,6 @@
std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes;
std::optional<hardware::graphics::composer::hal::PowerMode> initialPowerMode;
bool isPrimary{false};
- DisplayModes supportedModes;
DisplayModeId activeModeId;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cc93db3..1bb81c5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -53,9 +53,10 @@
#include <configstore/Utils.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
+#include <ftl/algorithm.h>
#include <ftl/fake_guard.h>
#include <ftl/future.h>
-#include <ftl/small_map.h>
+#include <ftl/unit.h>
#include <gui/AidlStatusUtil.h>
#include <gui/BufferQueue.h>
#include <gui/DebugEGLImageTracker.h>
@@ -108,6 +109,7 @@
#include "BufferStateLayer.h"
#include "Client.h"
#include "Colorizer.h"
+#include "Display/DisplayMap.h"
#include "DisplayDevice.h"
#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
@@ -172,6 +174,8 @@
OutputCompositionState::CompositionStrategyPredictionState;
using base::StringAppendF;
+using display::PhysicalDisplay;
+using display::PhysicalDisplays;
using gui::DisplayInfo;
using gui::GameMode;
using gui::IDisplayEventConnection;
@@ -594,12 +598,12 @@
std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdsLocked() const {
std::vector<PhysicalDisplayId> displayIds;
- displayIds.reserve(mPhysicalDisplayTokens.size());
+ displayIds.reserve(mPhysicalDisplays.size());
const auto defaultDisplayId = getDefaultDisplayDeviceLocked()->getPhysicalId();
displayIds.push_back(defaultDisplayId);
- for (const auto& [id, token] : mPhysicalDisplayTokens) {
+ for (const auto& [id, display] : mPhysicalDisplays) {
if (id != defaultDisplayId) {
displayIds.push_back(id);
}
@@ -608,6 +612,12 @@
return displayIds;
}
+std::optional<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdLocked(
+ const sp<display::DisplayToken>& displayToken) const {
+ return ftl::find_if(mPhysicalDisplays, PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_key<PhysicalDisplays>);
+}
+
sp<IBinder> SurfaceFlinger::getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
Mutex::Autolock lock(mStateLock);
return getPhysicalDisplayTokenLocked(displayId);
@@ -932,16 +942,19 @@
Mutex::Autolock lock(mStateLock);
- const auto display = getDisplayDeviceLocked(displayToken);
- if (!display) {
+ const auto displayOpt = ftl::find_if(mPhysicalDisplays, PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_mapped_ref<PhysicalDisplays>)
+ .and_then(getDisplayDeviceAndSnapshot());
+
+ if (!displayOpt) {
return NAME_NOT_FOUND;
}
- if (const auto connectionType = display->getConnectionType())
- info->connectionType = *connectionType;
- else {
- return INVALID_OPERATION;
- }
+ const auto& [display, snapshotRef] = *displayOpt;
+ const auto& snapshot = snapshotRef.get();
+
+ info->connectionType = snapshot.connectionType();
+ info->deviceProductInfo = snapshot.deviceProductInfo();
if (mEmulatedDisplayDensity) {
info->density = mEmulatedDisplayDensity;
@@ -953,7 +966,6 @@
info->density /= ACONFIGURATION_DENSITY_MEDIUM;
info->secure = display->isSecure();
- info->deviceProductInfo = display->getDeviceProductInfo();
info->installOrientation = display->getPhysicalOrientation();
return NO_ERROR;
@@ -967,23 +979,22 @@
Mutex::Autolock lock(mStateLock);
- const auto display = getDisplayDeviceLocked(displayToken);
- if (!display) {
+ const auto displayOpt = ftl::find_if(mPhysicalDisplays, PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_mapped_ref<PhysicalDisplays>)
+ .and_then(getDisplayDeviceAndSnapshot());
+ if (!displayOpt) {
return NAME_NOT_FOUND;
}
- const auto displayId = PhysicalDisplayId::tryCast(display->getId());
- if (!displayId) {
- return INVALID_OPERATION;
- }
+ const auto& [display, snapshotRef] = *displayOpt;
+ const auto& snapshot = snapshotRef.get();
- info->activeDisplayModeId = display->getActiveMode()->getId().value();
+ const auto& displayModes = snapshot.displayModes();
- const auto& supportedModes = display->getSupportedModes();
info->supportedDisplayModes.clear();
- info->supportedDisplayModes.reserve(supportedModes.size());
+ info->supportedDisplayModes.reserve(displayModes.size());
- for (const auto& [id, mode] : supportedModes) {
+ for (const auto& [id, mode] : displayModes) {
ui::DisplayMode outMode;
outMode.id = static_cast<int32_t>(id.value());
@@ -1027,21 +1038,24 @@
info->supportedDisplayModes.push_back(outMode);
}
+ const PhysicalDisplayId displayId = snapshot.displayId();
+
+ info->activeDisplayModeId = display->getActiveMode()->getId().value();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
- info->supportedColorModes = getDisplayColorModes(*display);
+ info->supportedColorModes = getDisplayColorModes(displayId);
info->hdrCapabilities = display->getHdrCapabilities();
info->autoLowLatencyModeSupported =
- getHwComposer().hasDisplayCapability(*displayId,
+ getHwComposer().hasDisplayCapability(displayId,
DisplayCapability::AUTO_LOW_LATENCY_MODE);
info->gameContentTypeSupported =
- getHwComposer().supportsContentType(*displayId, hal::ContentType::GAME);
+ getHwComposer().supportsContentType(displayId, hal::ContentType::GAME);
info->preferredBootDisplayMode = static_cast<ui::DisplayModeId>(-1);
if (getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG)) {
- if (const auto hwcId = getHwComposer().getPreferredBootDisplayMode(*displayId)) {
- if (const auto modeId = display->translateModeId(*hwcId)) {
+ if (const auto hwcId = getHwComposer().getPreferredBootDisplayMode(displayId)) {
+ if (const auto modeId = snapshot.translateModeId(*hwcId)) {
info->preferredBootDisplayMode = modeId->value();
}
}
@@ -1089,39 +1103,44 @@
}
}
-status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<IBinder>& displayToken, int modeId) {
+status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToken>& displayToken,
+ DisplayModeId modeId) {
ATRACE_CALL();
if (!displayToken) {
return BAD_VALUE;
}
+ const char* const whence = __func__;
auto future = mScheduler->schedule([=]() -> status_t {
- const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken));
- if (!display) {
- ALOGE("Attempt to set allowed display modes for invalid display token %p",
- displayToken.get());
+ const auto displayOpt =
+ FTL_FAKE_GUARD(mStateLock,
+ ftl::find_if(mPhysicalDisplays,
+ PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_mapped_ref<PhysicalDisplays>)
+ .and_then(getDisplayDeviceAndSnapshot()));
+ if (!displayOpt) {
+ ALOGE("%s: Invalid physical display token %p", whence, displayToken.get());
return NAME_NOT_FOUND;
}
- if (display->isVirtual()) {
- ALOGW("Attempt to set allowed display modes for virtual display");
- return INVALID_OPERATION;
- }
+ const auto& [display, snapshotRef] = *displayOpt;
+ const auto& snapshot = snapshotRef.get();
- const auto mode = display->getMode(DisplayModeId{modeId});
- if (!mode) {
- ALOGW("Attempt to switch to an unsupported mode %d.", modeId);
+ const auto fpsOpt = snapshot.displayModes().get(modeId).transform(
+ [](const DisplayModePtr& mode) { return mode->getFps(); });
+
+ if (!fpsOpt) {
+ ALOGE("%s: Invalid mode %d for display %s", whence, modeId.value(),
+ to_string(snapshot.displayId()).c_str());
return BAD_VALUE;
}
- const auto fps = mode->getFps();
+ const Fps fps = *fpsOpt;
// Keep the old switching type.
- const auto allowGroupSwitching =
+ const bool allowGroupSwitching =
display->refreshRateConfigs().getCurrentPolicy().allowGroupSwitching;
- const scheduler::RefreshRateConfigs::Policy policy{mode->getId(),
- allowGroupSwitching,
- {fps, fps}};
+ const scheduler::RefreshRateConfigs::Policy policy{modeId, allowGroupSwitching, {fps, fps}};
constexpr bool kOverridePolicy = false;
return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy);
@@ -1159,9 +1178,12 @@
return;
}
- // We just created this display so we can call even if we are not on the main thread.
- ftl::FakeGuard guard(kMainThreadContext);
- display->setActiveMode(upcomingModeInfo.mode->getId());
+ mPhysicalDisplays.get(display->getPhysicalId())
+ .transform(&PhysicalDisplay::snapshotRef)
+ .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) {
+ FTL_FAKE_GUARD(kMainThreadContext,
+ display->setActiveMode(upcomingModeInfo.mode->getId(), snapshot));
+ }));
const Fps refreshRate = upcomingModeInfo.mode->getFps();
mRefreshRateStats->setRefreshRate(refreshRate);
@@ -1191,12 +1213,16 @@
std::optional<PhysicalDisplayId> displayToUpdateImmediately;
- for (const auto& iter : mDisplays) {
- const auto& display = iter.second;
- if (!display || !display->isInternal()) {
+ for (const auto& [id, physical] : mPhysicalDisplays) {
+ const auto& snapshot = physical.snapshot();
+
+ if (snapshot.connectionType() != ui::DisplayConnectionType::Internal) {
continue;
}
+ const auto display = getDisplayDeviceLocked(id);
+ if (!display) continue;
+
// Store the local variable to release the lock.
const auto desiredActiveMode = display->getDesiredActiveMode();
if (!desiredActiveMode) {
@@ -1210,20 +1236,23 @@
continue;
}
- const auto desiredMode = display->getMode(desiredActiveMode->mode->getId());
- if (!desiredMode) {
+ const auto desiredModeId = desiredActiveMode->mode->getId();
+ const auto refreshRateOpt =
+ snapshot.displayModes()
+ .get(desiredModeId)
+ .transform([](const DisplayModePtr& mode) { return mode->getFps(); });
+
+ if (!refreshRateOpt) {
ALOGW("Desired display mode is no longer supported. Mode ID = %d",
- desiredActiveMode->mode->getId().value());
+ desiredModeId.value());
clearDesiredActiveModeState(display);
continue;
}
- const auto refreshRate = desiredMode->getFps();
- ALOGV("%s changing active mode to %d(%s) for display %s", __func__,
- desiredMode->getId().value(), to_string(refreshRate).c_str(),
- to_string(display->getId()).c_str());
+ ALOGV("%s changing active mode to %d(%s) for display %s", __func__, desiredModeId.value(),
+ to_string(*refreshRateOpt).c_str(), to_string(display->getId()).c_str());
- if (display->getActiveMode()->getId() == desiredActiveMode->mode->getId()) {
+ if (display->getActiveMode()->getId() == desiredModeId) {
// we are already in the requested mode, there is nothing left to do
desiredActiveModeChangeDone(display);
continue;
@@ -1232,8 +1261,7 @@
// Desired active mode was set, it is different than the mode currently in use, however
// allowed modes might have changed by the time we process the refresh.
// Make sure the desired mode is still allowed
- const auto displayModeAllowed =
- display->refreshRateConfigs().isModeAllowed(desiredActiveMode->mode->getId());
+ const auto displayModeAllowed = display->refreshRateConfigs().isModeAllowed(desiredModeId);
if (!displayModeAllowed) {
clearDesiredActiveModeState(display);
continue;
@@ -1295,15 +1323,18 @@
future.wait();
}
-std::vector<ColorMode> SurfaceFlinger::getDisplayColorModes(const DisplayDevice& display) {
- auto modes = getHwComposer().getColorModes(display.getPhysicalId());
+std::vector<ColorMode> SurfaceFlinger::getDisplayColorModes(PhysicalDisplayId displayId) {
+ auto modes = getHwComposer().getColorModes(displayId);
+
+ const bool isInternalDisplay = mPhysicalDisplays.get(displayId)
+ .transform(&PhysicalDisplay::isInternal)
+ .value_or(false);
// If the display is internal and the configuration claims it's not wide color capable,
// filter out all wide color modes. The typical reason why this happens is that the
// hardware is not good enough to support GPU composition of wide color, and thus the
// OEMs choose to disable this capability.
- if (display.getConnectionType() == ui::DisplayConnectionType::Internal &&
- !hasWideColorDisplay) {
+ if (isInternalDisplay && !hasWideColorDisplay) {
const auto newEnd = std::remove_if(modes.begin(), modes.end(), isWideColorMode);
modes.erase(newEnd, modes.end());
}
@@ -1319,13 +1350,13 @@
Mutex::Autolock lock(mStateLock);
- const auto display = getDisplayDeviceLocked(displayToken);
+ const auto display = ftl::find_if(mPhysicalDisplays, PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_mapped_ref<PhysicalDisplays>);
if (!display) {
return NAME_NOT_FOUND;
}
- const auto connectionType = display->getConnectionType();
- if (connectionType != ui::DisplayConnectionType::Internal) {
+ if (!display.transform(&PhysicalDisplay::isInternal).value()) {
return INVALID_OPERATION;
}
@@ -1353,7 +1384,7 @@
return INVALID_OPERATION;
}
- const auto modes = getDisplayColorModes(*display);
+ const auto modes = getDisplayColorModes(display->getPhysicalId());
const bool exists = std::find(modes.begin(), modes.end(), mode) != modes.end();
if (mode < ColorMode::NATIVE || !exists) {
@@ -1381,30 +1412,31 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken,
- ui::DisplayModeId modeId) {
+status_t SurfaceFlinger::setBootDisplayMode(const sp<display::DisplayToken>& displayToken,
+ DisplayModeId modeId) {
const char* const whence = __func__;
auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t {
- const auto display = getDisplayDeviceLocked(displayToken);
- if (!display) {
- ALOGE("%s: Invalid display token %p", whence, displayToken.get());
+ const auto snapshotOpt =
+ ftl::find_if(mPhysicalDisplays, PhysicalDisplay::hasToken(displayToken))
+ .transform(&ftl::to_mapped_ref<PhysicalDisplays>)
+ .transform(&PhysicalDisplay::snapshotRef);
+
+ if (!snapshotOpt) {
+ ALOGE("%s: Invalid physical display token %p", whence, displayToken.get());
return NAME_NOT_FOUND;
}
- if (display->isVirtual()) {
- ALOGE("%s: Invalid operation on virtual display", whence);
- return INVALID_OPERATION;
- }
+ const auto& snapshot = snapshotOpt->get();
+ const auto hwcIdOpt = snapshot.displayModes().get(modeId).transform(
+ [](const DisplayModePtr& mode) { return mode->getHwcId(); });
- const auto displayId = display->getPhysicalId();
- const auto mode = display->getMode(DisplayModeId{modeId});
- if (!mode) {
- ALOGE("%s: Invalid mode %d for display %s", whence, modeId,
- to_string(displayId).c_str());
+ if (!hwcIdOpt) {
+ ALOGE("%s: Invalid mode %d for display %s", whence, modeId.value(),
+ to_string(snapshot.displayId()).c_str());
return BAD_VALUE;
}
- return getHwComposer().setBootDisplayMode(displayId, mode->getHwcId());
+ return getHwComposer().setBootDisplayMode(snapshot.displayId(), *hwcIdOpt);
});
return future.get();
}
@@ -2467,7 +2499,13 @@
mTimeStats->incrementTotalFrames();
mTimeStats->setPresentFenceGlobal(presentFenceTime);
- if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&
+ const bool isInternalDisplay = display &&
+ FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays)
+ .get(display->getPhysicalId())
+ .transform(&PhysicalDisplay::isInternal)
+ .value_or(false);
+
+ if (isInternalDisplay && display && display->getPowerMode() == hal::PowerMode::ON &&
presentFenceTime->isValid()) {
mScheduler->addPresentFence(std::move(presentFenceTime));
}
@@ -2601,10 +2639,11 @@
return {};
}
- DisplayModes oldModes;
- if (const auto token = getPhysicalDisplayTokenLocked(displayId)) {
- oldModes = getDisplayDeviceLocked(token)->getSupportedModes();
- }
+ const DisplayModes oldModes = mPhysicalDisplays.get(displayId)
+ .transform([](const PhysicalDisplay& display) {
+ return display.snapshot().displayModes();
+ })
+ .value_or(DisplayModes{});
ui::DisplayModeId nextModeId = 1 +
std::accumulate(oldModes.begin(), oldModes.end(), static_cast<ui::DisplayModeId>(-1),
@@ -2669,21 +2708,22 @@
const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId,
hal::HWDisplayId hwcDisplayId, bool connected,
DisplayIdentificationInfo&& info) {
- const auto tokenOpt = mPhysicalDisplayTokens.get(displayId);
+ const auto displayOpt = mPhysicalDisplays.get(displayId);
if (!connected) {
- LOG_ALWAYS_FATAL_IF(!tokenOpt);
+ LOG_ALWAYS_FATAL_IF(!displayOpt);
+ const auto& display = displayOpt->get();
- if (const ssize_t index = mCurrentState.displays.indexOfKey(tokenOpt->get()); index >= 0) {
+ if (const ssize_t index = mCurrentState.displays.indexOfKey(display.token()); index >= 0) {
const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
mInterceptor->saveDisplayDeletion(state.sequenceId);
mCurrentState.displays.removeItemsAt(index);
}
- mPhysicalDisplayTokens.erase(displayId);
+ mPhysicalDisplays.erase(displayId);
return "Disconnecting";
}
- auto [supportedModes, activeMode] = loadDisplayModes(displayId);
+ auto [displayModes, activeMode] = loadDisplayModes(displayId);
if (!activeMode) {
// TODO(b/241286153): Report hotplug failure to the framework.
ALOGE("Failed to hotplug display %s", to_string(displayId).c_str());
@@ -2691,30 +2731,42 @@
return nullptr;
}
- if (tokenOpt) {
- auto& state = mCurrentState.displays.editValueFor(tokenOpt->get());
- state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId.
- state.physical->supportedModes = std::move(supportedModes);
- state.physical->activeMode = std::move(activeMode);
+ if (displayOpt) {
+ const auto& display = displayOpt->get();
+ const auto& snapshot = display.snapshot();
+
+ std::optional<DeviceProductInfo> deviceProductInfo;
if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
- state.physical->deviceProductInfo = std::move(info.deviceProductInfo);
+ deviceProductInfo = std::move(info.deviceProductInfo);
+ } else {
+ deviceProductInfo = snapshot.deviceProductInfo();
}
+
+ const auto it =
+ mPhysicalDisplays.try_replace(displayId, display.token(), displayId,
+ snapshot.connectionType(), std::move(displayModes),
+ std::move(deviceProductInfo));
+
+ auto& state = mCurrentState.displays.editValueFor(it->second.token());
+ state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId.
+ state.physical->activeMode = std::move(activeMode);
return "Reconnecting";
}
+ const sp<IBinder> token = sp<BBinder>::make();
+
+ mPhysicalDisplays.try_emplace(displayId, token, displayId,
+ getHwComposer().getDisplayConnectionType(displayId),
+ std::move(displayModes), std::move(info.deviceProductInfo));
+
DisplayDeviceState state;
state.physical = {.id = displayId,
- .type = getHwComposer().getDisplayConnectionType(displayId),
.hwcDisplayId = hwcDisplayId,
- .deviceProductInfo = std::move(info.deviceProductInfo),
- .supportedModes = std::move(supportedModes),
.activeMode = std::move(activeMode)};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = std::move(info.name);
- sp<IBinder> token = sp<BBinder>::make();
mCurrentState.displays.add(token, state);
- mPhysicalDisplayTokens.try_emplace(displayId, std::move(token));
mInterceptor->saveDisplayCreation(state);
return "Connecting";
}
@@ -2739,8 +2791,6 @@
creationArgs.supportedPerFrameMetadata = 0;
if (const auto& physical = state.physical) {
- creationArgs.connectionType = physical->type;
- creationArgs.supportedModes = physical->supportedModes;
creationArgs.activeModeId = physical->activeMode->getId();
const auto [kernelIdleTimerController, idleTimerTimeoutMs] =
getKernelIdleTimerProperties(compositionDisplay->getId());
@@ -2751,9 +2801,17 @@
base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0),
.idleTimerTimeout = idleTimerTimeoutMs,
.kernelIdleTimerController = kernelIdleTimerController};
+
creationArgs.refreshRateConfigs =
- std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
- creationArgs.activeModeId, config);
+ mPhysicalDisplays.get(physical->id)
+ .transform(&PhysicalDisplay::snapshotRef)
+ .transform([&](const display::DisplaySnapshot& snapshot) {
+ return std::make_shared<
+ scheduler::RefreshRateConfigs>(snapshot.displayModes(),
+ creationArgs.activeModeId,
+ config);
+ })
+ .value_or(nullptr);
}
if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
@@ -2811,13 +2869,17 @@
compositionengine::Output::ColorProfile{defaultColorMode, defaultDataSpace,
RenderIntent::COLORIMETRIC,
Dataspace::UNKNOWN});
- if (!state.isVirtual()) {
- FTL_FAKE_GUARD(kMainThreadContext,
- display->setActiveMode(state.physical->activeMode->getId()));
- display->setDeviceProductInfo(state.physical->deviceProductInfo);
+
+ if (const auto& physical = state.physical) {
+ mPhysicalDisplays.get(physical->id)
+ .transform(&PhysicalDisplay::snapshotRef)
+ .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) {
+ FTL_FAKE_GUARD(kMainThreadContext,
+ display->setActiveMode(physical->activeMode->getId(), snapshot));
+ }));
}
- display->setLayerStack(state.layerStack);
+ display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack));
display->setProjection(state.orientation, state.layerStackSpaceRect,
state.orientedDisplaySpaceRect);
display->setDisplayName(state.displayName);
@@ -2973,7 +3035,8 @@
if (const auto display = getDisplayDeviceLocked(displayToken)) {
if (currentState.layerStack != drawingState.layerStack) {
- display->setLayerStack(currentState.layerStack);
+ display->setLayerFilter(
+ makeLayerFilterForDisplay(display->getId(), currentState.layerStack));
}
if (currentState.flags != drawingState.flags) {
display->setFlags(currentState.flags);
@@ -3219,7 +3282,7 @@
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
std::vector<DisplayInfo>& outDisplayInfos) {
- ftl::SmallMap<ui::LayerStack, DisplayDevice::InputInfo, 4> displayInputInfos;
+ display::DisplayMap<ui::LayerStack, DisplayDevice::InputInfo> displayInputInfos;
for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
const auto layerStack = display->getLayerStack();
@@ -4718,8 +4781,12 @@
return;
}
+ const bool isInternalDisplay = mPhysicalDisplays.get(displayId)
+ .transform(&PhysicalDisplay::isInternal)
+ .value_or(false);
+
const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken);
- if (activeDisplay != display && display->isInternal() && activeDisplay &&
+ if (isInternalDisplay && activeDisplay != display && activeDisplay &&
activeDisplay->isPoweredOn()) {
ALOGW("Trying to change power mode on non active display while the active display is ON");
}
@@ -4732,7 +4799,7 @@
const auto refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
if (*currentMode == hal::PowerMode::OFF) {
// Turn on the display
- if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
+ if (isInternalDisplay && (!activeDisplay || !activeDisplay->isPoweredOn())) {
onActiveDisplayChangedLocked(display);
}
// Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.
@@ -4991,10 +5058,20 @@
}
void SurfaceFlinger::dumpDisplays(std::string& result) const {
- for (const auto& [token, display] : mDisplays) {
- display->dump(result);
+ for (const auto& [id, display] : mPhysicalDisplays) {
+ if (const auto device = getDisplayDeviceLocked(id)) {
+ device->dump(result);
+ }
+ display.snapshot().dump(result);
result += '\n';
}
+
+ for (const auto& [token, display] : mDisplays) {
+ if (display->isVirtual()) {
+ display->dump(result);
+ result += '\n';
+ }
+ }
}
void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const {
@@ -5793,7 +5870,7 @@
}();
mDebugDisplayModeSetByBackdoor = false;
- const status_t result = setActiveModeFromBackdoor(display, modeId);
+ const status_t result = setActiveModeFromBackdoor(display, DisplayModeId{modeId});
mDebugDisplayModeSetByBackdoor = result == NO_ERROR;
return result;
}
@@ -6700,15 +6777,28 @@
mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode);
}
- const DisplayModePtr preferredDisplayMode = [&] {
- const auto schedulerMode = mScheduler->getPreferredDisplayMode();
- if (schedulerMode && schedulerMode->getPhysicalDisplayId() == display->getPhysicalId()) {
+ const DisplayModePtr preferredDisplayMode = [&]() REQUIRES(mStateLock) -> DisplayModePtr {
+ const auto displayId = display->getPhysicalId();
+
+ if (const auto schedulerMode = mScheduler->getPreferredDisplayMode();
+ schedulerMode && schedulerMode->getPhysicalDisplayId() == displayId) {
return schedulerMode;
}
- return display->getMode(currentPolicy.defaultMode);
+ const DisplayModePtr nullMode;
+ return mPhysicalDisplays.get(displayId)
+ .transform(&PhysicalDisplay::snapshotRef)
+ .and_then([&](const display::DisplaySnapshot& snapshot) {
+ return snapshot.displayModes().get(currentPolicy.defaultMode);
+ })
+ .value_or(std::cref(nullMode));
}();
+ if (!preferredDisplayMode) {
+ ALOGE("%s: Preferred mode is unknown", __func__);
+ return NAME_NOT_FOUND;
+ }
+
ALOGV("trying to switch to Scheduler preferred mode %d (%s)",
preferredDisplayMode->getId().value(), to_string(preferredDisplayMode->getFps()).c_str());
@@ -6879,9 +6969,11 @@
}
void SurfaceFlinger::enableRefreshRateOverlay(bool enable) {
- for (const auto& [ignored, display] : mDisplays) {
- if (display->isInternal()) {
- display->enableRefreshRateOverlay(enable, mRefreshRateOverlaySpinner);
+ for (const auto& [id, display] : mPhysicalDisplays) {
+ if (display.snapshot().connectionType() == ui::DisplayConnectionType::Internal) {
+ if (const auto device = getDisplayDeviceLocked(id)) {
+ device->enableRefreshRateOverlay(enable, mRefreshRateOverlaySpinner);
+ }
}
}
}
@@ -7367,8 +7459,7 @@
int displayModeId) {
status_t status = checkAccessPermission();
if (status == OK) {
- status = mFlinger->setBootDisplayMode(display,
- static_cast<ui::DisplayModeId>(displayModeId));
+ status = mFlinger->setBootDisplayMode(display, DisplayModeId{displayModeId});
}
return binderStatusFromStatusT(status);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3101885..e9e13ef 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -29,7 +29,6 @@
#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <ftl/future.h>
-#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
#include <gui/CompositorTiming.h>
#include <gui/FrameTimestamps.h>
@@ -59,6 +58,8 @@
#include <ui/FenceResult.h>
#include "ClientCache.h"
+#include "Display/DisplayMap.h"
+#include "Display/PhysicalDisplay.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/PowerAdvisor.h"
@@ -515,7 +516,7 @@
status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken, ui::DisplayPrimaries&);
status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
status_t getBootDisplayModeSupport(bool* outSupport) const;
- status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id);
+ status_t setBootDisplayMode(const sp<display::DisplayToken>&, DisplayModeId);
status_t clearBootDisplayMode(const sp<IBinder>& displayToken);
void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on);
void setGameContentType(const sp<IBinder>& displayToken, bool on);
@@ -651,7 +652,7 @@
void onInitializeDisplays() REQUIRES(mStateLock);
// Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode.
void setDesiredActiveMode(const ActiveModeInfo& info) REQUIRES(mStateLock);
- status_t setActiveModeFromBackdoor(const sp<IBinder>& displayToken, int id);
+ status_t setActiveModeFromBackdoor(const sp<display::DisplayToken>&, DisplayModeId);
// Sets the active mode and a new refresh rate in SF.
void updateInternalStateWithChangedMode() REQUIRES(mStateLock);
// Calls to setActiveMode on the main thread if there is a pending mode change
@@ -820,6 +821,10 @@
// called when starting, or restarting after system_server death
void initializeDisplays();
+ bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) const REQUIRES(mStateLock) {
+ return display->getDisplayToken() == mActiveDisplayToken;
+ }
+
sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const
REQUIRES(mStateLock) {
return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(displayToken);
@@ -867,6 +872,21 @@
return getDefaultDisplayDeviceLocked();
}
+ using DisplayDeviceAndSnapshot =
+ std::pair<sp<DisplayDevice>, display::PhysicalDisplay::SnapshotRef>;
+
+ // Combinator for ftl::Optional<PhysicalDisplay>::and_then.
+ auto getDisplayDeviceAndSnapshot() REQUIRES(mStateLock) {
+ return [this](const display::PhysicalDisplay& display) REQUIRES(
+ mStateLock) -> ftl::Optional<DisplayDeviceAndSnapshot> {
+ if (auto device = getDisplayDeviceLocked(display.snapshot().displayId())) {
+ return std::make_pair(std::move(device), display.snapshotRef());
+ }
+
+ return {};
+ };
+ }
+
// Returns the first display that matches a `bool(const DisplayDevice&)` predicate.
template <typename Predicate>
sp<DisplayDevice> findDisplay(Predicate p) const REQUIRES(mStateLock) {
@@ -882,8 +902,13 @@
// region of all screens presenting this layer stack.
void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
- bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) const REQUIRES(mStateLock) {
- return display->getDisplayToken() == mActiveDisplayToken;
+ ui::LayerFilter makeLayerFilterForDisplay(DisplayId displayId, ui::LayerStack layerStack)
+ REQUIRES(mStateLock) {
+ return {layerStack,
+ PhysicalDisplayId::tryCast(displayId)
+ .and_then(display::getPhysicalDisplay(mPhysicalDisplays))
+ .transform(&display::PhysicalDisplay::isInternal)
+ .value_or(false)};
}
/*
@@ -959,21 +984,16 @@
/*
* Display identification
*/
- sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const
+ sp<display::DisplayToken> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const
REQUIRES(mStateLock) {
- const sp<IBinder> nullToken;
- return mPhysicalDisplayTokens.get(displayId).value_or(std::cref(nullToken));
+ const sp<display::DisplayToken> nullToken;
+ return mPhysicalDisplays.get(displayId)
+ .transform([](const display::PhysicalDisplay& display) { return display.token(); })
+ .value_or(std::cref(nullToken));
}
std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked(
- const sp<IBinder>& displayToken) const REQUIRES(mStateLock) {
- for (const auto& [id, token] : mPhysicalDisplayTokens) {
- if (token == displayToken) {
- return id;
- }
- }
- return {};
- }
+ const sp<display::DisplayToken>&) const REQUIRES(mStateLock);
// Returns the first display connected at boot.
//
@@ -1063,7 +1083,7 @@
/*
* Misc
*/
- std::vector<ui::ColorMode> getDisplayColorModes(const DisplayDevice&) REQUIRES(mStateLock);
+ std::vector<ui::ColorMode> getDisplayColorModes(PhysicalDisplayId) REQUIRES(mStateLock);
static int calculateMaxAcquiredBufferCount(Fps refreshRate,
std::chrono::nanoseconds presentLatency);
@@ -1164,12 +1184,10 @@
// Displays are composited in `mDisplays` order. Internal displays are inserted at boot and
// never removed, so take precedence over external and virtual displays.
//
- // The static capacities were chosen to exceed a typical number of physical/virtual displays.
- //
// May be read from any thread, but must only be written from the main thread.
- ftl::SmallMap<wp<IBinder>, const sp<DisplayDevice>, 5> mDisplays GUARDED_BY(mStateLock);
- ftl::SmallMap<PhysicalDisplayId, const sp<IBinder>, 3> mPhysicalDisplayTokens
- GUARDED_BY(mStateLock);
+ display::DisplayMap<wp<IBinder>, const sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);
+
+ display::PhysicalDisplays mPhysicalDisplays GUARDED_BY(mStateLock);
struct {
DisplayIdGenerator<GpuVirtualDisplayId> gpu;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 77625b3..e546c2f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -309,16 +309,20 @@
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs);
+ constexpr auto kDisplayConnectionType = ui::DisplayConnectionType::Internal;
+ constexpr bool kIsPrimary = true;
+
test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- ui::DisplayConnectionType::Internal, HWC_DISPLAY,
- true /* isPrimary */)
+ kDisplayConnectionType, HWC_DISPLAY, kIsPrimary)
.setDisplaySurface(test->mDisplaySurface)
.setNativeWindow(test->mNativeWindow)
.setSecure(Derived::IS_SECURE)
.setPowerMode(Derived::INIT_POWER_MODE)
.inject();
Mock::VerifyAndClear(test->mNativeWindow.get());
- test->mDisplay->setLayerStack(LAYER_STACK);
+
+ constexpr bool kIsInternal = kDisplayConnectionType == ui::DisplayConnectionType::Internal;
+ test->mDisplay->setLayerFilter({LAYER_STACK, kIsInternal});
}
template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index 71f1a2b..73f654b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -118,9 +118,7 @@
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
- expectedPhysical = {.id = *displayId,
- .type = *connectionType,
- .hwcDisplayId = *hwcDisplayId};
+ expectedPhysical = {.id = *displayId, .hwcDisplayId = *hwcDisplayId};
}
// The display should have been set up in the current display state
@@ -145,10 +143,13 @@
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId);
- ASSERT_TRUE(displayTokenOpt);
+ const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId);
+ ASSERT_TRUE(displayOpt);
- verifyDisplayIsConnected<Case>(displayTokenOpt->get());
+ const auto& display = displayOpt->get();
+ EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, display.snapshot().connectionType());
+
+ verifyDisplayIsConnected<Case>(display.token());
}
void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
@@ -247,10 +248,10 @@
// HWComposer should not have an entry for the display
EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
- // SF should not have a display token.
+ // SF should not have a PhysicalDisplay.
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId));
+ ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId));
// The existing token should have been removed.
verifyDisplayIsNotConnected(existing.token());
@@ -329,10 +330,10 @@
// HWComposer should not have an entry for the display
EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
- // SF should not have a display token.
+ // SF should not have a PhysicalDisplay.
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId));
+ ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId));
}(),
testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
}
@@ -376,9 +377,9 @@
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId));
- const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId);
- ASSERT_TRUE(displayTokenOpt);
- EXPECT_NE(existing.token(), displayTokenOpt->get());
+ const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId);
+ ASSERT_TRUE(displayOpt);
+ EXPECT_NE(existing.token(), displayOpt->get().token());
// A new display should be connected in its place.
verifyPhysicalDisplayIsConnected<Case>();
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index 1756368..9e54083 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -253,14 +253,16 @@
using DispSync = DispSyncVariant;
using Transition = TransitionVariant;
- static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, PowerMode mode) {
+ static sp<DisplayDevice> injectDisplayWithInitialPowerMode(DisplayTransactionTest* test,
+ PowerMode mode) {
Display::injectHwcDisplayWithNoDefaultCapabilities(test);
- auto display = Display::makeFakeExistingDisplayInjector(test);
- display.inject();
- display.mutableDisplayDevice()->setPowerMode(mode);
- if (display.mutableDisplayDevice()->isInternal()) {
- test->mFlinger.mutableActiveDisplayToken() =
- display.mutableDisplayDevice()->getDisplayToken();
+ auto injector = Display::makeFakeExistingDisplayInjector(test);
+ const auto display = injector.inject();
+ display->setPowerMode(mode);
+ if (injector.physicalDisplay()
+ .transform(&display::PhysicalDisplay::isInternal)
+ .value_or(false)) {
+ test->mFlinger.mutableActiveDisplayToken() = display->getDisplayToken();
}
return display;
@@ -353,8 +355,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.setPowerModeInternal(display.mutableDisplayDevice(),
- Case::Transition::TARGET_POWER_MODE);
+ mFlinger.setPowerModeInternal(display, Case::Transition::TARGET_POWER_MODE);
// --------------------------------------------------------------------
// Postconditions
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index 6aeb3fe..ec2c2b4 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -246,11 +246,14 @@
.setDpiY(DEFAULT_DPI)
.setGroup(0)
.build();
+
state.physical = {.id = *displayId,
- .type = *connectionType,
.hwcDisplayId = *hwcDisplayId,
- .supportedModes = makeModes(activeMode),
- .activeMode = std::move(activeMode)};
+ .activeMode = activeMode};
+
+ mFlinger.mutablePhysicalDisplays().emplace_or_replace(*displayId, displayToken, *displayId,
+ *connectionType,
+ makeModes(activeMode), std::nullopt);
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -264,7 +267,6 @@
ASSERT_TRUE(device != nullptr);
EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
- EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType());
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary());
@@ -280,7 +282,6 @@
device->receivesInput());
if constexpr (Case::Display::CONNECTION_TYPE::value) {
- EXPECT_EQ(1, device->getSupportedModes().size());
EXPECT_NE(nullptr, device->getActiveMode());
EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode()->getHwcId());
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 6c6c9aa..a6b3f7c 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -503,6 +503,7 @@
*/
const auto& displays() const { return mFlinger->mDisplays; }
+ const auto& physicalDisplays() const { return mFlinger->mPhysicalDisplays; }
const auto& currentState() const { return mFlinger->mCurrentState; }
const auto& drawingState() const { return mFlinger->mDrawingState; }
const auto& transactionFlags() const { return mFlinger->mTransactionFlags; }
@@ -515,12 +516,12 @@
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
auto& mutableDisplays() { return mFlinger->mDisplays; }
+ auto& mutablePhysicalDisplays() { return mFlinger->mPhysicalDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
auto& mutableGeometryDirty() { return mFlinger->mGeometryDirty; }
auto& mutableInterceptor() { return mFlinger->mInterceptor; }
auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
- auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; }
auto& mutableTexturePool() { return mFlinger->mTexturePool; }
auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; }
@@ -725,14 +726,20 @@
: mFlinger(flinger),
mCreationArgs(flinger.mFlinger, flinger.mFlinger->getHwComposer(), mDisplayToken,
display),
+ mConnectionType(connectionType),
mHwcDisplayId(hwcDisplayId) {
- mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
mCreationArgs.initialPowerMode = hal::PowerMode::ON;
}
sp<IBinder> token() const { return mDisplayToken; }
+ auto physicalDisplay() const {
+ return ftl::Optional(mCreationArgs.compositionDisplay->getDisplayId())
+ .and_then(&PhysicalDisplayId::tryCast)
+ .and_then(display::getPhysicalDisplay(mFlinger.physicalDisplays()));
+ }
+
DisplayDeviceState& mutableDrawingDisplayState() {
return mFlinger.mutableDrawingState().displays.editValueFor(mDisplayToken);
}
@@ -760,7 +767,7 @@
// the `configs` parameter in favor of an alternative setRefreshRateConfigs API.
auto& setDisplayModes(DisplayModes modes, DisplayModeId activeModeId,
std::shared_ptr<scheduler::RefreshRateConfigs> configs = nullptr) {
- mCreationArgs.supportedModes = std::move(modes);
+ mDisplayModes = std::move(modes);
mCreationArgs.activeModeId = activeModeId;
mCreationArgs.refreshRateConfigs = std::move(configs);
return *this;
@@ -806,7 +813,7 @@
sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS {
const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
- auto& modes = mCreationArgs.supportedModes;
+ auto& modes = mDisplayModes;
auto& activeModeId = mCreationArgs.activeModeId;
if (displayId && !mCreationArgs.refreshRateConfigs) {
@@ -834,8 +841,13 @@
}
}
+ sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
+ mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display);
+
DisplayDeviceState state;
- if (const auto type = mCreationArgs.connectionType) {
+ state.isSecure = mCreationArgs.isSecure;
+
+ if (mConnectionType) {
LOG_ALWAYS_FATAL_IF(!displayId);
const auto physicalId = PhysicalDisplayId::tryCast(*displayId);
LOG_ALWAYS_FATAL_IF(!physicalId);
@@ -845,29 +857,21 @@
LOG_ALWAYS_FATAL_IF(!activeMode);
state.physical = {.id = *physicalId,
- .type = *type,
.hwcDisplayId = *mHwcDisplayId,
- .deviceProductInfo = {},
- .supportedModes = modes,
.activeMode = activeMode->get()};
- }
- state.isSecure = mCreationArgs.isSecure;
+ const auto it = mFlinger.mutablePhysicalDisplays()
+ .emplace_or_replace(*physicalId, mDisplayToken, *physicalId,
+ *mConnectionType, std::move(modes),
+ std::nullopt)
+ .first;
- sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
- if (!display->isVirtual()) {
- display->setActiveMode(activeModeId);
+ display->setActiveMode(activeModeId, it->second.snapshot());
}
- mFlinger.mutableDisplays().emplace_or_replace(mDisplayToken, display);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
- if (const auto& physical = state.physical) {
- mFlinger.mutablePhysicalDisplayTokens().emplace_or_replace(physical->id,
- mDisplayToken);
- }
-
return display;
}
@@ -875,6 +879,8 @@
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = sp<BBinder>::make();
DisplayDeviceCreationArgs mCreationArgs;
+ DisplayModes mDisplayModes;
+ const std::optional<ui::DisplayConnectionType> mConnectionType;
const std::optional<hal::HWDisplayId> mHwcDisplayId;
};