2 * Copyright 2023 Samsung Electronics Co., Ltd
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <notification_setting.h>
24 #include <notification_setting_internal.h>
25 #include <notification_setting_service.h>
26 #include <notification_noti.h>
27 #include <badge_setting.h>
28 #include <badge_setting_service.h>
30 #include <package-manager.h>
31 #include <tzplatform_config.h>
32 #include <pkgmgr-info.h>
37 #include <string_view>
41 #include "pkgmgr_client.hh"
42 #include "service_common.h"
43 #include "notification_service.h"
44 #include "badge_service.h"
45 #include "shortcut_service.h"
47 #define DBUS_NAME "org.freedesktop.DBus"
48 #define DBUS_OBJECT_PATH "/org/freedesktop/DBus"
49 #define DBUS_INTERFACE_NAME "org.freedesktop.DBus"
51 #define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
52 #define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
56 static GDBusConnection *_gdbus_conn;
57 static GHashTable *_noti_pkg_privilege_info;
58 static GHashTable *_badge_pkg_privilege_info;
59 std::unique_ptr<PkgmgrClient> pkgmgr_client_;
60 std::list<std::shared_ptr<PkgmgrEventArgs>> pkgmgr_event_list_;
61 std::list<std::shared_ptr<PkgmgrAppEventArgs>> pkgmgr_app_event_list_;
63 const std::set<std::string_view> pkgmgr_installer_key_list_ = {
69 const std::set<std::string_view> pkgmgr_installer_val_list_ = {
77 static int _package_install_cb(uid_t uid, const char *pkgname);
78 static int _package_uninstall_cb(uid_t uid, const char *pkgname);
79 static int _app_enabled_cb(uid_t uid, const char *app_id);
80 static int _app_disabled_cb(uid_t uid, const char *app_id);
82 class PackageEventListener : public PkgmgrClient::IEvent {
84 void OnPkgmgrEvent(std::shared_ptr<PkgmgrEventArgs> args) override;
85 void OnPkgmgrAppEvent(std::shared_ptr<PkgmgrAppEventArgs> args) override;
88 void PackageEventListener::OnPkgmgrEvent(std::shared_ptr<PkgmgrEventArgs> args) {
89 if (pkgmgr_installer_key_list_.find(args->GetEventStatus()) ==
90 pkgmgr_installer_key_list_.end())
93 if (args->GetEventStatus().compare(std::string("start")) == 0 &&
94 pkgmgr_installer_val_list_.find(args->GetEventName()) !=
95 pkgmgr_installer_val_list_.end()) {
96 pkgmgr_event_list_.push_back(args);
100 if (args->GetEventName().compare(std::string("ok")) == 0) {
101 for (auto& a : pkgmgr_event_list_) {
102 if (a->GetTargetUid() == args->GetTargetUid() &&
103 a->GetPkgId().compare(args->GetPkgId()) == 0) {
104 if (a->GetEventName().compare(std::string("install")) == 0)
105 _package_install_cb(args->GetTargetUid(), args->GetPkgId().c_str());
106 else if (a->GetEventName().compare(std::string("uninstall")) == 0)
107 _package_uninstall_cb(args->GetTargetUid(), args->GetPkgId().c_str());
108 else if (a->GetEventName().compare(std::string("enable_app")) == 0)
109 _app_enabled_cb(args->GetTargetUid(), args->GetPkgId().c_str());
110 else if (a->GetEventName().compare(std::string("disable_app")) == 0)
111 _app_disabled_cb(args->GetTargetUid(), args->GetPkgId().c_str());
117 void PackageEventListener::OnPkgmgrAppEvent(std::shared_ptr<PkgmgrAppEventArgs> args) {
118 if (pkgmgr_installer_key_list_.find(args->GetEventStatus()) ==
119 pkgmgr_installer_key_list_.end())
122 if (args->GetEventStatus().compare(std::string("start")) == 0 &&
123 pkgmgr_installer_val_list_.find(args->GetEventName()) !=
124 pkgmgr_installer_val_list_.end()) {
125 pkgmgr_app_event_list_.push_back(args);
129 if (args->GetEventName().compare(std::string("ok")) == 0) {
130 for (auto& a : pkgmgr_app_event_list_) {
131 if (a->GetTargetUid() == args->GetTargetUid() &&
132 a->GetPkgId().compare(args->GetPkgId()) == 0) {
133 if (a->GetEventName().compare(std::string("install")) == 0)
134 _package_install_cb(args->GetTargetUid(), args->GetPkgId().c_str());
135 else if (a->GetEventName().compare(std::string("uninstall")) == 0)
136 _package_uninstall_cb(args->GetTargetUid(), args->GetPkgId().c_str());
137 else if (a->GetEventName().compare(std::string("enable_app")) == 0)
138 _app_enabled_cb(args->GetTargetUid(), args->GetPkgId().c_str());
139 else if (a->GetEventName().compare(std::string("disable_app")) == 0)
140 _app_disabled_cb(args->GetTargetUid(), args->GetPkgId().c_str());
146 uid_t get_sender_uid(const char *sender_name) {
147 GDBusMessage *msg = nullptr;
148 GDBusMessage *reply = nullptr;
149 GError *err = nullptr;
153 msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
154 DBUS_INTERFACE_NAME, "GetConnectionUnixUser");
156 LOGE("Failed to alloc new method call");
160 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
161 reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
162 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
165 if (err != nullptr) {
166 LOGE("Failed to get uid [%s]", err->message);
172 body = g_dbus_message_get_body(reply);
173 g_variant_get(body, "(u)", &uid);
179 g_object_unref(reply);
184 pid_t get_sender_pid(const char *sender_name) {
185 GDBusMessage *msg = nullptr;
186 GDBusMessage *reply = nullptr;
187 GError *err = nullptr;
191 msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
192 DBUS_INTERFACE_NAME, "GetConnectionUnixProcessID");
194 LOGE("Failed to alloc new method call");
198 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
199 reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
200 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
203 if (err != nullptr) {
204 LOGE("Failed to get uid [%s]", err->message);
210 body = g_dbus_message_get_body(reply);
211 g_variant_get(body, "(u)", &pid);
217 g_object_unref(reply);
222 bool is_existed_busname(const char *sender_name) {
223 GDBusMessage *msg = nullptr;
224 GDBusMessage *reply = nullptr;
225 GError *err = nullptr;
227 bool is_existed = false;
229 msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
230 DBUS_INTERFACE_NAME, "NameHasOwner");
232 LOGE("Failed to alloc new method call");
236 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
237 reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
238 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
241 if (err != nullptr) {
242 LOGE("Failed to get uid [%s]", err->message);
248 body = g_dbus_message_get_body(reply);
249 g_variant_get(body, "(b)", &is_existed);
255 g_object_unref(reply);
260 int send_notify(GVariant *body, char *cmd, GHashTable **monitoring_hash,
261 char *interface_name, uid_t uid) {
262 GError *err = nullptr;
263 GList *monitoring_list = nullptr;
265 char *target_bus_name;
266 int monitoring_count = 0;
267 bool is_existed = false;
269 monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid));
270 target_list = g_list_first(monitoring_list);
271 for (; target_list != nullptr; ) {
273 target_bus_name = static_cast<char*>(target_list->data);
274 target_list = target_list->next;
276 if (g_variant_is_floating(body))
279 if (g_dbus_connection_emit_signal(_gdbus_conn,
281 PROVIDER_OBJECT_PATH,
286 if (err != nullptr) {
287 ERR("Emit signal err [%s]", err->message);
290 is_existed = is_existed_busname(target_bus_name);
291 if (is_existed == false)
292 delete_monitoring_list(monitoring_hash, target_bus_name, uid);
293 ERR("Fail, emit signal to [%s]", target_bus_name);
296 DBG("Success, emit signal to [%s]", target_bus_name);
299 DBG("Success, cmd[%s] monitoring count[%d]", cmd, monitoring_count);
300 return SERVICE_COMMON_ERROR_NONE;
303 int send_event_notify_by_busname(GVariant *body, char *cmd, char *busname,
304 char *interface_name) {
305 GError *err = nullptr;
307 if (g_variant_is_floating(body))
310 if (g_dbus_connection_emit_signal(_gdbus_conn,
312 PROVIDER_OBJECT_PATH,
317 if (err != nullptr) {
318 ERR("Emit signal err [%s]",
322 ERR("Failed to emit signal to [%s]", busname);
323 return SERVICE_COMMON_ERROR_IO_ERROR;
325 DBG("Success, Emit signal to [%s] cmd[%s]", busname, cmd);
326 return SERVICE_COMMON_ERROR_NONE;
329 /* register service */
331 static int _monitoring_app_list_compare_cb(gconstpointer a, gconstpointer b) {
332 return strcmp(static_cast<const char*>(a), reinterpret_cast<const char*>(b));
335 int service_register(GVariant *parameters, GVariant **reply_body, const gchar *sender,
336 GBusNameAppearedCallback name_appeared_handler,
337 GBusNameVanishedCallback name_vanished_handler,
338 GHashTable **monitoring_hash,
340 GList *added_list = nullptr;
341 const char *bus_name = sender;
342 monitoring_info_s *m_info = nullptr;
343 uid_t request_uid = 0;
344 GList *monitoring_list = nullptr;
346 if (sender == nullptr)
347 return SERVICE_COMMON_ERROR_IO_ERROR;
349 g_variant_get(parameters, "(i)", &request_uid);
350 if (uid > NORMAL_UID_BASE && uid != request_uid)
351 return SERVICE_COMMON_ERROR_IO_ERROR;
353 DBG("service_register : uid %d , request_uid %d", uid, request_uid);
354 monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid));
355 added_list = g_list_find_custom(monitoring_list, bus_name,
356 (GCompareFunc)_monitoring_app_list_compare_cb);
358 if (added_list == nullptr) {
359 DBG("add new sender to list");
360 m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s));
361 if (m_info == nullptr) {
362 ERR("Failed to alloc memory");
363 return SERVICE_COMMON_ERROR_OUT_OF_MEMORY;
366 m_info->bus_name = strdup(bus_name);
367 m_info->uid = request_uid;
368 m_info->watcher_id = g_bus_watch_name_on_connection(
371 G_BUS_NAME_WATCHER_FLAGS_NONE,
372 name_appeared_handler,
373 name_vanished_handler,
376 if (m_info->watcher_id == 0) {
377 ERR("Fail to watch name [%s]", bus_name);
378 free(m_info->bus_name);
380 return SERVICE_COMMON_ERROR_IO_ERROR;
382 DBG("Watch on [%s] success", bus_name);
384 monitoring_list = g_list_append(monitoring_list, strdup(bus_name));
385 DBG("Success, sender[%s] length[%d]",
386 sender, g_list_length(monitoring_list));
387 if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid)) == nullptr)
388 g_hash_table_insert(*monitoring_hash, GUINT_TO_POINTER(request_uid), monitoring_list);
390 ERR("Sender [%s] already exist", sender);
393 *reply_body = g_variant_new("()");
394 if (*reply_body == nullptr) {
396 if (m_info->bus_name)
397 free(m_info->bus_name);
400 monitoring_list = g_list_remove(monitoring_list, bus_name);
401 ERR("Failed to make reply");
402 return SERVICE_COMMON_ERROR_OUT_OF_MEMORY;
404 return SERVICE_COMMON_ERROR_NONE;
407 int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender,
409 GList *monitoring_list = nullptr;
410 GList *del_list = nullptr;
413 monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid));
414 if (monitoring_list == nullptr) {
415 ERR("No uid[%d] in monitoring hash", uid);
416 return SERVICE_COMMON_ERROR_IO_ERROR;
419 monitoring_list = g_list_first(monitoring_list);
420 del_list = g_list_find_custom(monitoring_list, sender,
421 (GCompareFunc)_monitoring_app_list_compare_cb);
424 DBG("Find delete list - uid[%d] sender[%s]", uid, sender);
425 bus_name = static_cast<char*>(g_list_nth_data(del_list, 0));
428 monitoring_list = g_list_delete_link(monitoring_list, del_list);
430 if (monitoring_list == nullptr) {
431 g_hash_table_steal(*monitoring_hash, GUINT_TO_POINTER(uid));
433 monitoring_list = g_list_first(monitoring_list);
434 g_hash_table_replace(*monitoring_hash, GUINT_TO_POINTER(uid), monitoring_list);
437 return SERVICE_COMMON_ERROR_NONE;
440 static int _dbus_init(void) {
441 GError *error = nullptr;
443 if (_gdbus_conn == nullptr) {
444 _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
445 if (_gdbus_conn == nullptr) {
446 if (error != nullptr) {
447 ERR("Failed to get dbus [%s]", error->message);
450 return SERVICE_COMMON_ERROR_IO_ERROR;
454 return SERVICE_COMMON_ERROR_NONE;
457 int service_common_register_dbus_interface(char *introspection_xml,
458 GDBusInterfaceVTable interface_vtable) {
460 int owner_id, noti_registration_id;
461 GError *error = nullptr;
462 GDBusNodeInfo *introspection_data = nullptr;
464 result = _dbus_init();
465 if (result != SERVICE_COMMON_ERROR_NONE) {
466 ERR("Can't init dbus [%d]", result);
467 result = SERVICE_COMMON_ERROR_IO_ERROR;
471 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
473 G_BUS_NAME_OWNER_FLAGS_NONE,
479 ERR("Failed to own name");
480 result = SERVICE_COMMON_ERROR_IO_ERROR;
484 DBG("Acquiring the own name [%d]", owner_id);
485 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
486 if (!introspection_data) {
487 ERR("g_dbus_node_info_new_for_xml is failed.");
488 result = SERVICE_COMMON_ERROR_IO_ERROR;
489 if (error != nullptr) {
490 ERR("g_dbus_node_info_new_for_xml err [%s]", error->message);
496 noti_registration_id = g_dbus_connection_register_object(_gdbus_conn,
497 PROVIDER_OBJECT_PATH, introspection_data->interfaces[0],
498 &interface_vtable, nullptr, nullptr, nullptr);
500 DBG("registration id[%d]", noti_registration_id);
501 if (noti_registration_id == 0) {
502 ERR("Failed to g_dbus_connection_register_object");
503 result = SERVICE_COMMON_ERROR_IO_ERROR;
508 if (introspection_data)
509 g_dbus_node_info_unref(introspection_data);
514 static int _init_pkg_privilege_info() {
515 if (_noti_pkg_privilege_info != nullptr)
518 _noti_pkg_privilege_info =
519 g_hash_table_new_full(g_str_hash, g_str_equal, free, nullptr);
520 _badge_pkg_privilege_info =
521 g_hash_table_new_full(g_str_hash, g_str_equal, free, nullptr);
522 DBG("init pkg privilege info done");
526 static int _package_install_cb(uid_t uid, const char *pkgname) {
531 if (uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
532 uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
534 _init_pkg_privilege_info();
535 if (g_hash_table_contains(_noti_pkg_privilege_info, pkgname)) {
536 tmp = g_hash_table_lookup(_noti_pkg_privilege_info, pkgname);
537 privilege_info = GPOINTER_TO_UINT(tmp);
538 if (privilege_info == 1)
539 notification_setting_db_update_pkg_disabled(pkgname, false, uid);
541 g_hash_table_remove(_noti_pkg_privilege_info, pkgname);
543 /* In consideration of the reboot status, change the disable information. */
544 ret = notification_setting_db_update_pkg_disabled(pkgname, false, uid);
545 if (ret != NOTIFICATION_ERROR_NONE)
546 notification_setting_insert_package_for_uid(pkgname, uid);
549 if (g_hash_table_contains(_badge_pkg_privilege_info, pkgname)) {
550 tmp = g_hash_table_lookup(_badge_pkg_privilege_info, pkgname);
551 privilege_info = GPOINTER_TO_UINT(tmp);
552 if (privilege_info == 1)
553 badge_db_update_pkg_disabled(pkgname, false, uid);
555 g_hash_table_remove(_badge_pkg_privilege_info, pkgname);
557 /* In consideration of the reboot status, change the disable information. */
558 ret = badge_db_update_pkg_disabled(pkgname, false, uid);
559 if (ret != BADGE_ERROR_NONE)
560 badge_setting_insert_package_for_uid(pkgname, uid);
566 static int _package_uninstall_cb(uid_t uid, const char *pkgname) {
568 pkgmgrinfo_pkginfo_h pkginfo;
570 if (uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
571 uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
573 ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(pkgname, uid, &pkginfo);
574 if (ret == PMINFO_R_OK) {
575 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
577 _init_pkg_privilege_info();
578 ret = notification_setting_db_update_pkg_disabled(pkgname, true, uid);
579 if (ret == NOTIFICATION_ERROR_NONE)
580 g_hash_table_insert(_noti_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(1));
582 g_hash_table_insert(_noti_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(0));
584 ret = badge_db_update_pkg_disabled(pkgname, true, uid);
585 if (ret == BADGE_ERROR_NONE)
586 g_hash_table_insert(_badge_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(1));
588 g_hash_table_insert(_badge_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(0));
590 notification_setting_delete_package_for_uid(pkgname, uid);
591 badge_db_delete_by_pkgname(pkgname, uid);
592 badge_setting_delete_package_for_uid(pkgname, uid);
593 notification_noti_delete_template(pkgname);
599 static int _app_enabled_cb(uid_t uid, const char *app_id) {
600 notification_setting_db_update_app_disabled(app_id, false, uid);
604 static int _app_disabled_cb(uid_t uid, const char *app_id) {
605 notification_delete_noti_by_app_id(app_id, uid);
606 notification_setting_db_update_app_disabled(app_id, true, uid);
610 std::unique_ptr<PackageEventListener> listener_;
612 void service_common_init(void) {
613 pkgmgr_client_ = std::make_unique<PkgmgrClient>();
614 listener_ = std::make_unique<PackageEventListener>();
615 pkgmgr_client_->Listen(listener_.get());
618 void service_common_set_connection(GDBusConnection *conn) {