• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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/libs/config/custom_actions.h"
17 
18 #include <android-base/logging.h>
19 #include <json/json.h>
20 
21 #include <optional>
22 #include <string>
23 #include <vector>
24 
25 #include "host/libs/config/cuttlefish_config.h"
26 
27 namespace cuttlefish {
28 namespace {
29 
30 const char* kCustomActionShellCommand = "shell_command";
31 const char* kCustomActionServer = "server";
32 const char* kCustomActionDeviceStates = "device_states";
33 const char* kCustomActionDeviceStateLidSwitchOpen = "lid_switch_open";
34 const char* kCustomActionDeviceStateHingeAngleValue = "hinge_angle_value";
35 const char* kCustomActionButton = "button";
36 const char* kCustomActionButtons = "buttons";
37 const char* kCustomActionButtonCommand = "command";
38 const char* kCustomActionButtonTitle = "title";
39 const char* kCustomActionButtonIconName = "icon_name";
40 
41 } //namespace
42 
43 
CustomActionConfig(const Json::Value & dictionary)44 CustomActionConfig::CustomActionConfig(const Json::Value& dictionary) {
45   if (dictionary.isMember(kCustomActionShellCommand) +
46           dictionary.isMember(kCustomActionServer) +
47           dictionary.isMember(kCustomActionDeviceStates) !=
48       1) {
49     LOG(FATAL) << "Custom action must contain exactly one of shell_command, "
50                << "server, or device_states";
51     return;
52   }
53   if (dictionary.isMember(kCustomActionShellCommand)) {
54     // Shell command with one button.
55     Json::Value button_entry = dictionary[kCustomActionButton];
56     buttons = {{button_entry[kCustomActionButtonCommand].asString(),
57                 button_entry[kCustomActionButtonTitle].asString(),
58                 button_entry[kCustomActionButtonIconName].asString()}};
59     shell_command = dictionary[kCustomActionShellCommand].asString();
60   } else if (dictionary.isMember(kCustomActionServer)) {
61     // Action server with possibly multiple buttons.
62     for (const Json::Value& button_entry : dictionary[kCustomActionButtons]) {
63       ControlPanelButton button = {
64           button_entry[kCustomActionButtonCommand].asString(),
65           button_entry[kCustomActionButtonTitle].asString(),
66           button_entry[kCustomActionButtonIconName].asString()};
67       buttons.push_back(button);
68     }
69     server = dictionary[kCustomActionServer].asString();
70   } else if (dictionary.isMember(kCustomActionDeviceStates)) {
71     // Device state(s) with one button.
72     // Each button press cycles to the next state, then repeats to the first.
73     Json::Value button_entry = dictionary[kCustomActionButton];
74     buttons = {{button_entry[kCustomActionButtonCommand].asString(),
75                 button_entry[kCustomActionButtonTitle].asString(),
76                 button_entry[kCustomActionButtonIconName].asString()}};
77     for (const Json::Value& device_state_entry :
78          dictionary[kCustomActionDeviceStates]) {
79       DeviceState state;
80       if (device_state_entry.isMember(kCustomActionDeviceStateLidSwitchOpen)) {
81         state.lid_switch_open =
82             device_state_entry[kCustomActionDeviceStateLidSwitchOpen].asBool();
83       }
84       if (device_state_entry.isMember(
85               kCustomActionDeviceStateHingeAngleValue)) {
86         state.hinge_angle_value =
87             device_state_entry[kCustomActionDeviceStateHingeAngleValue].asInt();
88       }
89       device_states.push_back(state);
90     }
91   } else {
92     LOG(FATAL) << "Unknown custom action type.";
93   }
94 }
95 
ToJson() const96 Json::Value CustomActionConfig::ToJson() const {
97   Json::Value custom_action;
98   if (shell_command) {
99     // Shell command with one button.
100     custom_action[kCustomActionShellCommand] = *shell_command;
101     custom_action[kCustomActionButton] = Json::Value();
102     custom_action[kCustomActionButton][kCustomActionButtonCommand] =
103         buttons[0].command;
104     custom_action[kCustomActionButton][kCustomActionButtonTitle] =
105         buttons[0].title;
106     custom_action[kCustomActionButton][kCustomActionButtonIconName] =
107         buttons[0].icon_name;
108   } else if (server) {
109     // Action server with possibly multiple buttons.
110     custom_action[kCustomActionServer] = *server;
111     custom_action[kCustomActionButtons] = Json::Value(Json::arrayValue);
112     for (const auto& button : buttons) {
113       Json::Value button_entry;
114       button_entry[kCustomActionButtonCommand] = button.command;
115       button_entry[kCustomActionButtonTitle] = button.title;
116       button_entry[kCustomActionButtonIconName] = button.icon_name;
117       custom_action[kCustomActionButtons].append(button_entry);
118     }
119   } else if (!device_states.empty()) {
120     // Device state(s) with one button.
121     custom_action[kCustomActionDeviceStates] = Json::Value(Json::arrayValue);
122     for (const auto& device_state : device_states) {
123       Json::Value device_state_entry;
124       if (device_state.lid_switch_open) {
125         device_state_entry[kCustomActionDeviceStateLidSwitchOpen] =
126             *device_state.lid_switch_open;
127       }
128       if (device_state.hinge_angle_value) {
129         device_state_entry[kCustomActionDeviceStateHingeAngleValue] =
130             *device_state.hinge_angle_value;
131       }
132       custom_action[kCustomActionDeviceStates].append(device_state_entry);
133     }
134     custom_action[kCustomActionButton] = Json::Value();
135     custom_action[kCustomActionButton][kCustomActionButtonCommand] =
136         buttons[0].command;
137     custom_action[kCustomActionButton][kCustomActionButtonTitle] =
138         buttons[0].title;
139     custom_action[kCustomActionButton][kCustomActionButtonIconName] =
140         buttons[0].icon_name;
141   } else {
142     LOG(FATAL) << "Unknown custom action type.";
143   }
144   return custom_action;
145 }
146 
147 }  // namespace cuttlefish
148