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 <android-base/file.h>
17
18 #include <stdio.h>
19 #include <string>
20
21 #include "common/libs/utils/json.h"
22 #include "host/commands/cvd/parser/cf_configs_common.h"
23
24 namespace cuttlefish {
25
26 enum class ConfigTemplate {
27 PHONE,
28 TABLET,
29 TV,
30 WEARABLE,
31 AUTO,
32 SLIM,
33 GO,
34 FOLDABLE,
35 UNKNOWN,
36 };
37
38 static std::map<std::string, ConfigTemplate> kSupportedTemplatesKeyMap = {
39 {"phone", ConfigTemplate::PHONE}, {"tablet", ConfigTemplate::TABLET},
40 {"tv", ConfigTemplate::TV}, {"wearable", ConfigTemplate::WEARABLE},
41 {"auto", ConfigTemplate::AUTO}, {"slim", ConfigTemplate::SLIM},
42 {"go", ConfigTemplate::GO}, {"foldable", ConfigTemplate::FOLDABLE}};
43
44 // Definition of phone instance template in Json format
45 static const char* kPhoneInstanceTemplate = R""""(
46 {
47 "vm": {
48 "memory_mb": 4096
49 },
50 "graphics":{
51 "displays":[
52 {
53 "width": 720,
54 "height": 1280,
55 "dpi": 320
56 }
57 ]
58 }
59 }
60 )"""";
61
62 // Definition of tablet instance template in Json format
63 static const char* kTabletInstanceTemplate = R""""(
64 {
65 "vm": {
66 "memory_mb": 4096
67 },
68 "graphics":{
69 "displays":[
70 {
71 "width": 2560,
72 "height": 1800,
73 "dpi": 320
74 }
75 ]
76 }
77 }
78 )"""";
79
80 // Definition of tablet instance template in Json format
81 static const char* kTvInstanceTemplate = R""""(
82 {
83 "vm": {
84 "memory_mb": 2048
85 },
86 "graphics":{
87 "displays":[
88 {
89 "width": 1920,
90 "height": 1080,
91 "dpi": 213
92 }
93 ]
94 }
95 }
96 )"""";
97
98 // Definition of tablet instance template in Json format
99 static const char* kWearableInstanceTemplate = R""""(
100 {
101 "vm": {
102 "memory_mb": 1536,
103 "use_sdcard" : false
104 },
105 "graphics":{
106 "displays":[
107 {
108 "width": 450,
109 "height": 450,
110 "dpi": 320
111 }
112 ]
113 }
114 }
115 )"""";
116
117 // Definition of auto instance template in Json format
118 static const char* kAutoInstanceTemplate = R""""(
119 {
120 "vm": {
121 "memory_mb": 4096
122 },
123 "graphics":{
124 "displays":[
125 {
126 "width": 1080,
127 "height": 600,
128 "dpi": 120
129 },
130 {
131 "width": 400,
132 "height": 600,
133 "dpi": 120
134 }
135 ]
136 }
137 }
138 )"""";
139
140 // Definition of auto instance template in Json format
141 static const char* kSlimInstanceTemplate = R""""(
142 {
143 "vm": {
144 "memory_mb": 2048,
145 "use_sdcard" : false
146 },
147 "graphics":{
148 "displays":[
149 {
150 "width": 720,
151 "height": 1280,
152 "dpi": 320
153 }
154 ]
155 }
156 }
157 )"""";
158
159 // Definition of go instance template in Json format
160 static const char* kGoInstanceTemplate = R""""(
161 {
162 "vm": {
163 "memory_mb": 2048
164 },
165 "graphics":{
166 "displays":[
167 {
168 "width": 720,
169 "height": 1280,
170 "dpi": 320
171 }
172 ]
173 }
174 }
175 )"""";
176
177 static const char* kFoldableInstanceTemplate = R""""(
178 {
179 "vm": {
180 "memory_mb": 4096,
181 "custom_actions" : [
182 {
183 "device_states": [
184 {
185 "lid_switch_open": false,
186 "hinge_angle_value": 0
187 }
188 ],
189 "button":{
190 "command":"device_state_closed",
191 "title":"Device State Closed",
192 "icon_name":"smartphone"
193 }
194 },
195 {
196 "device_states": [
197 {
198 "lid_switch_open": true,
199 "hinge_angle_value": 90
200 }
201 ],
202 "button":{
203 "command":"device_state_half_opened",
204 "title":"Device State Half-Opened",
205 "icon_name":"laptop"
206 }
207 },
208 {
209 "device_states": [
210 {
211 "lid_switch_open": true,
212 "hinge_angle_value": 180
213 }
214 ],
215 "button":{
216 "command":"device_state_opened",
217 "title":"Device State Opened",
218 "icon_name":"tablet"
219 }
220 }
221 ]
222 },
223 "graphics":{
224 "displays":[
225 {
226 "width": 1768,
227 "height": 2208,
228 "dpi": 374
229 },
230 {
231 "width": 832,
232 "height": 2268,
233 "dpi": 387
234 }
235 ]
236 }
237 }
238 )"""";
239
ExtractJsonTemplate(const Json::Value & instance,const char * template_string)240 Json::Value ExtractJsonTemplate(const Json::Value& instance,
241 const char* template_string) {
242 std::string json_text(template_string);
243 Json::Value result;
244
245 Json::Reader reader;
246 reader.parse(json_text, result);
247 MergeTwoJsonObjs(result, instance);
248 return result;
249 }
250
ExtractInstaneTemplate(const Json::Value & instance)251 Json::Value ExtractInstaneTemplate(const Json::Value& instance) {
252 std::string instance_template = instance["@import"].asString();
253 ConfigTemplate selected_template =
254 kSupportedTemplatesKeyMap.at(instance_template);
255
256 Json::Value result;
257
258 switch (selected_template) {
259 case ConfigTemplate::PHONE:
260 // Extract phone instance configs from input template
261 result = ExtractJsonTemplate(instance, kPhoneInstanceTemplate);
262 break;
263 case ConfigTemplate::TABLET:
264 // Extract tablet instance configs from input template
265 result = ExtractJsonTemplate(instance, kTabletInstanceTemplate);
266 break;
267 case ConfigTemplate::TV:
268 // Extract tv instance configs from input template
269 result = ExtractJsonTemplate(instance, kTvInstanceTemplate);
270 break;
271 case ConfigTemplate::WEARABLE:
272 // Extract wearable instance configs from input template
273 result = ExtractJsonTemplate(instance, kWearableInstanceTemplate);
274 break;
275 case ConfigTemplate::AUTO:
276 // Extract auto instance configs from input template
277 result = ExtractJsonTemplate(instance, kAutoInstanceTemplate);
278 break;
279 case ConfigTemplate::SLIM:
280 // Extract slim instance configs from input template
281 result = ExtractJsonTemplate(instance, kSlimInstanceTemplate);
282 break;
283 case ConfigTemplate::GO:
284 // Extract go instance configs from input template
285 result = ExtractJsonTemplate(instance, kGoInstanceTemplate);
286 break;
287 case ConfigTemplate::FOLDABLE:
288 // Extract foldable instance configs from input template
289 result = ExtractJsonTemplate(instance, kFoldableInstanceTemplate);
290 break;
291
292 default:
293 // handle unsupported @import flag values
294 result = instance;
295 break;
296 }
297
298 return result;
299 }
300
ExtractLaunchTemplates(Json::Value & root)301 void ExtractLaunchTemplates(Json::Value& root) {
302 int num_instances = root.size();
303 for (unsigned int i = 0; i < num_instances; i++) {
304 // Validate @import flag values are supported or not
305 if (root[i].isMember("@import")) {
306 // Extract instance configs from input template and override current
307 // instance
308 root[i] = ExtractInstaneTemplate(root[i]);
309 }
310 }
311 }
312
313 } // namespace cuttlefish
314