• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 
17 #include "host/libs/vm_manager/crosvm_display_controller.h"
18 
19 #include <android-base/logging.h>
20 #include <cstddef>
21 #include <iostream>
22 #include <string>
23 #include <vector>
24 #include "common/libs/utils/result.h"
25 #include "common/libs/utils/subprocess.h"
26 #include "host/libs/config/cuttlefish_config.h"
27 
28 namespace cuttlefish {
29 namespace vm_manager {
30 
GetCrosvmDisplayController()31 Result<CrosvmDisplayController> GetCrosvmDisplayController() {
32   auto config = CuttlefishConfig::Get();
33   if (!config) {
34     return CF_ERR("Failed to get Cuttlefish config.");
35   }
36   auto vm_manager = config->vm_manager();
37   if (vm_manager != VmmMode::kCrosvm) {
38     LOG(ERROR) << "Expected vm_manager is kCrosvm but " << vm_manager;
39     return CF_ERR(
40         "CrosvmDisplayController is only available when VmmMode is kCrosvm");
41   }
42   return CrosvmDisplayController(config);
43 }
44 
Add(const int instance_num,const std::vector<CuttlefishConfig::DisplayConfig> & display_configs) const45 Result<int> CrosvmDisplayController::Add(
46     const int instance_num,
47     const std::vector<CuttlefishConfig::DisplayConfig>& display_configs) const {
48   std::vector<std::string> command_args;
49   command_args.push_back("add-displays");
50 
51   for (const auto& display_config : display_configs) {
52     const std::string w = std::to_string(display_config.width);
53     const std::string h = std::to_string(display_config.height);
54     const std::string dpi = std::to_string(display_config.dpi);
55     const std::string rr = std::to_string(display_config.refresh_rate_hz);
56 
57     const std::string add_display_flag =
58         "--gpu-display=" + android::base::Join(
59                                std::vector<std::string>{
60                                    "mode=windowed[" + w + "," + h + "]",
61                                    "dpi=[" + dpi + "," + dpi + "]",
62                                    "refresh-rate=" + rr,
63                                },
64                                ",");
65 
66     command_args.push_back(add_display_flag);
67   }
68 
69   return RunCrosvmDisplayCommand(instance_num, command_args, NULL);
70 }
71 
Remove(const int instance_num,const std::vector<std::string> display_ids) const72 Result<int> CrosvmDisplayController::Remove(
73     const int instance_num, const std::vector<std::string> display_ids) const {
74   std::vector<std::string> command_args;
75   command_args.push_back("remove-displays");
76 
77   for (const auto& display_id : display_ids) {
78     command_args.push_back("--display-id=" + display_id);
79   }
80 
81   return RunCrosvmDisplayCommand(instance_num, command_args, NULL);
82 }
83 
List(const int instance_num)84 Result<std::string> CrosvmDisplayController::List(const int instance_num) {
85   std::string out;
86   CF_EXPECT(RunCrosvmDisplayCommand(instance_num, {"list-displays"}, &out));
87   return out;
88 }
89 
RunCrosvmDisplayCommand(const int instance_num,const std::vector<std::string> & args,std::string * stdout_str) const90 Result<int> CrosvmDisplayController::RunCrosvmDisplayCommand(
91     const int instance_num, const std::vector<std::string>& args,
92     std::string* stdout_str) const {
93   // TODO(b/260649774): Consistent executable API for selecting an instance
94   const CuttlefishConfig::InstanceSpecific instance =
95       config_->ForInstance(instance_num);
96 
97   const std::string crosvm_binary_path = instance.crosvm_binary();
98   const std::string crosvm_control_path = instance.CrosvmSocketPath();
99 
100   Command command(crosvm_binary_path);
101   command.AddParameter("gpu");
102   for (const std::string& arg : args) {
103     command.AddParameter(arg);
104   }
105   command.AddParameter(crosvm_control_path);
106 
107   std::string err;
108   auto ret = RunWithManagedStdio(std::move(command), NULL, stdout_str, &err);
109   if (ret != 0) {
110     LOG(ERROR) << "Failed to run crosvm display command: ret code: " << ret
111                << "\n"
112                << err << std::endl;
113     return CF_ERRF("Failed to run crosvm display command: ret code: {}", ret);
114   }
115 
116   return 0;
117 }
118 
119 }  // namespace vm_manager
120 }  // namespace cuttlefish
121