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 \
|
drm/DrmDisplayPipelineTest.cpp \
|
||||||
stats/CompositionStatsTest.cpp \
|
stats/CompositionStatsTest.cpp \
|
||||||
stats/CompositionStatsAtomReporterDesktop.cpp \
|
stats/CompositionStatsAtomReporterDesktop.cpp \
|
||||||
|
stats/DisplayHotplugConnectModeDetectedAtomReporterDesktop.cpp \
|
||||||
stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp \
|
stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp \
|
||||||
|
|
||||||
BUILD_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/test_include/*' -path '*.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: [
|
srcs: [
|
||||||
"compositor/FlatteningEventAtomReporterDesktop.cpp",
|
"compositor/FlatteningEventAtomReporterDesktop.cpp",
|
||||||
"stats/CompositionStatsAtomReporterDesktop.cpp",
|
"stats/CompositionStatsAtomReporterDesktop.cpp",
|
||||||
|
"stats/DisplayHotplugConnectModeDetectedAtomReporterDesktop.cpp",
|
||||||
"stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp",
|
"stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp",
|
||||||
],
|
],
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
|
|
@ -357,6 +358,7 @@ drm_hwcomposer_atom_reporter_library {
|
||||||
srcs: [
|
srcs: [
|
||||||
"compositor/FlatteningEventAtomReporter.cpp",
|
"compositor/FlatteningEventAtomReporter.cpp",
|
||||||
"stats/CompositionStatsAtomReporter.cpp",
|
"stats/CompositionStatsAtomReporter.cpp",
|
||||||
|
"stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp",
|
||||||
"stats/DisplayRefreshRatesChangedAtomReporter.cpp",
|
"stats/DisplayRefreshRatesChangedAtomReporter.cpp",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "drm/VSyncWorker.h"
|
#include "drm/VSyncWorker.h"
|
||||||
#include "hwc/HwcLayer.h"
|
#include "hwc/HwcLayer.h"
|
||||||
#include "stats/CompositionStats.h"
|
#include "stats/CompositionStats.h"
|
||||||
|
#include "stats/DisplayHotplugConnectModeDetectedAtomReporter.h"
|
||||||
#include "utils/EdidWrapper.h"
|
#include "utils/EdidWrapper.h"
|
||||||
#include "utils/log.h"
|
#include "utils/log.h"
|
||||||
#include "utils/properties.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);
|
writeback_layer_ = std::make_unique<HwcLayer>(this);
|
||||||
|
|
||||||
identity_color_matrix_ = ToColorTransform(kIdentityMatrix);
|
identity_color_matrix_ = ToColorTransform(kIdentityMatrix);
|
||||||
|
|
||||||
|
display_mode_reporter_ = DisplayHotplugConnectModeDetectedAtomReporter::
|
||||||
|
Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HwcDisplay::SetColorTransformMatrix(
|
void HwcDisplay::SetColorTransformMatrix(
|
||||||
|
|
@ -631,6 +635,9 @@ void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) {
|
||||||
bool success = Init();
|
bool success = Init();
|
||||||
ALOGE_IF(!success, "Failed to init HwcDisplay after setting pipeline.");
|
ALOGE_IF(!success, "Failed to init HwcDisplay after setting pipeline.");
|
||||||
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kConnected);
|
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kConnected);
|
||||||
|
if (pipeline_) {
|
||||||
|
LogModesOnHotplug();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kDisconnected);
|
hwc_->ScheduleHotplugEvent(handle_, DrmHwc::kDisconnected);
|
||||||
}
|
}
|
||||||
|
|
@ -1381,4 +1388,60 @@ std::pair<uint32_t, uint32_t> HwcDisplay::GetSize() const {
|
||||||
config->mode.GetRawMode().vdisplay);
|
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
|
} // namespace android::drm_hwcomposer
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ using aidl::android::hardware::graphics::common::Hdr;
|
||||||
namespace android::drm_hwcomposer {
|
namespace android::drm_hwcomposer {
|
||||||
|
|
||||||
class ChangedLayer;
|
class ChangedLayer;
|
||||||
|
class DisplayHotplugConnectModeDetectedAtomReporter;
|
||||||
class DrmHwc;
|
class DrmHwc;
|
||||||
class EdidWrapper;
|
class EdidWrapper;
|
||||||
class FlatteningController;
|
class FlatteningController;
|
||||||
|
|
@ -299,6 +300,8 @@ class HwcDisplay {
|
||||||
return edid_wrapper_;
|
return edid_wrapper_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LogModesOnHotplug();
|
||||||
|
|
||||||
HwcDisplayConfigs configs_;
|
HwcDisplayConfigs configs_;
|
||||||
|
|
||||||
DrmHwc *const hwc_;
|
DrmHwc *const hwc_;
|
||||||
|
|
@ -344,6 +347,9 @@ class HwcDisplay {
|
||||||
HwcDisplay::HdcpState hdcp_state_ = HdcpState::kUndesired;
|
HwcDisplay::HdcpState hdcp_state_ = HdcpState::kUndesired;
|
||||||
|
|
||||||
std::shared_ptr<FrontendDisplayBase> frontend_private_data_;
|
std::shared_ptr<FrontendDisplayBase> frontend_private_data_;
|
||||||
|
|
||||||
|
std::unique_ptr<DisplayHotplugConnectModeDetectedAtomReporter>
|
||||||
|
display_mode_reporter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace android::drm_hwcomposer
|
} // namespace android::drm_hwcomposer
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ src_common = files(
|
||||||
'stats/CompositionStats.cpp',
|
'stats/CompositionStats.cpp',
|
||||||
'stats/CompositionStatsAtomReporter.cpp',
|
'stats/CompositionStatsAtomReporter.cpp',
|
||||||
'stats/CompositionStatsPoller.cpp',
|
'stats/CompositionStatsPoller.cpp',
|
||||||
|
'stats/DisplayHotplugConnectModeDetectedAtomReporter.cpp',
|
||||||
'stats/DisplayRefreshRatesChangedAtomReporter.cpp',
|
'stats/DisplayRefreshRatesChangedAtomReporter.cpp',
|
||||||
'utils/fd.cpp',
|
'utils/fd.cpp',
|
||||||
'utils/LibdisplayEdidWrapper.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