Fix static analysis issue
[platform/core/appfw/event-system.git] / src / modules / cion / cion_ondemand_server.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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 <glib.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <aul.h>
23 #include <aul_svc.h>
24 #include <bundle_cpp.h>
25 #include <parcel.hh>
26 #include <pkgmgr-info.h>
27 #include <vconf.h>
28 #include <system_info.h>
29 #include <cion/common/data_payload.hh>
30
31 #include <log.hh>
32 #include "cion_ondemand_server.h"
33 #include "cion_peer_info.h"
34 #include "cion_module.hh"
35
36 namespace {
37
38 std::string GetAppVersion(const std::string& appid) {
39   char *pkgid;
40   char *pkg_version = NULL;
41   pkgmgrinfo_appinfo_h appinfo = NULL;
42
43   int retval = pkgmgrinfo_appinfo_get_usr_appinfo(appid.c_str(),
44       getuid(), &appinfo);
45   if (retval != PMINFO_R_OK)
46     return {};
47
48   retval = pkgmgrinfo_appinfo_get_pkgid(appinfo, &pkgid);
49   if (retval != PMINFO_R_OK) {
50     pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
51     return {};
52   }
53
54   pkgmgrinfo_pkginfo_h pkginfo = NULL;
55   retval = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &pkginfo);
56   if (retval != PMINFO_R_OK) {
57     pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
58     return {};
59   }
60
61   retval = pkgmgrinfo_pkginfo_get_version(pkginfo, &pkg_version);
62   if (retval != PMINFO_R_OK) {
63     pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
64     pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
65     return {};
66   }
67
68   std::string version(pkg_version);
69   pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
70   pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
71
72   return version;
73 }
74
75 std::string GetSystemInfoPlatformString(const char* key) {
76     char* val = nullptr;
77   int ret = system_info_get_platform_string(key, &val);
78   if (ret != SYSTEM_INFO_ERROR_NONE || !val)
79     return {};
80
81   std::string val_str = val;
82   free(val);
83
84   return val_str;
85 }
86
87 std::string GetVconfString(const char* key) {
88   char* val = vconf_get_str(key);
89   if (val == nullptr)
90     return {};
91
92   std::string val_str = val;
93   free(val);
94
95   return val_str;
96 }
97
98 std::string device_id = GetSystemInfoPlatformString("http://tizen.org/system/tizenid");
99 std::string device_name = GetVconfString(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
100 std::string device_platform = "Tizen";
101 std::string device_platform_version =
102     GetSystemInfoPlatformString("http://tizen.org/feature/platform.version");
103 std::string device_type = GetSystemInfoPlatformString("http://tizen.org/system/device_type");
104
105 }  // namespace
106
107 CionOndemandServer::CionOndemandServer(std::string service_name,
108     std::string display_name, esd::api::IModule* module)
109     : cion::channel::ServerChannel(service_name, display_name), module_(module) {
110   LoadOndemandServiceList();
111 }
112
113 CionOndemandServer::CionOndemandServer(std::string service_name,
114     std::string display_name, cion::SecurityInfo security) :
115     cion::channel::ServerChannel(service_name, display_name,
116         std::move(security)) {
117   LoadOndemandServiceList();
118 }
119
120 void CionOndemandServer::OnConnectionResult(std::shared_ptr<cion::PeerInfo> info,
121     const cion::ConnectionResult& result) {
122 }
123
124 void CionOndemandServer::OnDisconnected(std::shared_ptr<cion::PeerInfo> peer) {
125 }
126
127 std::vector<char> CionOndemandServer::OnDataReceived(
128     const std::vector<char>& data, std::shared_ptr<cion::PeerInfo> peer) {
129   std::string return_data("returned");
130
131   std::vector<char> v(return_data.begin(), return_data.end());
132   return v;
133 }
134
135 void CionOndemandServer::OnPayloadReceived(std::shared_ptr<cion::IPayload> data,
136     std::shared_ptr<cion::PeerInfo> peer,
137     IPayloadReceiver::PayloadTransferStatus status) {
138 }
139
140 void CionOndemandServer::OnConnectionRequest(
141     std::shared_ptr<cion::PeerInfo> peer) {
142 }
143
144 void CionOndemandServer::OnOndemandListRequested(
145     std::shared_ptr<cion::IPayload> data,
146     std::shared_ptr<cion::PeerInfo> peer) {
147   std::vector<uint8_t> raw;
148
149   _D("[Request Ondemand List]");
150
151   if (data->GetType() == cion::IPayload::PayloadType::File)
152     return;
153
154   std::shared_ptr<cion::DataPayload> data_payload =
155       std::dynamic_pointer_cast<cion::DataPayload>(data);
156   std::vector<char> requested_data = data_payload->GetData();
157   tizen_base::Parcel ondemand_parcel(requested_data.data(),
158       requested_data.size());
159
160   std::string list_header = ondemand_parcel.ReadString();
161   std::string list_service_name = ondemand_parcel.ReadString();
162   _D("Ondemand Service_name : %s", list_service_name.c_str());
163   if (list_header == std::string("OndemandList")) {
164     raw = GetOndemandList(list_service_name).ToRaw();
165     if (raw.size() == 0)
166       return;
167   }
168
169   auto dpl = std::make_unique<cion::DataPayload>();
170   std::vector<char> listdata_vector(raw.begin(), raw.end());
171   dpl->SetData(listdata_vector);
172
173   SendPayloadAsync(dpl.get(), peer, [] (
174       std::shared_ptr<cion::PayloadAsyncResult> result) {
175     _I("result received !!! %s", result->GetPayloadID().c_str());
176   });
177 }
178
179 int CionOndemandServer::OnOndemandLaunchRequested(
180     std::shared_ptr<cion::IPayload> data,
181     std::shared_ptr<cion::PeerInfo> peer) {
182   //TODO check privilege app_id
183   std::string app_id = peer->GetAppID();
184   int ret = -20;
185
186   cion::IPayload::PayloadType type = data->GetType();
187   if (type == cion::IPayload::PayloadType::File)
188     return ret;
189
190   std::shared_ptr<cion::DataPayload> data_payload =
191       std::dynamic_pointer_cast<cion::DataPayload>(data);
192
193   std::vector<char> getdata = data_payload->GetData();
194   std::string launch_requested(getdata.begin(), getdata.end());
195
196   ret = OndemandLaunchApp(launch_requested);
197   if (ret != 0) {
198     _E("Faled to __esd_cion_launch_ondemand : %d", ret);
199   }
200
201   return ret;
202 }
203
204 int CionOndemandServer::OndemandLaunchApp(std::string appid) {
205   uid_t uid = getuid();
206   tizen_base::Bundle b;
207   int ret = -20;
208   bool found = false;
209
210   for (std::shared_ptr<CionPeerInfo> cs : ondemand_peer_list_) {
211     if (cs->GetAppID() == appid) {
212       found = true;
213       break;
214     }
215   }
216
217   if (found == false) {
218     _E("%s is not found", appid.c_str());
219     return ret;
220   }
221
222   _D("cion launch ondemand: app_id(%s)", appid.c_str());
223
224   if (!aul_app_is_running_for_uid(appid.c_str(), uid)) {
225     aul_svc_set_operation(b.GetHandle(), AUL_SVC_OPERATION_DEFAULT);
226     aul_svc_set_appid(b.GetHandle(), appid.c_str());
227
228     ret = aul_svc_run_service_async_for_uid(b.GetHandle(), 0, NULL, NULL, uid);
229     if (ret < 0)
230       _E("Failed to launch app : %s", appid.c_str());
231
232   } else {
233     _D("already is running or launch failed");
234   }
235
236   return ret;
237 }
238
239 void CionOndemandServer::LoadOndemandServiceList() {
240   auto* mod = static_cast<esd::module::CionModule*>(module_);
241   auto ret = mod->GetEnabledServiceList();
242
243   if (!ret)
244     return;
245
246   for (const auto& i : *ret) {
247     std::optional<std::string> uuid;
248     mod->GetUuidWithGenerate(i.GetAppId(), uuid);
249     if (!uuid) {
250       _E("Get uuid for %s", i.GetAppId().c_str());
251     }
252
253     std::string app_version = GetAppVersion(i.GetAppId());
254     tizen_base::Parcel parcel;
255     parcel.WriteString(device_id);
256     parcel.WriteString(device_name);
257     parcel.WriteString(device_platform);
258     parcel.WriteString(device_platform_version);
259     parcel.WriteString(device_type);
260     parcel.WriteString(i.GetAppId());
261     parcel.WriteString(app_version);
262     parcel.WriteString(*uuid);
263     parcel.WriteString(i.GetDisplayName());
264
265     std::shared_ptr<CionPeerInfo> pi =
266         std::make_shared<CionPeerInfo>(i.GetServiceName(),
267         parcel.GetData(), parcel.GetDataSize());
268     ondemand_peer_list_.emplace_back(pi);
269   }
270 }
271
272 void CionOndemandServer::AddOndemandServiceList(std::string service_name,
273     std::string appid, std::string display_name) {
274   for (auto const& peer : ondemand_peer_list_) {
275     if (peer->GetServiceName() == service_name &&
276         peer->GetAppID() == appid) {
277       _W("%s is already exist", appid.c_str());
278       return;
279     }
280   }
281
282   std::optional<std::string> uuid;
283   auto* mod = static_cast<esd::module::CionModule*>(module_);
284   mod->GetUuidWithGenerate(appid, uuid);
285   if (!uuid) {
286     _E("Get uuid for %s", appid.c_str());
287     return;
288   }
289
290   std::string app_version = GetAppVersion(appid);
291
292   tizen_base::Parcel parcel;
293   parcel.WriteString(device_id);
294   parcel.WriteString(device_name);
295   parcel.WriteString(device_platform);
296   parcel.WriteString(device_platform_version);
297   parcel.WriteString(device_type);
298   parcel.WriteString(appid);
299   parcel.WriteString(app_version);
300   parcel.WriteString(*uuid);
301   parcel.WriteString(display_name);
302
303   std::shared_ptr<CionPeerInfo> pi =
304       std::make_shared<CionPeerInfo>(service_name, parcel.GetData(),
305           parcel.GetDataSize());
306   ondemand_peer_list_.emplace_back(pi);
307
308   _D("[%s:%s] is added to list", appid.c_str(), service_name.c_str());
309 }
310
311 void CionOndemandServer::RemoveOndemandServiceList(std::string service_name,
312     std::string appid) {
313   for (auto peer = ondemand_peer_list_.begin();
314        peer != ondemand_peer_list_.end(); peer++) {
315     if (peer->get()->GetServiceName() == service_name &&
316         peer->get()->GetAppID() == appid) {
317       ondemand_peer_list_.erase(peer);
318       _D("[%s:%s] is removed from list", appid.c_str(), service_name.c_str());
319       break;
320     }
321   }
322 }
323
324 tizen_base::Parcel CionOndemandServer::GetOndemandList(
325     std::string service_name) {
326   if (ondemand_peer_list_.size() == 0) {
327     _W("ondemand peer list is empty");
328     return {};
329   }
330
331   std::string header("ODL:");
332   tizen_base::Parcel parcel;
333   parcel.WriteString(header);
334
335   for (auto& peer : ondemand_peer_list_) {
336     if (peer->GetServiceName() != service_name ||
337         aul_app_is_running(peer->GetAppID().c_str()))
338       continue;
339
340     parcel.WriteBool(true);
341     std::vector<uint8_t> peer_raw = peer->Serialize();
342     parcel.WriteUInt32(peer_raw.size());
343     parcel.Write(peer_raw.data(), peer_raw.size());
344   }
345
346   parcel.WriteBool(false);
347
348   return parcel;
349 }