1
0
Fork 0

Add atom reporting for refresh rate changes

Add DisplayRefreshRatesChangedAtomReporter, which reports the changed
refresh rates of all the active displays managed by drm_hwcomposer.

Change-Id: I03a81c667c44160dc319a899a3bd9a8bc527a382
This commit is contained in:
Su Hong Koo 2025-11-07 12:24:52 -05:00
parent 5a9cc2cba3
commit 680790982c
9 changed files with 176 additions and 1 deletions

View file

@ -103,6 +103,7 @@ SKIP_FILES := \
drm/DrmDisplayPipelineTest.cpp \
stats/CompositionStatsTest.cpp \
stats/CompositionStatsAtomReporterDesktop.cpp \
stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp \
BUILD_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/test_include/*' -path '*.cpp')
SKIP_FILES_path := $(foreach file,$(SKIP_FILES),$(SRC_DIR)/$(file))

View file

@ -345,6 +345,7 @@ drm_hwcomposer_atom_reporter_library {
srcs: [
"compositor/FlatteningEventAtomReporterDesktop.cpp",
"stats/CompositionStatsAtomReporterDesktop.cpp",
"stats/DisplayRefreshRatesChangedAtomReporterDesktop.cpp",
],
shared_libs: [
"android.frameworks.stats-V2-ndk",
@ -356,6 +357,7 @@ drm_hwcomposer_atom_reporter_library {
srcs: [
"compositor/FlatteningEventAtomReporter.cpp",
"stats/CompositionStatsAtomReporter.cpp",
"stats/DisplayRefreshRatesChangedAtomReporter.cpp",
],
},
},

View file

@ -72,7 +72,11 @@ std::string DumpDisplayStats(const HwcDisplay *display,
}
} // namespace
DrmHwc::DrmHwc() : resource_manager_(this), dump_stats_tracker_(this) {};
DrmHwc::DrmHwc()
: resource_manager_(this),
dump_stats_tracker_(this),
refresh_rates_reporter_(
DisplayRefreshRatesChangedAtomReporter::Create()) {};
/* Must be called after every display attach/detach cycle */
void DrmHwc::FinalizeDisplayBinding() {
@ -274,4 +278,18 @@ void DrmHwc::DeinitDisplays() {
}
}
void DrmHwc::LogRefreshRateChanges() {
std::vector<int32_t> refresh_rates;
refresh_rates.reserve(displays_.size());
for (const auto &[_, display] : displays_) {
if (const HwcDisplayConfig *config = display->GetCurrentConfig(); config) {
refresh_rates.push_back(
static_cast<int32_t>(lround(config->mode.GetVRefresh())));
}
}
if (refresh_rates_reporter_)
refresh_rates_reporter_->UpdateRefreshRates(refresh_rates);
}
} // namespace android::drm_hwcomposer

View file

@ -19,6 +19,7 @@
#include "drm/ResourceManager.h"
#include "hwc/HwcDisplay.h"
#include "stats/CompositionStats.h"
#include "stats/DisplayRefreshRatesChangedAtomReporter.h"
namespace android::drm_hwcomposer {
@ -85,6 +86,9 @@ class DrmHwc : public PipelineToFrontendBindingInterface,
void NotifyDisplayLinkStatus(
std::shared_ptr<DrmDisplayPipeline> pipeline) override;
// Should be done for all successful modesets (full and seamless).
void LogRefreshRateChanges();
protected:
auto &Displays() {
return displays_;
@ -100,6 +104,9 @@ class DrmHwc : public PipelineToFrontendBindingInterface,
DisplayHandle last_display_handle_ = kPrimaryDisplay;
CompositionStatsTracker dump_stats_tracker_;
std::unique_ptr<DisplayRefreshRatesChangedAtomReporter>
refresh_rates_reporter_;
};
} // namespace android::drm_hwcomposer

View file

@ -1318,6 +1318,7 @@ ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
return ToBinderStatus(hwc3::Error::kBadConfig);
#endif
case HwcDisplay::ConfigError::kNone:
hwc_->LogRefreshRateChanges();
return ndk::ScopedAStatus::ok();
}
}

View file

@ -24,6 +24,7 @@ src_common = files(
'stats/CompositionStats.cpp',
'stats/CompositionStatsAtomReporter.cpp',
'stats/CompositionStatsPoller.cpp',
'stats/DisplayRefreshRatesChangedAtomReporter.cpp',
'utils/fd.cpp',
'utils/LibdisplayEdidWrapper.cpp',
'utils/properties.cpp',

View 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 "DisplayRefreshRatesChangedAtomReporter.h"
#include "utils/log.h"
namespace android::drm_hwcomposer {
std::unique_ptr<DisplayRefreshRatesChangedAtomReporter>
DisplayRefreshRatesChangedAtomReporter::Create() {
ALOGI("Atom reporting is not enabled.");
return {};
}
} // namespace android::drm_hwcomposer

View 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.
*/
#pragma once
#include <memory>
#include <vector>
namespace android::drm_hwcomposer {
class DisplayRefreshRatesChangedAtomReporter {
public:
static std::unique_ptr<DisplayRefreshRatesChangedAtomReporter> Create();
virtual void UpdateRefreshRates(std::vector<int32_t> refresh_rates) = 0;
virtual ~DisplayRefreshRatesChangedAtomReporter() = default;
};
} // namespace android::drm_hwcomposer

View file

@ -0,0 +1,83 @@
/*
* 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 "DisplayRefreshRatesChangedAtomReporter.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 {
const std::string kStatsServiceName = std::string(IStats::descriptor)
.append("/default");
// Use a private implementation of DisplayRefreshRatesChangedAtomReporter to
// avoid leaking the IStats interface through the public api.
class DisplayRefreshRatesChangedAtomReporterDesktop
: public DisplayRefreshRatesChangedAtomReporter {
public:
void UpdateRefreshRates(std::vector<int32_t> refresh_rates) override {
if (refresh_rates == last_refresh_rates_) {
return;
}
last_refresh_rates_ = refresh_rates;
// 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_REFRESH_RATES_CHANGED,
deprecated_reverse_domain_name, refresh_rates);
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);
}
}
private:
std::vector<int32_t> last_refresh_rates_;
};
} // namespace
std::unique_ptr<DisplayRefreshRatesChangedAtomReporter>
DisplayRefreshRatesChangedAtomReporter::Create() {
if (!AServiceManager_isDeclared(kStatsServiceName.c_str())) {
ALOGW("Stats service is not declared.");
return nullptr;
}
return std::make_unique<DisplayRefreshRatesChangedAtomReporterDesktop>();
}
} // namespace android::drm_hwcomposer