Move function definition to aul header
[platform/core/appfw/aul-1.git] / src / app_group.cc
1 /*
2  * Copyright (c) 2015 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
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 "include/aul_app_group.h"
18
19 #include <bundle_cpp.h>
20
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include "app_request.h"
26 #include "aul_api.h"
27 #include "aul_util.h"
28 #include "include/aul.h"
29 #include "include/aul_error.h"
30 #include "include/aul_sock.h"
31 #include "launch.h"
32
33 #include "aul/app_group/app_group_info.hh"
34 #include "aul/common/exception.hh"
35
36 using namespace aul;
37 using namespace aul::internal;
38
39 struct aul_app_group_info_s {
40   void* dummy;
41 };
42
43 namespace {
44
45 constexpr const int kMaxPacketLength = AUL_SOCK_MAXBUFF - AUL_PKT_HEADER_SIZE;
46
47 AppGroupInfo* CreateAppGroupInfo(const tizen_base::Bundle& b) {
48   return  AppGroupInfo::Builder()
49       .SetId(b)
50       .SetPid(b)
51       .SetAppId(b)
52       .SetPkgId(b)
53       .SetWid(b)
54       .SetFg(b)
55       .SetStatus(b);
56 }
57
58 std::vector<std::shared_ptr<AppGroupInfo>> ReceiveAppGroupInfos(int fd) {
59   std::vector<std::shared_ptr<AppGroupInfo>> infos;
60   int ret = aul_sock_recv_pkt_with_cb(fd,
61       [](app_pkt_t* pkt, void* user_data) {
62         if (pkt->cmd == APP_GET_INFO_ERROR || !(pkt->opt & AUL_SOCK_BUNDLE))
63           return;
64
65         bundle* kb = bundle_decode(pkt->data, pkt->len);
66         if (kb == nullptr) {
67           _E("bundle_decode() is failed");
68           return;
69         }
70
71         tizen_base::Bundle b(kb, false, true);
72         try {
73           auto* info = CreateAppGroupInfo(b);
74           if (info == nullptr) {
75             _E("Out of memory");
76             return;
77           }
78
79           auto* info_array =
80               static_cast<std::vector<std::shared_ptr<AppGroupInfo>>*>(
81                   user_data);
82           info_array->emplace_back(info);
83         } catch (const Exception& e) {
84           _E("Exception occurs. error(%s)", e.what());
85         }
86       }, &infos);
87   if (ret < 0)
88     THROW(aul_error_convert(ret));
89
90   return infos;
91 }
92
93 std::vector<std::string> ReceiveLeaderIds(int fd) {
94   app_pkt_t* pkt = nullptr;
95   int ret = aul_sock_recv_reply_pkt(fd, &pkt);
96   if (ret < 0 || pkt == nullptr)
97     THROW(AUL_R_ERROR);
98
99   auto pkt_auto = std::unique_ptr<app_pkt_t, decltype(std::free)*>(
100       pkt, std::free);
101
102   bundle* kb = bundle_decode(pkt->data, pkt->len);
103   if (kb == nullptr) {
104     _E("bundle_decode() is failed. data(%s:%d)", pkt->data, pkt->len);
105     THROW(AUL_R_ERROR);
106   }
107
108   tizen_base::Bundle b(kb, false, true);
109   return b.GetStringArray(AUL_K_LEADER_IDS);
110 }
111
112 void ReceivePids(int fd, int* cnt, int** pids) {
113   app_pkt_t* pkt = nullptr;
114   int ret = aul_sock_recv_reply_pkt(fd, &pkt);
115   if (ret < 0 || pkt == nullptr)
116     THROW(AUL_R_ERROR);
117
118   auto pkt_auto = std::unique_ptr<app_pkt_t, decltype(std::free)*>(
119       pkt, std::free);
120
121   int count = pkt->len / sizeof(int);
122   if (count > 0 && pkt->len <= kMaxPacketLength) {
123     *pids = reinterpret_cast<int*>(calloc(1, pkt->len));
124     if (*pids == nullptr) {
125       _E("Out of memory");
126       THROW(AUL_R_ENOMEM);
127     }
128
129     memcpy(*pids, pkt->data, pkt->len);
130     *cnt = count;
131   }
132 }
133
134 }  // namespace
135
136 extern "C" API int aul_app_group_get_window(int pid) {
137   if (pid < 1) {
138     _E("Invalid parameter");
139     return AUL_R_EINVAL;
140   }
141
142   return AppRequest(APP_GROUP_GET_WINDOW, getuid())
143       .SetPid(pid)
144       .SendSimply();
145 }
146
147 extern "C" API int aul_app_group_set_window(int wid) {
148   if (wid < 1) {
149     _E("Invalid parameter");
150     return AUL_R_EINVAL;
151   }
152
153   tizen_base::Bundle b { { AUL_K_WID, std::to_string(wid) } };
154   return AppRequest(APP_GROUP_SET_WINDOW, getuid())
155       .With(std::move(b))
156       .SendSimply(AUL_SOCK_NOREPLY);
157 }
158
159 extern "C" API void aul_app_group_get_leader_pids(int* cnt, int** pids) {
160   if (cnt == nullptr || pids == nullptr) {
161     _E("Invalid parameter");
162     return;
163   }
164
165   *cnt = 0;
166   *pids = nullptr;
167
168   int fd = AppRequest(APP_GROUP_GET_LEADER_PIDS, getuid())
169       .SendCmdOnly(AUL_SOCK_ASYNC);
170   if (fd < 0)
171     return;
172
173   try {
174     ReceivePids(fd, cnt, pids);
175   } catch (const Exception& e) {
176     _E("Exception occurs. error(%s)", e.what());
177   }
178 }
179
180 extern "C" API void aul_app_group_get_group_pids(int leader_pid, int* cnt,
181     int** pids) {
182   if (leader_pid < 1 || cnt == nullptr || pids == nullptr) {
183     _E("Invalid parameter");
184     return;
185   }
186
187   *cnt = 0;
188   *pids = nullptr;
189
190   tizen_base::Bundle b { { AUL_K_LEADER_PID, std::to_string(leader_pid) } };
191   int fd = AppRequest(APP_GROUP_GET_GROUP_PIDS, getuid())
192       .With(std::move(b))
193       .SendSimply(AUL_SOCK_ASYNC);
194   if (fd < 0)
195     return;
196
197   try {
198     ReceivePids(fd, cnt, pids);
199   } catch (const Exception& e) {
200     _E("Exception occurs. error(%s)", e.what());
201   }
202 }
203
204 extern "C" API int aul_app_group_get_leader_pid(int pid) {
205   if (pid < 1) {
206     _E("Invalid parameter");
207     return AUL_R_EINVAL;
208   }
209
210   return AppRequest(APP_GROUP_GET_LEADER_PID, getuid())
211       .SetPid(pid)
212       .SendSimply();
213 }
214
215 extern "C" API int aul_app_group_clear_top(void) {
216   return AppRequest(APP_GROUP_CLEAR_TOP, getuid())
217       .SendCmdOnly();
218 }
219
220 extern "C" API int aul_app_group_is_top(void) {
221   int leader_pid = aul_app_group_get_leader_pid(getpid());
222   if (leader_pid < 1)
223     return 1;
224
225   int cnt = 0;
226   int* pids = nullptr;
227   aul_app_group_get_group_pids(leader_pid, &cnt, &pids);
228   auto pids_auto = std::unique_ptr<int, decltype(std::free)*>(pids, std::free);
229   if (cnt > 0 && pids != nullptr) {
230     if (pids[cnt - 1] == getpid())
231       return 1;
232
233     return 0;
234   }
235
236   return 1;
237 }
238
239 extern "C" API int aul_app_group_get_fg_flag(int pid) {
240   if (pid < 1) {
241     _E("Invalid parameter");
242     return AUL_R_EINVAL;
243   }
244
245   return AppRequest(APP_GROUP_GET_FG, getuid())
246       .SetPid(pid)
247       .SendSimply();
248 }
249
250 extern "C" API void aul_app_group_lower(int* exit) {
251   if (exit == nullptr) {
252     _E("Invalid parameter");
253     return;
254   }
255
256   int ret = AppRequest(APP_GROUP_LOWER, getuid())
257       .SendCmdOnly();
258   if (ret < 0)
259     return;
260
261   *exit = ret;
262 }
263
264 extern "C" API void aul_app_group_get_idle_pids(int* cnt, int** pids) {
265   if (cnt == nullptr || pids == nullptr) {
266     _E("Invalid parameter");
267     return;
268   }
269
270   *cnt = 0;
271   *pids = nullptr;
272   int fd = AppRequest(APP_GROUP_GET_IDLE_PIDS, getuid())
273       .SendCmdOnly(AUL_SOCK_ASYNC);
274   if (fd < 0)
275     return;
276
277   try {
278     ReceivePids(fd, cnt, pids);
279   } catch (const Exception& e) {
280     _E("Exception occurs. error(%s)", e.what());
281   }
282 }
283
284 extern "C" API int aul_app_group_activate_below(const char* below_appid) {
285   if (below_appid == nullptr) {
286     _E("Invalid parameter");
287     return AUL_R_EINVAL;
288   }
289
290   return AppRequest(APP_GROUP_ACTIVATE_BELOW, getuid())
291       .SetAppId(below_appid)
292       .SendSimply();
293 }
294
295 extern "C" API int aul_app_group_activate_above(const char* above_appid) {
296   if (above_appid == nullptr) {
297     _E("Invalid parameter");
298     return AUL_R_EINVAL;
299   }
300
301   return AppRequest(APP_GROUP_ACTIVATE_ABOVE, getuid())
302       .SetAppId(above_appid)
303       .SendSimply();
304 }
305
306 extern "C" API int aul_app_group_set_window_v2(const char* inst_id, int wid) {
307   if (inst_id == nullptr || wid < 1) {
308     _E("Invalid parameter");
309     return AUL_R_EINVAL;
310   }
311
312   tizen_base::Bundle b {
313     { AUL_K_INSTANCE_ID, inst_id },
314     { AUL_K_WID, std::to_string(wid) }
315   };
316
317   return AppRequest(APP_GROUP_SET_WINDOW_V2, getuid())
318       .With(std::move(b))
319       .SendSimply(AUL_SOCK_NOREPLY);
320 }
321
322 extern "C" API int aul_app_group_lower_v2(const char* inst_id, bool* exit) {
323   if (inst_id == nullptr || exit == nullptr) {
324     _E("Invalid parameter");
325     return AUL_R_EINVAL;
326   }
327
328   int ret = AppRequest(APP_GROUP_LOWER_V2, getuid())
329       .SetInstId(inst_id)
330       .SendSimply();
331   if (ret < 0)
332     return ret;
333
334   *exit = (ret == 0) ? false : true;
335   return AUL_R_OK;
336 }
337
338 extern "C" API int aul_app_group_foreach_leader_ids(
339     aul_app_group_leader_id_cb callback, void* user_data) {
340   if (callback == nullptr) {
341     _E("Invalid parameter");
342     return AUL_R_EINVAL;
343   }
344
345   int fd = AppRequest(APP_GROUP_GET_LEADER_IDS, getuid())
346       .SendCmdOnly(AUL_SOCK_ASYNC);
347   if (fd < 0)
348     return aul_error_convert(fd);
349
350   try {
351     for (auto const& id : ReceiveLeaderIds(fd))
352       callback(id.c_str(), user_data);
353   } catch (const Exception& e) {
354     _E("Exception occurs. error(%s)", e.what());
355     return e.GetErrorCode();
356   }
357
358   return AUL_R_OK;
359 }
360
361 extern "C" API int aul_app_group_foreach_group_info(const char* leader_id,
362     aul_app_group_info_cb callback, void* user_data) {
363   if (leader_id == nullptr || callback == nullptr) {
364     _E("Invalid parameter");
365     return AUL_R_EINVAL;
366   }
367
368   tizen_base::Bundle b { { AUL_K_LEADER_ID, leader_id } };
369   int fd = AppRequest(APP_GROUP_GET_GROUP_INFO, getuid())
370       .With(std::move(b))
371       .SendSimply(AUL_SOCK_ASYNC);
372   if (fd < 0)
373     return aul_error_convert(fd);
374
375   try {
376     for (auto const& info : ReceiveAppGroupInfos(fd))
377       callback(reinterpret_cast<aul_app_group_info_h>(info.get()), user_data);
378   } catch (const Exception& e) {
379     _E("Exception occurs. error(%s)", e.what());
380   }
381
382   return AUL_R_OK;
383 }
384
385 extern "C" API int aul_app_group_foreach_idle_info(
386     aul_app_group_info_cb callback, void* user_data) {
387   if (callback == nullptr) {
388     _E("Invalid parameter");
389     return AUL_R_EINVAL;
390   }
391
392   int fd = AppRequest(APP_GROUP_GET_IDLE_INFO, getuid())
393       .SendCmdOnly(AUL_SOCK_ASYNC);
394   if (fd < 0)
395     return aul_error_convert(fd);
396
397   try {
398     for (auto const& info : ReceiveAppGroupInfos(fd))
399       callback(reinterpret_cast<aul_app_group_info_h>(info.get()), user_data);
400   } catch (const Exception& e) {
401     _E("Exception occurs. error(%s)", e.what());
402   }
403
404   return AUL_R_OK;
405 }
406
407 extern "C" API int aul_app_group_info_get_id(aul_app_group_info_h h,
408     const char** id) {
409   if (h == nullptr || id == nullptr) {
410     _E("Invalid parameter");
411     return AUL_R_EINVAL;
412   }
413
414   auto* info = reinterpret_cast<AppGroupInfo*>(h);
415   *id = info->GetId().c_str();
416   return AUL_R_OK;
417 }
418
419 extern "C" API int aul_app_group_info_get_pid(aul_app_group_info_h h,
420     pid_t* pid) {
421   if (h == nullptr || pid == nullptr) {
422     _E("Invalid parameter");
423     return AUL_R_EINVAL;
424   }
425
426   auto* info = reinterpret_cast<AppGroupInfo*>(h);
427   *pid = info->GetPid();
428   return AUL_R_OK;
429 }
430
431 extern "C" API int aul_app_group_info_get_appid(aul_app_group_info_h h,
432     const char** appid) {
433   if (h == nullptr || appid == nullptr) {
434     _E("Invalid parameter");
435     return AUL_R_EINVAL;
436   }
437
438   auto* info = reinterpret_cast<AppGroupInfo*>(h);
439   *appid = info->GetAppId().c_str();
440   return AUL_R_OK;
441 }
442
443 extern "C" API int aul_app_group_info_get_pkgid(aul_app_group_info_h h,
444     const char** pkgid) {
445   if (h == nullptr || pkgid == nullptr) {
446     _E("Invalid parameter");
447     return AUL_R_EINVAL;
448   }
449
450   auto* info = reinterpret_cast<AppGroupInfo*>(h);
451   *pkgid = info->GetPkgId().c_str();
452   return AUL_R_OK;
453 }
454
455 extern "C" API int aul_app_group_info_get_window(aul_app_group_info_h h,
456     int* wid) {
457   if (h == nullptr || wid == nullptr) {
458     _E("Invalid parameter");
459     return AUL_R_EINVAL;
460   }
461
462   auto* info = reinterpret_cast<AppGroupInfo*>(h);
463   *wid = info->GetWid();
464   return AUL_R_OK;
465 }
466
467 extern "C" API int aul_app_group_info_get_fg_flag(aul_app_group_info_h h,
468     bool* fg_flag) {
469   if (h == nullptr || fg_flag == nullptr) {
470     _E("Invalid parameter");
471     return AUL_R_EINVAL;
472   }
473
474   auto* info = reinterpret_cast<AppGroupInfo*>(h);
475   *fg_flag = info->IsFg();
476   return AUL_R_OK;
477 }
478
479 extern "C" API int aul_app_group_info_get_status(aul_app_group_info_h h,
480     int* status) {
481   if (h == nullptr || status == nullptr) {
482     _E("Invalid parameter");
483     return AUL_R_EINVAL;
484   }
485
486   auto* info = reinterpret_cast<AppGroupInfo*>(h);
487   *status = info->GetStatus();
488   return AUL_R_OK;
489 }
490
491 extern "C" API int aul_app_group_add(int wid) {
492   if (wid < 1) {
493     _E("Invalid parameter");
494     return AUL_R_EINVAL;
495   }
496
497   tizen_base::Bundle b { { AUL_K_WID, std::to_string(wid) } };
498   return AppRequest(APP_GROUP_ADD, getuid())
499       .With(std::move(b))
500       .SendSimply(AUL_SOCK_NOREPLY);
501 }
502
503 extern "C" API int aul_app_group_remove(int wid) {
504   if (wid < 1) {
505     _E("Invalid parameter");
506     return AUL_R_EINVAL;
507   }
508
509   tizen_base::Bundle b { { AUL_K_WID, std::to_string(wid) } };
510   return AppRequest(APP_GROUP_REMOVE, getuid())
511       .With(std::move(b))
512       .SendSimply(AUL_SOCK_NOREPLY);
513 }