POI: AGL LifeCycle Management
[apps/agl-service-windowmanager.git] / src / pm_wrapper.cpp
1 /*
2  * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
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 "pm_wrapper.hpp"
18 #include "json_helper.hpp"
19 #include "util.hpp"
20
21 namespace wm
22 {
23
24 static PMWrapper *g_context;
25
26 namespace
27 {
28
29 static void onStateTransitioned(json_object *json_out)
30 {
31     g_context->updateStates(json_out);
32 }
33
34 static void onError(json_object *json_out)
35 {
36     HMI_DEBUG("error message from PolicyManager:%s",
37               json_object_get_string(json_out));
38
39     g_context->processError();
40 }
41
42 } // namespace
43
44 PMWrapper::PMWrapper() {}
45
46 int PMWrapper::initialize()
47 {
48     int ret = 0;
49
50     ret = this->pm.initialize();
51     if (0 > ret)
52     {
53         HMI_ERROR("Faild to initialize PolicyManager");
54     }
55
56     g_context = this;
57
58     return ret;
59 }
60
61 void PMWrapper::registerCallback(StateTransitionHandler on_state_transitioned,
62                                  ErrorHandler on_error)
63 {
64     this->on_state_transitioned = on_state_transitioned;
65     this->on_error = on_error;
66
67     PolicyManager::CallbackTable my_callback;
68     my_callback.onStateTransitioned = onStateTransitioned;
69     my_callback.onError = onError;
70     this->pm.registerCallback(my_callback);
71 }
72
73 int PMWrapper::setInputEventData(Task task, std::string role, std::string area)
74 {
75     const char* event;
76     if (Task::TASK_ALLOCATE == task)
77     {
78         event = "activate";
79     }
80     else if (Task::TASK_RELEASE == task)
81     {
82         event = "deactivate";
83     }
84     else
85     {
86         event = "";
87     }
88
89     json_object *json_in = json_object_new_object();
90     json_object_object_add(json_in, "event", json_object_new_string(event));
91     json_object_object_add(json_in, "role", json_object_new_string(role.c_str()));
92     json_object_object_add(json_in, "area", json_object_new_string(area.c_str()));
93
94     int ret;
95     ret = this->pm.setInputEventData(json_in);
96     if (0 > ret)
97     {
98         HMI_ERROR("Faild to set input event data to PolicyManager");
99     }
100     json_object_put(json_in);
101
102     return ret;
103 }
104
105 int PMWrapper::executeStateTransition()
106 {
107     int ret;
108     ret = this->pm.executeStateTransition();
109     if (0 > ret)
110     {
111         HMI_ERROR("Failed to execute state transition for PolicyManager");
112     }
113
114     return ret;
115 }
116
117 void PMWrapper::undoState()
118 {
119     this->pm.undoState();
120
121     this->crrlayer2rolestate = this->prvlayer2rolestate;
122 }
123
124 void PMWrapper::updateStates(json_object *json_out)
125 {
126     std::vector<WMAction> actions;
127
128     HMI_DEBUG("json_out dump:%s", json_object_get_string(json_out));
129
130     this->createLayoutChangeAction(json_out, actions);
131
132     this->on_state_transitioned(actions);
133 }
134
135 void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAction> &actions)
136 {
137     // Get displayed roles from previous layout
138     json_object *json_layers;
139     if (!json_object_object_get_ex(json_out, "layers", &json_layers))
140     {
141         HMI_DEBUG("Not found key \"layers\"");
142         return;
143     }
144
145     int len = json_object_array_length(json_layers);
146     HMI_DEBUG("json_layers len:%d", len);
147
148     for (int i = 0; i < len; i++)
149     {
150         json_object *json_tmp = json_object_array_get_idx(json_layers, i);
151
152         std::string layer_name = jh::getStringFromJson(json_tmp, "name");
153         json_bool changed = jh::getBoolFromJson(json_tmp, "changed");
154         HMI_DEBUG("layer:%s changed:%d", layer_name.c_str(), changed);
155
156         if (changed)
157         {
158             json_object *json_areas;
159             if (!json_object_object_get_ex(json_tmp, "areas", &json_areas))
160             {
161                 HMI_DEBUG("Not found key \"areas\"");
162                 return;
163             }
164
165             int len = json_object_array_length(json_areas);
166             HMI_DEBUG("json_layers len:%d", len);
167
168             // Store previous role state in this layer
169             this->prvlayer2rolestate[layer_name] = this->crrlayer2rolestate[layer_name];
170
171             RoleState crr_roles;
172             RoleState prv_roles = this->prvlayer2rolestate[layer_name];
173             for (int j = 0; j < len; j++)
174             {
175                 json_object *json_tmp2 = json_object_array_get_idx(json_areas, j);
176
177                 std::string area_name = jh::getStringFromJson(json_tmp2, "name");
178                 std::string role_name = jh::getStringFromJson(json_tmp2, "role");
179
180                 crr_roles[role_name] = area_name;
181
182                 auto i_prv = prv_roles.find(role_name);
183                 HMI_DEBUG("current role:%s area:%s",
184                           role_name.c_str(), area_name.c_str());
185
186                 // If current role does not exist in previous
187                 if (prv_roles.end() == i_prv)
188                 {
189                     HMI_DEBUG("current role does not exist in previous");
190
191                     // Set activate action
192                     bool end_draw_finished = false;
193                     WMAction act
194                     {
195                         0,
196                         nullptr,
197                         role_name,
198                         area_name,
199                         TaskVisible::VISIBLE,
200                         end_draw_finished
201                     };
202                     actions.push_back(act);
203                 }
204                 else
205                 {
206                     HMI_DEBUG("previous role:%s area:%s",
207                               i_prv->first.c_str(), i_prv->second.c_str());
208
209                     // If current role exists in previous and area is different with previous
210                     if (area_name != i_prv->second)
211                     {
212                         HMI_DEBUG("current role exists in previous and area is different with previous");
213
214                         // Set activate action
215                         bool end_draw_finished = false;
216                         WMAction act
217                         {
218                             0,
219                             nullptr,
220                             role_name,
221                             area_name,
222                             TaskVisible::VISIBLE,
223                             end_draw_finished
224                         };
225                         actions.push_back(act);
226                     }
227
228                     // Remove role which exist in current list from previous list
229                     prv_roles.erase(i_prv);
230                 }
231             }
232
233             // Deactivate roles which remains in previous list
234             // because these are not displayed in current layout
235             for (auto i_prv : prv_roles)
236             {
237                 HMI_DEBUG("Deactivate role:%s", i_prv.first.c_str());
238
239                 // Set deactivate action
240                 bool end_draw_finished = true;
241                 WMAction act
242                 {
243                     0,
244                     nullptr,
245                     i_prv.first,
246                     "",
247                     TaskVisible::INVISIBLE,
248                     end_draw_finished
249                 };
250                 actions.push_back(act);
251             }
252
253             // Update previous role list
254             this->crrlayer2rolestate[layer_name] = crr_roles;
255         }
256     }
257 }
258
259 void PMWrapper::processError()
260 {
261     this->on_error();
262 }
263
264 } // namespace wm