// // Copyright (C) 2023 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 "host/commands/assemble_cvd/display.h" #include "common/libs/utils/flag_parser.h" #include "host/libs/config/display.h" namespace cuttlefish { namespace { class DisplaysConfigsImpl : public DisplaysConfigs { public: INJECT(DisplaysConfigsImpl()) {} const std::vector& GetConfigs() const override { return display_configs_; } void SetConfigs(const std::vector& configs) { display_configs_ = configs; } std::string Name() const override { return "DisplaysConfigsImpl"; } private: std::vector display_configs_; }; } // namespace fruit::Component DisplaysConfigsComponent() { return fruit::createComponent() .bind() .addMultibinding(); } namespace { class DisplaysConfigsFlagImpl : public DisplaysConfigsFlag { public: INJECT(DisplaysConfigsFlagImpl(DisplaysConfigs& configs, ConfigFlag& config_flag)) : display_configs_(configs), config_flag_dependency_(config_flag) {} std::string Name() const override { return "DisplaysConfigsFlagImpl"; } std::unordered_set Dependencies() const override { return {static_cast(&config_flag_dependency_)}; } Result Process(std::vector& args) override { display_configs_.SetConfigs(CF_EXPECT(ParseDisplayConfigsFromArgs(args))); return {}; } bool WriteGflagsCompatHelpXml(std::ostream& out) const override { Flag display_flag = GflagsCompatFlag(kDisplayFlag).Help(kDisplayHelp); return WriteGflagsCompatXml({display_flag}, out); } private: DisplaysConfigs& display_configs_; ConfigFlag& config_flag_dependency_; }; } // namespace fruit::Component, DisplaysConfigsFlag> DisplaysConfigsFlagComponent() { return fruit::createComponent() .bind() .addMultibinding(); } namespace { class DisplaysConfigsFragmentImpl : public DisplaysConfigsFragment { public: INJECT(DisplaysConfigsFragmentImpl(DisplaysConfigs& displays_configs)) : displays_configs_(displays_configs) {} std::string Name() const override { return "DisplaysConfigsFragmentImpl"; } Json::Value Serialize() const override { Json::Value display_configs_json(Json::arrayValue); for (const auto& display_configs : displays_configs_.GetConfigs()) { Json::Value display_config_json(Json::objectValue); display_config_json[kXRes] = display_configs.width; display_config_json[kYRes] = display_configs.height; display_config_json[kDpi] = display_configs.dpi; display_config_json[kRefreshRateHz] = display_configs.refresh_rate_hz; display_configs_json.append(display_config_json); } return display_configs_json; } bool Deserialize(const Json::Value& json) override { if (!json.isMember(kDisplayConfigs)) { LOG(ERROR) << "Invalid value for " << kDisplayConfigs; return false; } const Json::Value& displays_configs_json = json[kDisplayConfigs]; std::vector displays_configs; for (auto& display_config_json : displays_configs_json) { CuttlefishConfig::DisplayConfig display_config = {}; display_config.width = display_config_json[kXRes].asInt(); display_config.height = display_config_json[kYRes].asInt(); display_config.dpi = display_config_json[kDpi].asInt(); display_config.refresh_rate_hz = display_config_json[kRefreshRateHz].asInt(); displays_configs.emplace_back(display_config); } displays_configs_.SetConfigs(displays_configs); return true; } private: static constexpr char kDisplayConfigs[] = "display_configs"; static constexpr char kXRes[] = "x_res"; static constexpr char kYRes[] = "y_res"; static constexpr char kDpi[] = "dpi"; static constexpr char kRefreshRateHz[] = "refresh_rate_hz"; DisplaysConfigs& displays_configs_; }; } // namespace fruit::Component, DisplaysConfigsFragment> DisplaysConfigsFragmentComponent() { return fruit::createComponent() .bind() .addMultibinding(); } } // namespace cuttlefish