diff options
author | 2022-08-30 14:42:01 -0700 | |
---|---|---|
committer | 2022-09-29 18:03:45 -0400 | |
commit | e70461ad2658371bc06adef2307fbdef6e39cca8 (patch) | |
tree | fd51a46cc61c2d0259340e9b884c0f37f361db71 | |
parent | f2fdb56c787297cb92029ac107d407dc8d3f94d3 (diff) |
SF: Add utility class for dumpsys formatting
The Dumper class automates stringifying (a minimal set of types for now)
and indenting.
Bug: 241285876
Test: dumpsys SurfaceFlinger --displays
Change-Id: I5581cd9cb4235e2c710e303b6ab634847554cc30
-rw-r--r-- | libs/ui/DeviceProductInfo.cpp | 49 | ||||
-rw-r--r-- | libs/ui/include/ui/DeviceProductInfo.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Display/DisplaySnapshot.cpp | 17 | ||||
-rw-r--r-- | services/surfaceflinger/Display/DisplaySnapshot.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 13 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/Hal.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp | 40 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateConfigs.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 15 | ||||
-rw-r--r-- | services/surfaceflinger/Utils/Dumper.h | 71 |
11 files changed, 149 insertions, 77 deletions
diff --git a/libs/ui/DeviceProductInfo.cpp b/libs/ui/DeviceProductInfo.cpp index 33060126ff..6ae27dee1d 100644 --- a/libs/ui/DeviceProductInfo.cpp +++ b/libs/ui/DeviceProductInfo.cpp @@ -14,44 +14,43 @@ * limitations under the License. */ +#include <ftl/match.h> #include <ui/DeviceProductInfo.h> #include <android-base/stringprintf.h> -#include <utils/Log.h> - -#define RETURN_IF_ERROR(op) \ - if (const status_t status = (op); status != OK) return status; namespace android { -using base::StringAppendF; - -void DeviceProductInfo::dump(std::string& result) const { - StringAppendF(&result, "{name=\"%s\", ", name.c_str()); - StringAppendF(&result, "manufacturerPnpId=%s, ", manufacturerPnpId.data()); - StringAppendF(&result, "productId=%s, ", productId.c_str()); - - if (const auto* model = std::get_if<ModelYear>(&manufactureOrModelDate)) { - StringAppendF(&result, "modelYear=%u, ", model->year); - } else if (const auto* manufactureWeekAndYear = - std::get_if<ManufactureWeekAndYear>(&manufactureOrModelDate)) { - StringAppendF(&result, "manufactureWeek=%u, ", manufactureWeekAndYear->week); - StringAppendF(&result, "manufactureYear=%d, ", manufactureWeekAndYear->year); - } else if (const auto* manufactureYear = - std::get_if<ManufactureYear>(&manufactureOrModelDate)) { - StringAppendF(&result, "manufactureYear=%d, ", manufactureYear->year); - } else { - ALOGE("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate"); - } +std::string to_string(const DeviceProductInfo& info) { + using base::StringAppendF; + + std::string result; + StringAppendF(&result, "{name=\"%s\", ", info.name.c_str()); + StringAppendF(&result, "manufacturerPnpId=%s, ", info.manufacturerPnpId.data()); + StringAppendF(&result, "productId=%s, ", info.productId.c_str()); + + ftl::match( + info.manufactureOrModelDate, + [&](DeviceProductInfo::ModelYear model) { + StringAppendF(&result, "modelYear=%u, ", model.year); + }, + [&](DeviceProductInfo::ManufactureWeekAndYear manufacture) { + StringAppendF(&result, "manufactureWeek=%u, ", manufacture.week); + StringAppendF(&result, "manufactureYear=%d, ", manufacture.year); + }, + [&](DeviceProductInfo::ManufactureYear manufacture) { + StringAppendF(&result, "manufactureYear=%d, ", manufacture.year); + }); result.append("relativeAddress=["); - for (size_t i = 0; i < relativeAddress.size(); i++) { + for (size_t i = 0; i < info.relativeAddress.size(); i++) { if (i != 0) { result.append(", "); } - StringAppendF(&result, "%u", relativeAddress[i]); + StringAppendF(&result, "%u", info.relativeAddress[i]); } result.append("]}"); + return result; } } // namespace android diff --git a/libs/ui/include/ui/DeviceProductInfo.h b/libs/ui/include/ui/DeviceProductInfo.h index 879e46fbdc..4229cf1507 100644 --- a/libs/ui/include/ui/DeviceProductInfo.h +++ b/libs/ui/include/ui/DeviceProductInfo.h @@ -61,8 +61,8 @@ struct DeviceProductInfo { // address is unavailable. // For example, for HDMI connected device this will be the physical address. std::vector<uint8_t> relativeAddress; - - void dump(std::string& result) const; }; +std::string to_string(const DeviceProductInfo&); + } // namespace android diff --git a/services/surfaceflinger/Display/DisplaySnapshot.cpp b/services/surfaceflinger/Display/DisplaySnapshot.cpp index b4f104a74d..fca3a3de08 100644 --- a/services/surfaceflinger/Display/DisplaySnapshot.cpp +++ b/services/surfaceflinger/Display/DisplaySnapshot.cpp @@ -41,18 +41,11 @@ std::optional<DisplayModeId> DisplaySnapshot::translateModeId(hal::HWConfigId hw .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; - } +void DisplaySnapshot::dump(utils::Dumper& dumper) const { + using namespace std::string_view_literals; + + dumper.dump("connectionType"sv, ftl::enum_string(mConnectionType)); + dumper.dump("deviceProductInfo"sv, mDeviceProductInfo); } } // namespace android::display diff --git a/services/surfaceflinger/Display/DisplaySnapshot.h b/services/surfaceflinger/Display/DisplaySnapshot.h index 0279220b1b..3f34e39d92 100644 --- a/services/surfaceflinger/Display/DisplaySnapshot.h +++ b/services/surfaceflinger/Display/DisplaySnapshot.h @@ -17,12 +17,12 @@ #pragma once #include <optional> -#include <string> #include <ui/DisplayId.h> #include <ui/StaticDisplayInfo.h> -#include "../DisplayHardware/DisplayMode.h" +#include "DisplayHardware/DisplayMode.h" +#include "Utils/Dumper.h" namespace android::display { @@ -43,7 +43,7 @@ public: const auto& displayModes() const { return mDisplayModes; } const auto& deviceProductInfo() const { return mDeviceProductInfo; } - void dump(std::string&) const; + void dump(utils::Dumper&) const; private: const PhysicalDisplayId mDisplayId; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index a25296c86d..eeab0cd78f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -338,17 +338,16 @@ std::string DisplayDevice::getDebugName() const { return name + ", \""s + mDisplayName + "\")"s; } -void DisplayDevice::dump(std::string& result) const { - using namespace std::string_literals; +void DisplayDevice::dump(utils::Dumper& dumper) const { + using namespace std::string_view_literals; - result += getDebugName(); + dumper.dump({}, getDebugName()); - result += "\n powerMode="s; - result += mPowerMode.has_value() ? to_string(mPowerMode.value()) : "OFF(reset)"; - result += '\n'; + utils::Dumper::Indent indent(dumper); + dumper.dump("powerMode"sv, mPowerMode); if (mRefreshRateConfigs) { - mRefreshRateConfigs->dump(result); + mRefreshRateConfigs->dump(dumper); } } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 0f52aff4f3..1de8147547 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -47,6 +47,7 @@ #include "Scheduler/RefreshRateConfigs.h" #include "ThreadContext.h" #include "TracedOrdinal.h" +#include "Utils/Dumper.h" namespace android { @@ -248,7 +249,7 @@ public: * Debugging */ std::string getDebugName() const; - void dump(std::string& result) const; + void dump(utils::Dumper&) const; private: const sp<SurfaceFlinger> mFlinger; diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h index 473703423e..33a7bca038 100644 --- a/services/surfaceflinger/DisplayHardware/Hal.h +++ b/services/surfaceflinger/DisplayHardware/Hal.h @@ -177,6 +177,9 @@ inline std::string to_string(hardware::graphics::composer::hal::Error error) { return to_string(static_cast<hardware::graphics::composer::hal::V2_4::Error>(error)); } +// For utils::Dumper ADL. +namespace hardware::graphics::composer::V2_2 { + inline std::string to_string(hardware::graphics::composer::hal::PowerMode mode) { switch (mode) { case hardware::graphics::composer::hal::PowerMode::OFF: @@ -194,6 +197,8 @@ inline std::string to_string(hardware::graphics::composer::hal::PowerMode mode) } } +} // namespace hardware::graphics::composer::V2_2 + inline std::string to_string(hardware::graphics::composer::hal::Vsync vsync) { switch (vsync) { case hardware::graphics::composer::hal::Vsync::ENABLE: diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 3cb052c4e3..fb505881fc 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -1037,47 +1037,45 @@ bool RefreshRateConfigs::isFractionalPairOrMultiple(Fps smaller, Fps bigger) { isApproxEqual(bigger, Fps::fromValue(smaller.getValue() * multiplier * kCoef)); } -void RefreshRateConfigs::dump(std::string& result) const { - using namespace std::string_literals; +void RefreshRateConfigs::dump(utils::Dumper& dumper) const { + using namespace std::string_view_literals; std::lock_guard lock(mLock); const auto activeModeId = getActiveModeItLocked()->first; - result += " activeModeId="s; - result += std::to_string(activeModeId.value()); - - result += "\n displayModes=\n"s; - for (const auto& [id, mode] : mDisplayModes) { - result += " "s; - result += to_string(*mode); - result += '\n'; + dumper.dump("activeModeId"sv, std::to_string(activeModeId.value())); + + dumper.dump("displayModes"sv); + { + utils::Dumper::Indent indent(dumper); + for (const auto& [id, mode] : mDisplayModes) { + dumper.dump({}, to_string(*mode)); + } } - base::StringAppendF(&result, " displayManagerPolicy=%s\n", - mDisplayManagerPolicy.toString().c_str()); + dumper.dump("displayManagerPolicy"sv, mDisplayManagerPolicy.toString()); if (const Policy& currentPolicy = *getCurrentPolicyLocked(); mOverridePolicy && currentPolicy != mDisplayManagerPolicy) { - base::StringAppendF(&result, " overridePolicy=%s\n", currentPolicy.toString().c_str()); + dumper.dump("overridePolicy"sv, currentPolicy.toString()); } - base::StringAppendF(&result, " supportsFrameRateOverrideByContent=%s\n", - mSupportsFrameRateOverrideByContent ? "true" : "false"); + dumper.dump("supportsFrameRateOverrideByContent"sv, mSupportsFrameRateOverrideByContent); - result += " idleTimer="s; + std::string idleTimer; if (mIdleTimer) { - result += mIdleTimer->dump(); + idleTimer = mIdleTimer->dump(); } else { - result += "off"s; + idleTimer = "off"sv; } if (const auto controller = mConfig.kernelIdleTimerController) { - base::StringAppendF(&result, " (kernel via %s)", ftl::enum_string(*controller).c_str()); + base::StringAppendF(&idleTimer, " (kernel via %s)", ftl::enum_string(*controller).c_str()); } else { - result += " (platform)"s; + idleTimer += " (platform)"sv; } - result += '\n'; + dumper.dump("idleTimer"sv, idleTimer); } std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() { diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 0642fcbd14..8b89104c5c 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -32,6 +32,7 @@ #include "Scheduler/OneShotTimer.h" #include "Scheduler/StrongTyping.h" #include "ThreadContext.h" +#include "Utils/Dumper.h" namespace android::scheduler { @@ -336,7 +337,7 @@ public: mIdleTimer->reset(); } - void dump(std::string& result) const EXCLUDES(mLock); + void dump(utils::Dumper&) const EXCLUDES(mLock); std::chrono::milliseconds getIdleTimerTimeout(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f3551ae080..896eebfce2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -142,6 +142,7 @@ #include "SurfaceInterceptor.h" #include "TimeStats/TimeStats.h" #include "TunnelModeEnabledReporter.h" +#include "Utils/Dumper.h" #include "WindowInfosListenerInvoker.h" #include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h> @@ -5077,18 +5078,22 @@ void SurfaceFlinger::dumpCompositionDisplays(std::string& result) const { } void SurfaceFlinger::dumpDisplays(std::string& result) const { + utils::Dumper dumper{result}; + for (const auto& [id, display] : mPhysicalDisplays) { if (const auto device = getDisplayDeviceLocked(id)) { - device->dump(result); + device->dump(dumper); } - display.snapshot().dump(result); - result += '\n'; + + utils::Dumper::Indent indent(dumper); + display.snapshot().dump(dumper); + dumper.eol(); } for (const auto& [token, display] : mDisplays) { if (display->isVirtual()) { - display->dump(result); - result += '\n'; + display->dump(dumper); + dumper.eol(); } } } diff --git a/services/surfaceflinger/Utils/Dumper.h b/services/surfaceflinger/Utils/Dumper.h new file mode 100644 index 0000000000..3761f9e806 --- /dev/null +++ b/services/surfaceflinger/Utils/Dumper.h @@ -0,0 +1,71 @@ +/* + * 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 <string_view> + +namespace android::utils { + +// Dumps variables by appending their name and value to the output string. A variable is formatted +// as "name=value". If the name or value is empty, the format is "value" or "name=", respectively. +// A value of user-defined type T is stringified via `std::string to_string(const T&)`, which must +// be defined in the same namespace as T per the rules of ADL (argument-dependent lookup). +// +// TODO(b/249828573): Consolidate with <compositionengine/impl/DumpHelpers.h> +class Dumper { +public: + explicit Dumper(std::string& out) : mOut(out) {} + + void eol() { mOut += '\n'; } + + void dump(std::string_view name, std::string_view value = {}) { + using namespace std::string_view_literals; + + for (int i = mIndent; i-- > 0;) mOut += " "sv; + mOut += name; + if (!name.empty()) mOut += '='; + mOut += value; + eol(); + } + + void dump(std::string_view name, bool value) { + using namespace std::string_view_literals; + dump(name, value ? "true"sv : "false"sv); + } + + template <typename T> + void dump(std::string_view name, const std::optional<T>& value) { + using namespace std::string_view_literals; + using std::to_string; + dump(name, value ? to_string(*value) : "nullopt"sv); + } + + struct Indent { + explicit Indent(Dumper& dumper) : dumper(dumper) { dumper.mIndent++; } + ~Indent() { dumper.mIndent--; } + + Dumper& dumper; + }; + +private: + std::string& mOut; + int mIndent = 0; +}; + +} // namespace android::utils |