Remove service surface in WMClient if service surface vanishes
[apps/agl-service-windowmanager.git] / src / wm_client.cpp
1 /*
2  * Copyright (c) 2017 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 <json-c/json.h>
18 #include "wm_client.hpp"
19 #include "util.hpp"
20 #include <ilm/ilm_control.h>
21 #include <uuid/uuid.h>
22
23
24 #define INVALID_SURFACE_ID 0
25
26 using std::string;
27 using std::vector;
28
29 namespace wm
30 {
31
32 static const vector<string> kWMEvents = {
33     // Private event for applications
34     "syncDraw", "flushDraw", "visible", "invisible", "active", "inactive", "error"};
35 static const vector<string> kErrorDescription = {
36     "unknown-error"};
37
38 static const char kKeyDrawingName[] = "drawing_name";
39 static const char kKeyrole[] = "role";
40 static const char kKeyError[] = "error";
41 static const char kKeyErrorDesc[] = "kErrorDescription";
42
43 WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const string &role)
44     : id(appid), layer(layer),
45       role2surface(0)
46 {
47     role2surface[role] = surface;
48     for (auto x : kWMEvents)
49     {
50 #if GTEST_ENABLED
51         string ev = x;
52 #else
53         afb_event ev = afb_daemon_make_event(x.c_str());
54 #endif
55         evname2afb_event[x] = ev;
56     }
57 }
58
59 WMClient::WMClient(const string &appid, const string &role)
60     : id(appid),
61       layer(0),
62       role2surface(0),
63       evname2afb_event(0)
64 {
65     role2surface[role] = INVALID_SURFACE_ID;
66     for (auto x : kWMEvents)
67     {
68 #if GTEST_ENABLED
69         string ev = x;
70 #else
71         afb_event ev = afb_daemon_make_event(x.c_str());
72 #endif
73         evname2afb_event[x] = ev;
74     }
75 }
76
77 WMClient::WMClient(const string &appid, unsigned layer, const string &role)
78     : id(appid),
79       layer(layer),
80       main_role(role),
81       role2surface(0),
82       evname2afb_event(0)
83 {
84     role2surface[role] = INVALID_SURFACE_ID;
85     for (auto x : kWMEvents)
86     {
87 #if GTEST_ENABLED
88         string ev = x;
89 #else
90         afb_event ev = afb_daemon_make_event(x.c_str());
91 #endif
92         evname2afb_event[x] = ev;
93     }
94 }
95
96 string WMClient::appID() const
97 {
98     return this->id;
99 }
100
101 string WMClient::role() const
102 {
103     return this->main_role;
104 }
105
106 unsigned WMClient::layerID() const
107 {
108     return this->layer;
109 }
110
111 unsigned WMClient::surfaceID() const
112 {
113     return this->surface;
114 }
115
116 /**
117  * Add surface to the client
118  *
119  * This function add main surface to the client(ivi_layer).
120  *
121  * @param     string[in] role
122  * @return    WMError
123  */
124 WMError WMClient::addSurface(unsigned surface)
125 {
126     this->surface = surface;
127     ilmErrorTypes err = ilm_layerAddSurface(this->layer, surface);
128
129     if(err == ILM_SUCCESS)
130     {
131         err = ilm_commitChanges();
132     }
133     return (err == ILM_SUCCESS) ? WMError::SUCCESS : WMError::FAIL;
134 }
135
136 bool WMClient::removeSurfaceIfExist(unsigned surface)
137 {
138     bool ret = false;
139     if(surface == this->surface)
140     {
141         this->surface = INVALID_SURFACE_ID;
142         ret = true;
143     }
144     else
145     {
146         for(auto &x : this->service2surfaces)
147         {
148             if(x.second = surface)
149             {
150                 ret = true;
151                 string key = x.first;
152                 this->service2surfaces.erase(key);
153                 this->service2supplier.erase(key);
154             }
155         }
156     }
157     return ret;
158 }
159
160 WMError WMClient::setRenderOrder(const vector<string> &order)
161 {
162     WMError ret = WMError::SUCCESS;
163     this->surface_render_order.clear();
164     for(const auto& x : order)
165     {
166         unsigned s; // surface
167         if(x == this->role())
168         {
169             s = this->surfaceID();
170         }
171         else if(this->service2surfaces.count(x) != 0)
172         {
173             s = this->service2surfaces[x];
174         }
175         else
176         {
177             ret = WMError::NOT_REGISTERED;
178             break;
179         }
180         this->surface_render_order.push_back(s);
181     }
182     if(ret == WMError::SUCCESS)
183     {
184         int count = 0;
185         t_ilm_layer* id_array = new t_ilm_surface[this->surface_render_order.size()];
186         if(id_array == nullptr)
187         {
188             HMI_WARNING("short memory");
189             ret = WMError::FAIL;
190         }
191         else
192         {
193             for(const auto& i : this->surface_render_order)
194             {
195                 id_array[count] = i;
196                 ++count;
197             }
198             ilm_layerSetRenderOrder(this->layerID(),
199                 id_array, this->surface_render_order.size());
200             delete id_array;
201         }
202     }
203     return ret;
204 }
205
206 string WMClient::attachTmpServiceSurface(const string& supplier, const string& service_surface)
207 {
208     string uuid;
209     uuid_t u;
210     char out[37]; // uuid is 36 characters
211     uuid_generate_random(u);
212     uuid_unparse(u, out);
213     uuid = out;
214     this->service2supplier.emplace(service_surface, supplier);
215     return uuid;
216 }
217
218 WMError WMClient::attachServiceSurface(const string& service_surface, unsigned surface)
219 {
220     WMError ret = WMError::NOT_REGISTERED;
221     if(this->service2supplier.count(service_surface) != 0)
222     {
223         this->service2surfaces.emplace(service_surface, surface);
224         ret = WMError::SUCCESS;
225     }
226     return ret;
227 }
228
229 #if GTEST_ENABLED
230 bool WMClient::subscribe(afb_req req, const string &evname)
231 {
232     if(evname != kKeyError){
233         HMI_DEBUG("error is only enabeled for now");
234         return false;
235     }
236     int ret = afb_req_subscribe(req, this->evname2afb_event[evname]);
237     if (ret)
238     {
239         HMI_DEBUG("Failed to subscribe %s", evname.c_str());
240         return false;
241     }
242     return true;
243 }
244
245 void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev)
246 {
247     if (!afb_event_is_valid(this->evname2afb_event[kKeyError])){
248         HMI_ERROR("event err is not valid");
249         return;
250     }
251     json_object *j = json_object_new_object();
252     json_object_object_add(j, kKeyError, json_object_new_int(ev));
253     json_object_object_add(j, kKeyErrorDesc, json_object_new_string(kErrorDescription[ev].c_str()));
254     HMI_DEBUG("error: %d, description:%s", ev, kErrorDescription[ev].c_str());
255
256     int ret = afb_event_push(this->evname2afb_event[kKeyError], j);
257     if (ret != 0)
258     {
259         HMI_DEBUG("afb_event_push failed: %m");
260     }
261 }
262 #endif
263
264 void WMClient::dumpInfo()
265 {
266     DUMP("APPID : %s", id.c_str());
267     DUMP("  LAYER : %d", layer);
268     DUMP("  ROLE  : %s , SURFACE : %d", main_role.c_str(), surface);
269 }
270
271 } // namespace wm