Add atom reporting for modes on hotplugged displays
Add and use DisplayHotplugConnectModeDetectedAtomReporter, which logs all valid modes of a hotplugged display. Change-Id: Ie93487ad8e4936195e3d949ce46034c5ec4fda83
This commit is contained in:
parent
680790982c
commit
406a14f111
8 changed files with 260 additions and 0 deletions
|
|
@ -103,6 +103,7 @@ SKIP_FILES := \
|
|||
drm/DrmDisplayPipelineTest.cpp \
|
||||
stats/CompositionStatsTest.cpp \
|
||||
stats/CompositionStatsAtomReporterDesktop.cpp \
|
||||
stats/DisplayHotplugConnectModeDetectedAtomReporterDesktop.cpp \
|
||||
stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp \
|
||||
|
||||
BUILD_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/test_include/*' -path '*.cpp')
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ drm_hwcomposer_atom_reporter_library {
|
|||
srcs: [
|
||||
"compositor/FlatteningEventAtomReporterDesktop.cpp",
|
||||
"stats/CompositionStatsAtomReporterDesktop.cpp",
|
||||
"stats/DisplayHotplugConnectModeDetectedAtomReporterDesktop.cpp",
|
||||
"stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
|
|
@ -357,6 +358,7 @@ drm_hwcomposer_atom_reporter_library {
|
|||
srcs: [
|
||||
"compositor/FlatteningEventAtomReporter.cpp",
|
||||
"stats/CompositionStatsAtomReporter.cpp",
|
||||
"stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp",
|
||||
"stats/DisplayRefreshRatesChangedAtomReporter.cpp",
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "drm/VSyncWorker.h"
|
||||
#include "hwc/HwcLayer.h"
|
||||
#include "stats/CompositionStats.h"
|
||||
#include "stats/DisplayHotplugConnectModeDetectedAtomReporter.h"
|
||||
#include "utils/EdidWrapper.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/properties.h"
|
||||
|
|
@ -144,6 +145,9 @@ HwcDisplay::HwcDisplay(DisplayHandle handle, bool is_virtual, DrmHwc *hwc)
|
|||
writeback_layer_ = std::make_unique<HwcLayer>(this);
|
||||
|
||||
identity_color_matrix_ = ToColorTransform(kIdentityMatrix);
|
||||
|
||||
display_mode_reporter_ = DisplayHotplugConnectModeDetectedAtomReporter::
|
||||
Create();
|
||||
}
|
||||
|
||||
void HwcDisplay::SetColorTransformMatrix(
|
||||
|
|
@ -631,6 +635,9 @@ void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) {
|
|||
bool success = Init();
|
||||
ALOGE_IF(!success, "Failed to init HwcDisplay after setting pipeline.");
|
||||
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kConnected);
|
||||
if (pipeline_) {
|
||||
LogModesOnHotplug();
|
||||
}
|
||||
} else {
|
||||
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kDisconnected);
|
||||
}
|
||||
|
|
@ -1381,4 +1388,60 @@ std::pair<uint32_t, uint32_t> HwcDisplay::GetSize() const {
|
|||
config->mode.GetRawMode().vdisplay);
|
||||
}
|
||||
|
||||
void HwcDisplay::LogModesOnHotplug() {
|
||||
if (!display_mode_reporter_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const HwcDisplay::DisplayType display_type = GetDisplayType();
|
||||
if (display_type != HwcDisplay::DisplayType::kInternal &&
|
||||
display_type != HwcDisplay::DisplayType::kExternal) {
|
||||
return;
|
||||
}
|
||||
|
||||
using ModeAtom = DisplayHotplugConnectModeDetectedAtomReporter::Atom;
|
||||
std::vector<ModeAtom> submitted_atoms;
|
||||
for (const auto &[id, hwc_mode] : configs_.hwc_configs) {
|
||||
const DrmMode &mode = hwc_mode.mode;
|
||||
const drmModeModeInfo &raw_mode = mode.GetRawMode();
|
||||
const bool is_preferred = (raw_mode.type & DRM_MODE_TYPE_PREFERRED) != 0;
|
||||
|
||||
constexpr float kMmPerInch = 25.4;
|
||||
const auto [width_mm, height_mm] = GetDisplayBoundsMm();
|
||||
int32_t dpi_x = -1;
|
||||
if (width_mm > 0) {
|
||||
dpi_x = static_cast<int32_t>(
|
||||
lround((static_cast<float>(raw_mode.hdisplay) * kMmPerInch) /
|
||||
static_cast<float>(width_mm)));
|
||||
}
|
||||
int32_t dpi_y = dpi_x;
|
||||
if (height_mm > 0) {
|
||||
dpi_y = static_cast<int32_t>(
|
||||
lround((static_cast<float>(raw_mode.vdisplay) * kMmPerInch) /
|
||||
static_cast<float>(height_mm)));
|
||||
}
|
||||
|
||||
using AtomDisplayType = DisplayHotplugConnectModeDetectedAtomReporter::
|
||||
DisplayType;
|
||||
const ModeAtom atom =
|
||||
{.display_handle = handle_,
|
||||
.resolution_x = raw_mode.hdisplay,
|
||||
.resolution_y = raw_mode.vdisplay,
|
||||
.refresh_rate = static_cast<int32_t>(lround(mode.GetVRefresh())),
|
||||
.dpi_x = dpi_x,
|
||||
.dpi_y = dpi_y,
|
||||
.display_type = display_type == HwcDisplay::DisplayType::kInternal
|
||||
? AtomDisplayType::kInternal
|
||||
: AtomDisplayType::kExternal,
|
||||
.is_preferred = is_preferred};
|
||||
|
||||
if (std::find(submitted_atoms.begin(), submitted_atoms.end(), atom) !=
|
||||
submitted_atoms.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
display_mode_reporter_->PushAtom(atom);
|
||||
submitted_atoms.push_back(atom);
|
||||
}
|
||||
}
|
||||
} // namespace android::drm_hwcomposer
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ using aidl::android::hardware::graphics::common::Hdr;
|
|||
namespace android::drm_hwcomposer {
|
||||
|
||||
class ChangedLayer;
|
||||
class DisplayHotplugConnectModeDetectedAtomReporter;
|
||||
class DrmHwc;
|
||||
class EdidWrapper;
|
||||
class FlatteningController;
|
||||
|
|
@ -299,6 +300,8 @@ class HwcDisplay {
|
|||
return edid_wrapper_;
|
||||
}
|
||||
|
||||
void LogModesOnHotplug();
|
||||
|
||||
HwcDisplayConfigs configs_;
|
||||
|
||||
DrmHwc *const hwc_;
|
||||
|
|
@ -344,6 +347,9 @@ class HwcDisplay {
|
|||
HwcDisplay::HdcpState hdcp_state_ = HdcpState::kUndesired;
|
||||
|
||||
std::shared_ptr<FrontendDisplayBase> frontend_private_data_;
|
||||
|
||||
std::unique_ptr<DisplayHotplugConnectModeDetectedAtomReporter>
|
||||
display_mode_reporter_;
|
||||
};
|
||||
|
||||
} // namespace android::drm_hwcomposer
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ src_common = files(
|
|||
'stats/CompositionStats.cpp',
|
||||
'stats/CompositionStatsAtomReporter.cpp',
|
||||
'stats/CompositionStatsPoller.cpp',
|
||||
'stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp',
|
||||
'stats/DisplayRefreshRatesChangedAtomReporter.cpp',
|
||||
'utils/fd.cpp',
|
||||
'utils/LibdisplayEdidWrapper.cpp',
|
||||
|
|
|
|||
31
stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp
Normal file
31
stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "drmhwc"
|
||||
|
||||
#include "DisplayHotplugConnectModeDetectedAtomReporter.h"
|
||||
|
||||
#include "utils/log.h"
|
||||
|
||||
namespace android::drm_hwcomposer {
|
||||
|
||||
std::unique_ptr<DisplayHotplugConnectModeDetectedAtomReporter>
|
||||
DisplayHotplugConnectModeDetectedAtomReporter::Create() {
|
||||
ALOGI("Atom reporting is not enabled.");
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace android::drm_hwcomposer
|
||||
58
stats/DisplayHotplugConnectModeDetectedAtomReporter.h
Normal file
58
stats/DisplayHotplugConnectModeDetectedAtomReporter.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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 <memory>
|
||||
|
||||
namespace android::drm_hwcomposer {
|
||||
class DisplayHotplugConnectModeDetectedAtomReporter {
|
||||
public:
|
||||
static std::unique_ptr<DisplayHotplugConnectModeDetectedAtomReporter>
|
||||
Create();
|
||||
|
||||
enum class DisplayType {
|
||||
kUnspecified = 0,
|
||||
kInternal,
|
||||
kExternal,
|
||||
};
|
||||
|
||||
struct Atom {
|
||||
int64_t display_handle = 0;
|
||||
int32_t resolution_x = 0;
|
||||
int32_t resolution_y = 0;
|
||||
int32_t refresh_rate = 0;
|
||||
int32_t dpi_x = 0;
|
||||
int32_t dpi_y = 0;
|
||||
DisplayType display_type = DisplayType::kUnspecified;
|
||||
bool is_preferred = false;
|
||||
|
||||
bool operator==(const Atom& other) const {
|
||||
return display_handle == other.display_handle &&
|
||||
resolution_x == other.resolution_x &&
|
||||
resolution_y == other.resolution_y &&
|
||||
refresh_rate == other.refresh_rate && dpi_x == other.dpi_x &&
|
||||
dpi_y == other.dpi_y && display_type == other.display_type &&
|
||||
is_preferred == other.is_preferred;
|
||||
};
|
||||
};
|
||||
|
||||
// Pushes a Vendor Atom to IStats::reportVendorAtom.
|
||||
virtual void PushAtom(Atom atom) = 0;
|
||||
virtual ~DisplayHotplugConnectModeDetectedAtomReporter() = default;
|
||||
};
|
||||
|
||||
} // namespace android::drm_hwcomposer
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "drmhwc"
|
||||
// #define NLOG_DEBUG 0
|
||||
|
||||
#include "DisplayHotplugConnectModeDetectedAtomReporter.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <thread>
|
||||
|
||||
#include <aidl/android/frameworks/stats/IStats.h>
|
||||
#include <android/binder_manager.h>
|
||||
|
||||
#include "desktopatoms.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
using aidl::android::frameworks::stats::IStats;
|
||||
using aidl::android::frameworks::stats::VendorAtom;
|
||||
namespace DesktopAtoms = android::vendor::google::desktop::stats::DesktopAtoms;
|
||||
|
||||
namespace android::drm_hwcomposer {
|
||||
namespace {
|
||||
|
||||
DesktopAtoms::DisplayHotplugConnectModeDetected::DisplayType ToProtoEnum(
|
||||
DisplayHotplugConnectModeDetectedAtomReporter::DisplayType type) {
|
||||
switch (type) {
|
||||
case DisplayHotplugConnectModeDetectedAtomReporter::DisplayType::
|
||||
kUnspecified:
|
||||
return DesktopAtoms::DisplayHotplugConnectModeDetected::
|
||||
DISPLAY_TYPE_UNSPECIFIED;
|
||||
case DisplayHotplugConnectModeDetectedAtomReporter::DisplayType::kInternal:
|
||||
return DesktopAtoms::DisplayHotplugConnectModeDetected::
|
||||
DISPLAY_TYPE_INTERNAL;
|
||||
case DisplayHotplugConnectModeDetectedAtomReporter::DisplayType::kExternal:
|
||||
return DesktopAtoms::DisplayHotplugConnectModeDetected::
|
||||
DISPLAY_TYPE_EXTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string kStatsServiceName = std::string(IStats::descriptor)
|
||||
.append("/default");
|
||||
|
||||
// Use a private implementation of DisplayHotplugConnectModeDetectedAtomReporter
|
||||
// to avoid leaking the IStats interface through the public api.
|
||||
class DisplayHotplugConnectModeDetectedAtomReporterDesktop
|
||||
: public DisplayHotplugConnectModeDetectedAtomReporter {
|
||||
public:
|
||||
void PushAtom(Atom atom) override {
|
||||
ALOGE("zzzz DisplayHotplugConnectModeDetected");
|
||||
|
||||
// The order of the arguments to createVendorAtom is determined by the
|
||||
// proto definition in libdesktopatoms.
|
||||
const char* deprecated_reverse_domain_name = "";
|
||||
const VendorAtom vendor_atom = DesktopAtoms::
|
||||
createVendorAtom(DesktopAtoms::DISPLAY_HOTPLUG_CONNECT_MODE_DETECTED,
|
||||
deprecated_reverse_domain_name, atom.display_handle,
|
||||
atom.resolution_x, atom.resolution_y,
|
||||
atom.refresh_rate, atom.dpi_x, atom.dpi_y,
|
||||
ToProtoEnum(atom.display_type), atom.is_preferred);
|
||||
|
||||
auto stats_service = IStats::fromBinder(ndk::SpAIBinder(
|
||||
AServiceManager_checkService(kStatsServiceName.c_str())));
|
||||
ALOGE_IF(stats_service == nullptr, "Failed to get IStats service");
|
||||
if (stats_service) {
|
||||
const ndk::ScopedAStatus ret = stats_service->reportVendorAtom(
|
||||
vendor_atom);
|
||||
ALOGE_IF(!ret.isOk(), "Failed to report stats: %s",
|
||||
ret.getDescription().c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<DisplayHotplugConnectModeDetectedAtomReporter>
|
||||
DisplayHotplugConnectModeDetectedAtomReporter::Create() {
|
||||
if (!AServiceManager_isDeclared(kStatsServiceName.c_str())) {
|
||||
ALOGW("Stats service is not declared.");
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<
|
||||
DisplayHotplugConnectModeDetectedAtomReporterDesktop>();
|
||||
}
|
||||
|
||||
} // namespace android::drm_hwcomposer
|
||||
Loading…
Add table
Add a link
Reference in a new issue