1 //
2 // Copyright (C) 2023 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "host/commands/assemble_cvd/display.h"
17 
18 #include "common/libs/utils/flag_parser.h"
19 #include "host/libs/config/display.h"
20 
21 namespace cuttlefish {
22 namespace {
23 
24 class DisplaysConfigsImpl : public DisplaysConfigs {
25  public:
INJECT(DisplaysConfigsImpl ())26   INJECT(DisplaysConfigsImpl()) {}
27 
GetConfigs() const28   const std::vector<CuttlefishConfig::DisplayConfig>& GetConfigs()
29       const override {
30     return display_configs_;
31   }
32 
SetConfigs(const std::vector<CuttlefishConfig::DisplayConfig> & configs)33   void SetConfigs(const std::vector<CuttlefishConfig::DisplayConfig>& configs) {
34     display_configs_ = configs;
35   }
36 
Name() const37   std::string Name() const override { return "DisplaysConfigsImpl"; }
38 
39  private:
40   std::vector<CuttlefishConfig::DisplayConfig> display_configs_;
41 };
42 
43 }  // namespace
44 
DisplaysConfigsComponent()45 fruit::Component<DisplaysConfigs> DisplaysConfigsComponent() {
46   return fruit::createComponent()
47       .bind<DisplaysConfigs, DisplaysConfigsImpl>()
48       .addMultibinding<DisplaysConfigs, DisplaysConfigs>();
49 }
50 
51 namespace {
52 
53 class DisplaysConfigsFlagImpl : public DisplaysConfigsFlag {
54  public:
INJECT(DisplaysConfigsFlagImpl (DisplaysConfigs & configs,ConfigFlag & config_flag))55   INJECT(DisplaysConfigsFlagImpl(DisplaysConfigs& configs,
56                                  ConfigFlag& config_flag))
57       : display_configs_(configs), config_flag_dependency_(config_flag) {}
58 
Name() const59   std::string Name() const override { return "DisplaysConfigsFlagImpl"; }
60 
Dependencies() const61   std::unordered_set<FlagFeature*> Dependencies() const override {
62     return {static_cast<FlagFeature*>(&config_flag_dependency_)};
63   }
64 
Process(std::vector<std::string> & args)65   Result<void> Process(std::vector<std::string>& args) override {
66     display_configs_.SetConfigs(CF_EXPECT(ParseDisplayConfigsFromArgs(args)));
67     return {};
68   }
69 
WriteGflagsCompatHelpXml(std::ostream & out) const70   bool WriteGflagsCompatHelpXml(std::ostream& out) const override {
71     Flag display_flag = GflagsCompatFlag(kDisplayFlag).Help(kDisplayHelp);
72     return WriteGflagsCompatXml({display_flag}, out);
73   }
74 
75  private:
76   DisplaysConfigs& display_configs_;
77   ConfigFlag& config_flag_dependency_;
78 };
79 
80 }  // namespace
81 
82 fruit::Component<fruit::Required<DisplaysConfigs, ConfigFlag>,
83                  DisplaysConfigsFlag>
DisplaysConfigsFlagComponent()84 DisplaysConfigsFlagComponent() {
85   return fruit::createComponent()
86       .bind<DisplaysConfigsFlag, DisplaysConfigsFlagImpl>()
87       .addMultibinding<FlagFeature, DisplaysConfigsFlag>();
88 }
89 
90 namespace {
91 
92 class DisplaysConfigsFragmentImpl : public DisplaysConfigsFragment {
93  public:
INJECT(DisplaysConfigsFragmentImpl (DisplaysConfigs & displays_configs))94   INJECT(DisplaysConfigsFragmentImpl(DisplaysConfigs& displays_configs))
95       : displays_configs_(displays_configs) {}
96 
Name() const97   std::string Name() const override { return "DisplaysConfigsFragmentImpl"; }
98 
Serialize() const99   Json::Value Serialize() const override {
100     Json::Value display_configs_json(Json::arrayValue);
101     for (const auto& display_configs : displays_configs_.GetConfigs()) {
102       Json::Value display_config_json(Json::objectValue);
103       display_config_json[kXRes] = display_configs.width;
104       display_config_json[kYRes] = display_configs.height;
105       display_config_json[kDpi] = display_configs.dpi;
106       display_config_json[kRefreshRateHz] = display_configs.refresh_rate_hz;
107       display_configs_json.append(display_config_json);
108     }
109     return display_configs_json;
110   }
111 
Deserialize(const Json::Value & json)112   bool Deserialize(const Json::Value& json) override {
113     if (!json.isMember(kDisplayConfigs)) {
114       LOG(ERROR) << "Invalid value for " << kDisplayConfigs;
115       return false;
116     }
117 
118     const Json::Value& displays_configs_json = json[kDisplayConfigs];
119 
120     std::vector<CuttlefishConfig::DisplayConfig> displays_configs;
121     for (auto& display_config_json : displays_configs_json) {
122       CuttlefishConfig::DisplayConfig display_config = {};
123       display_config.width = display_config_json[kXRes].asInt();
124       display_config.height = display_config_json[kYRes].asInt();
125       display_config.dpi = display_config_json[kDpi].asInt();
126       display_config.refresh_rate_hz =
127           display_config_json[kRefreshRateHz].asInt();
128       displays_configs.emplace_back(display_config);
129     }
130 
131     displays_configs_.SetConfigs(displays_configs);
132     return true;
133   }
134 
135  private:
136   static constexpr char kDisplayConfigs[] = "display_configs";
137   static constexpr char kXRes[] = "x_res";
138   static constexpr char kYRes[] = "y_res";
139   static constexpr char kDpi[] = "dpi";
140   static constexpr char kRefreshRateHz[] = "refresh_rate_hz";
141 
142   DisplaysConfigs& displays_configs_;
143 };
144 
145 }  // namespace
146 
147 fruit::Component<fruit::Required<DisplaysConfigs>, DisplaysConfigsFragment>
DisplaysConfigsFragmentComponent()148 DisplaysConfigsFragmentComponent() {
149   return fruit::createComponent()
150       .bind<DisplaysConfigsFragment, DisplaysConfigsFragmentImpl>()
151       .addMultibinding<ConfigFragment, DisplaysConfigsFragment>();
152 }
153 
154 }  // namespace cuttlefish
155