2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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 <sys/types.h>
31 #include "pkgmgr-info.h"
32 #include "pkgmgrinfo_debug.h"
33 #include "pkgmgrinfo_private.h"
34 #include "pkgmgr_parser.h"
35 #include "pkgmgrinfo_internal.h"
39 char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
40 std::optional<std::string> str = rec.GetString(idx);
44 return strdup(str->c_str());
47 void ParseAppControl(GList** appcontrol,
48 const char* appcontrol_str, const char* visibility, const char* id) {
54 if (appcontrol_str == nullptr)
57 dup = strdup(appcontrol_str);
59 _LOGE("out of memory");
64 ac = static_cast<appcontrol_x*>(calloc(1, sizeof(appcontrol_x)));
66 _LOGE("out of memory");
69 token = strtok_r(dup, "|", &ptr);
70 if (token && strcmp(token, "NULL"))
71 ac->operation = strdup(token);
72 token = strtok_r(nullptr, "|", &ptr);
73 if (token && strcmp(token, "NULL"))
74 ac->uri = strdup(token);
75 token = strtok_r(nullptr, "|", &ptr);
76 if (token && strcmp(token, "NULL"))
77 ac->mime = strdup(token);
78 ac->visibility = strdup(visibility);
80 *appcontrol = g_list_prepend(*appcontrol, ac);
81 } while ((token = strtok_r(nullptr, ";", &ptr)));
86 int GetSplashScreens(const tizen_base::Database& db,
87 const char* appid, GList** splashscreens) {
88 auto q = tizen_base::Database::Sql(
89 "SELECT src, type, orientation, indicatordisplay, "
90 "operation, color_depth "
91 "FROM package_app_splash_screen WHERE app_id=?")
96 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
97 return PMINFO_R_ERROR;
100 for (const auto& rec : r) {
101 splashscreen_x* info = static_cast<splashscreen_x*>(
102 calloc(1, sizeof(splashscreen_x)));
103 if (info == nullptr) {
104 LOGE("out of memory");
105 return PMINFO_R_ERROR;
109 info->src = GetCString(idx++, rec);
110 info->type = GetCString(idx++, rec);
111 info->orientation = GetCString(idx++, rec);
112 info->indicatordisplay = GetCString(idx++, rec);
113 info->operation = GetCString(idx++, rec);
114 info->color_depth = GetCString(idx++, rec);
115 *splashscreens = g_list_prepend(*splashscreens, info);
121 int GetMetadata(const tizen_base::Database& db,
122 const char* appid, GList** metadata) {
123 auto q = tizen_base::Database::Sql(
124 "SELECT md_key, md_value "
125 "FROM package_app_app_metadata WHERE app_id=?")
130 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
131 return PMINFO_R_ERROR;
134 for (const auto& rec : r) {
135 metadata_x* info = static_cast<metadata_x*>(
136 calloc(1, sizeof(metadata_x)));
137 if (info == nullptr) {
138 LOGE("out of memory");
139 return PMINFO_R_ERROR;
143 info->key = GetCString(idx++, rec);
144 info->value = GetCString(idx++, rec);
145 *metadata = g_list_prepend(*metadata, info);
151 int GetAppControl(const tizen_base::Database& db,
152 const char* appid, GList** appcontrol) {
153 auto q = tizen_base::Database::Sql(
154 "SELECT app_control, visibility, app_control_id "
155 "FROM package_app_app_control WHERE app_id=?")
160 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
161 return PMINFO_R_ERROR;
164 for (const auto& rec : r) {
165 ParseAppControl(appcontrol, rec.GetString(0)->c_str(),
166 rec.GetString(1)->c_str(), rec.GetString(2)->c_str());
172 int GetCategory(const tizen_base::Database& db,
173 const char* appid, GList** category) {
174 auto q = tizen_base::Database::Sql(
176 "FROM package_app_app_category WHERE app_id=?")
180 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
181 return PMINFO_R_ERROR;
184 for (const auto& rec : r) {
185 char* val = GetCString(0, rec);
187 *category = g_list_prepend(*category, (gpointer)val);
193 int GetResControl(const tizen_base::Database& db, const char* appid,
194 GList** res_control) {
195 auto q = tizen_base::Database::Sql(
196 "SELECT res_type, min_res_version, max_res_version, auto_close "
197 "FROM package_app_res_control WHERE app_id=?")
202 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
203 return PMINFO_R_ERROR;
206 for (const auto& rec : r) {
207 res_control_x* info = static_cast<res_control_x*>(
208 calloc(1, sizeof(res_control_x)));
209 if (info == nullptr) {
210 LOGE("out of memory");
211 return PMINFO_R_ERROR;
215 info->res_type = GetCString(idx++, rec);
216 info->min_res_version = GetCString(idx++, rec);
217 info->max_res_version = GetCString(idx++, rec);
218 info->auto_close = GetCString(idx++, rec);
219 *res_control = g_list_prepend(*res_control, info);
225 GList* __get_background_category(const char* value) {
226 GList* category_list = nullptr;
227 int convert_value = 0;
229 if (!value || strlen(value) == 0)
232 convert_value = atoi(value);
233 if (convert_value < 0)
236 if (convert_value & APP_BG_CATEGORY_USER_DISABLE_TRUE_VAL)
237 category_list = g_list_prepend(category_list,
238 strdup(APP_BG_CATEGORY_USER_DISABLE_TRUE_STR));
240 category_list = g_list_prepend(category_list,
241 strdup(APP_BG_CATEGORY_USER_DISABLE_FALSE_STR));
243 if (convert_value & APP_BG_CATEGORY_MEDIA_VAL)
244 category_list = g_list_prepend(category_list,
245 strdup(APP_BG_CATEGORY_MEDIA_STR));
247 if (convert_value & APP_BG_CATEGORY_DOWNLOAD_VAL)
248 category_list = g_list_prepend(category_list,
249 strdup(APP_BG_CATEGORY_DOWNLOAD_STR));
251 if (convert_value & APP_BG_CATEGORY_BGNETWORK_VAL)
252 category_list = g_list_prepend(category_list,
253 strdup(APP_BG_CATEGORY_BGNETWORK_STR));
255 if (convert_value & APP_BG_CATEGORY_LOCATION_VAL)
256 category_list = g_list_prepend(category_list,
257 strdup(APP_BG_CATEGORY_LOCATION_STR));
259 if (convert_value & APP_BG_CATEGORY_SENSOR_VAL)
260 category_list = g_list_prepend(category_list,
261 strdup(APP_BG_CATEGORY_SENSOR_STR));
263 if (convert_value & APP_BG_CATEGORY_IOTCOMM_VAL)
264 category_list = g_list_prepend(category_list,
265 strdup(APP_BG_CATEGORY_IOTCOMM_STR));
267 if (convert_value & APP_BG_CATEGORY_SYSTEM_VAL)
268 category_list = g_list_prepend(category_list,
269 strdup(APP_BG_CATEGORY_SYSTEM));
271 return category_list;
274 constexpr const char join_localized_info[] =
275 " LEFT OUTER JOIN package_app_localized_info"
276 " ON ai.app_id=package_app_localized_info.app_id"
277 " AND package_app_localized_info.app_locale=?";
278 constexpr const char join_category[] =
279 " LEFT OUTER JOIN package_app_app_category"
280 " ON ai.app_id=package_app_app_category.app_id";
281 constexpr const char join_app_control[] =
282 " LEFT OUTER JOIN package_app_app_control"
283 " ON ai.app_id=package_app_app_control.app_id";
284 constexpr const char join_metadata[] =
285 " LEFT OUTER JOIN package_app_app_metadata"
286 " ON ai.app_id=package_app_app_metadata.app_id ";
287 constexpr const char join_privilege[] =
288 " LEFT OUTER JOIN package_privilege_info"
289 " ON ai.package=package_privilege_info.package ";
291 int GetFilteredQuery(pkgmgrinfo_filter_x* filter, const char* locale,
292 uid_t uid, std::string& query, std::list<std::string>& bind_params) {
294 char* condition = nullptr;
299 if (filter->cache_flag) {
300 joined = E_PMINFO_APPINFO_JOIN_LOCALIZED_INFO |
301 E_PMINFO_APPINFO_JOIN_CATEGORY |
302 E_PMINFO_APPINFO_JOIN_APP_CONTROL |
303 E_PMINFO_APPINFO_JOIN_METADATA |
304 E_PMINFO_APPINFO_JOIN_PRIVILEGE;
307 std::string buf = " WHERE 1=1";
308 GList* tmp_params = nullptr;
309 for (GSList* list = filter->list; list; list = list->next) {
310 joined |= __get_filter_condition(list->data,
311 uid, &condition, &tmp_params);
312 if (condition == nullptr)
321 if (filter->list_metadata)
323 for (GSList* list = filter->list_metadata; list; list = list->next) {
324 joined |= __get_metadata_filter_condition(list->data,
325 &condition, &tmp_params);
326 if (condition == nullptr)
334 if (filter->list_metadata)
337 std::string tmp_query;
338 if (joined & E_PMINFO_APPINFO_JOIN_LOCALIZED_INFO) {
339 tmp_query += join_localized_info;
340 bind_params.push_back(locale);
343 if (joined & E_PMINFO_APPINFO_JOIN_CATEGORY)
344 tmp_query += join_category;
345 if (joined & E_PMINFO_APPINFO_JOIN_APP_CONTROL)
346 tmp_query += join_app_control;
347 if (joined & E_PMINFO_APPINFO_JOIN_METADATA)
348 tmp_query += join_metadata;
349 if (joined & E_PMINFO_APPINFO_JOIN_PRIVILEGE)
350 tmp_query += join_privilege;
352 for (GList* l = tmp_params; l != nullptr; l = l->next)
353 bind_params.push_back(reinterpret_cast<char*>(l->data));
355 query = tmp_query + buf;
356 g_list_free_full(tmp_params, free);
361 bool __check_app_storage_status(pkgmgrinfo_filter_x* tmp_filter) {
362 GSList* tmp_list = nullptr;
363 pkgmgrinfo_node_x* tmp_node = nullptr;
366 if (tmp_filter == nullptr)
369 if (tmp_filter->cache_flag)
372 property = _pminfo_appinfo_convert_to_prop_bool(
373 PMINFO_APPINFO_PROP_APP_CHECK_STORAGE);
374 for (tmp_list = tmp_filter->list; tmp_list != nullptr;
375 tmp_list = g_slist_next(tmp_list)) {
376 tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
377 if (property == tmp_node->prop) {
378 if (strcmp(tmp_node->value, "true") == 0)
388 enum class PackageDisableFilterStatus {
394 PackageDisableFilterStatus GetPackageDisableFilterStatus(
395 const pkgmgrinfo_filter_x* filter) {
396 GSList* tmp_list = nullptr;
397 pkgmgrinfo_node_x* tmp_node = nullptr;
400 property = _pminfo_appinfo_convert_to_prop_bool(
401 PMINFO_APPINFO_PROP_PKG_DISABLE);
402 for (tmp_list = filter->list; tmp_list != nullptr;
403 tmp_list = g_slist_next(tmp_list)) {
404 tmp_node = reinterpret_cast<pkgmgrinfo_node_x*>(tmp_list->data);
405 if (property != tmp_node->prop)
408 return strcasecmp(tmp_node->value, "true") == 0 ?
409 PackageDisableFilterStatus::True : PackageDisableFilterStatus::False;
412 return PackageDisableFilterStatus::None;
415 bool CheckPkgDisableFilter(PackageDisableFilterStatus expected,
416 const char* package_disable, application_x* app_info) {
417 if (!package_disable)
420 PackageDisableFilterStatus result = strcasecmp(package_disable, "true") == 0 ?
421 PackageDisableFilterStatus::True : PackageDisableFilterStatus::False;
423 if (expected == result)
426 if (result == PackageDisableFilterStatus::True)
427 LOGW("The package [%s] to which the application [%s] belongs is disabled",
428 app_info->package, app_info->appid);
433 bool CheckAppDisableFilter(const pkgmgrinfo_filter_x* filter,
434 const application_x* app_info) {
435 GSList* tmp_list = nullptr;
436 pkgmgrinfo_node_x* tmp_node = nullptr;
439 property = _pminfo_appinfo_convert_to_prop_bool(
440 PMINFO_APPINFO_PROP_APP_DISABLE);
441 for (tmp_list = filter->list; tmp_list != nullptr;
442 tmp_list = g_slist_next(tmp_list)) {
443 tmp_node = reinterpret_cast<pkgmgrinfo_node_x*>(tmp_list->data);
444 if (property != tmp_node->prop)
447 if (strcasecmp(tmp_node->value, app_info->is_disabled) == 0)
450 if (strcasecmp(app_info->is_disabled, "true") == 0)
451 LOGW("The application [%s] is disabled", app_info->appid);
458 int DoGetAppInfo(const tizen_base::Database& db, uid_t db_uid, uid_t uid,
459 const char* locale, pkgmgrinfo_filter_x* filter, int flag,
460 std::vector<std::shared_ptr<application_x>>& applications) {
461 static const char query_raw[] =
462 "SELECT DISTINCT ai.app_id, ai.app_installed_storage, "
463 "ai.app_external_path";
464 static const char query_app_disable[] = ", "
466 "WHEN ai.app_disable='true' COLLATE NOCASE OR "
467 "ui.is_disabled='true' COLLATE NOCASE "
470 "END AS app_disable";
471 static const char query_basic[] =
472 ", ai.app_component, ai.app_exec, "
473 "ai.app_nodisplay, ai.app_type, ai.app_onboot, "
474 "ai.app_multiple, ai.app_autorestart, ai.app_taskmanage, "
475 "ai.app_hwacceleration, ai.app_screenreader, "
476 "ai.app_mainapp, ai.app_recentimage, ai.app_launchcondition, "
477 "ai.app_indicatordisplay, ai.app_portraitimg, "
478 "ai.app_landscapeimg, ai.app_guestmodevisibility, "
479 "ai.app_permissiontype, ai.app_preload, ai.app_submode, "
480 "ai.app_submode_mainid, ai.app_launch_mode, ai.app_ui_gadget, "
481 "ai.app_support_disable, ai.app_process_pool, "
482 "ai.app_background_category, ai.app_package_type, "
483 "ai.app_root_path, ai.app_api_version, ai.app_effective_appid, "
484 "ai.app_splash_screen_display, ai.app_tep_name, "
485 "ai.app_zip_mount_file, ai.component_type, ai.package, "
486 "ai.app_package_system, ai.app_removable, "
487 "ai.app_package_installed_time, ai.app_support_mode, "
488 "ai.app_support_ambient, ai.app_setup_appid, ai.light_user_switch_mode";
489 static const char query_uid_info[] =
490 ", ui.is_disabled, ui.is_splash_screen_enabled";
491 static const char query_label[] =
493 "(SELECT app_label FROM package_app_localized_info WHERE "
494 "ai.app_id=app_id AND app_locale=?), "
495 "(SELECT app_label FROM package_app_localized_info WHERE "
496 "ai.app_id=app_id AND app_locale='No Locale'))";
497 static const char query_icon[] =
499 "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
500 "AND app_locale=?), "
501 "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
502 "AND app_locale='No Locale'))";
503 static const char query_package_disable[] =
504 ", (SELECT package_disable FROM package_info WHERE ai.package=package)";
505 static const char query_from_clause[] = " FROM package_app_info as ai";
506 static const char query_uid_info_clause[] =
507 " LEFT OUTER JOIN package_app_info_for_uid AS ui "
508 "ON (ai.app_id=ui.app_id AND ui.uid=?)";
509 char* bg_category_str = nullptr;
510 char* tmp_record = nullptr;
511 std::list<std::string> bind_params;
512 bool is_check_storage = true;
513 const uid_t global_user_uid = GLOBAL_USER;
514 std::string query = query_raw;
515 auto pkg_disable_filter_status = GetPackageDisableFilterStatus(filter);
517 query += query_app_disable;
519 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
520 query += query_basic;
521 query += query_uid_info;
524 if (flag & PMINFO_APPINFO_GET_LABEL) {
525 query += query_label;
526 bind_params.push_back(locale);
529 if (flag & PMINFO_APPINFO_GET_ICON) {
531 bind_params.push_back(locale);
534 if (pkg_disable_filter_status != PackageDisableFilterStatus::None)
535 query += query_package_disable;
537 bind_params.push_back(std::to_string(uid));
538 is_check_storage = __check_app_storage_status(filter);
540 std::string constraint;
541 int ret = GetFilteredQuery(filter, locale, uid, constraint, bind_params);
542 if (ret != PMINFO_R_OK) {
543 LOGE("Failed to get WHERE clause");
544 return PMINFO_R_ERROR;
547 query += query_from_clause;
548 query += query_uid_info_clause;
550 if (!constraint.empty())
553 auto q = tizen_base::Database::Sql(query);
554 for (auto& i : bind_params)
555 q.Bind(std::move(i));
559 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
560 return PMINFO_R_ERROR;
563 for (const auto& rec : r) {
564 application_x* info = static_cast<application_x*>(
565 calloc(1, sizeof(application_x)));
566 if (info == nullptr) {
567 LOGE("out of memory");
568 return PMINFO_R_ERROR;
570 std::shared_ptr<application_x> info_auto(info,
571 pkgmgrinfo_basic_free_application);
573 info->locale = strdup(locale);
574 if (info->locale == nullptr) {
575 LOGE("Out of memory");
576 return PMINFO_R_ERROR;
580 info->appid = GetCString(idx++, rec);
581 info->installed_storage = GetCString(idx++, rec);
582 info->external_path = GetCString(idx++, rec);
583 info->is_disabled = GetCString(idx++, rec);
584 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
585 info->component = GetCString(idx++, rec);
586 info->exec = GetCString(idx++, rec);
587 info->nodisplay = GetCString(idx++, rec);
588 info->type = GetCString(idx++, rec);
589 info->onboot = GetCString(idx++, rec);
590 info->multiple = GetCString(idx++, rec);
591 info->autorestart = GetCString(idx++, rec);
592 info->taskmanage = GetCString(idx++, rec);
593 info->hwacceleration = GetCString(idx++, rec);
594 info->screenreader = GetCString(idx++, rec);
595 info->mainapp = GetCString(idx++, rec);
596 info->recentimage = GetCString(idx++, rec);
597 info->launchcondition = GetCString(idx++, rec);
598 info->indicatordisplay = GetCString(idx++, rec);
599 info->portraitimg = GetCString(idx++, rec);
600 info->landscapeimg = GetCString(idx++, rec);
601 info->guestmode_visibility = GetCString(idx++, rec);
602 info->permission_type = GetCString(idx++, rec);
603 info->preload = GetCString(idx++, rec);
604 info->submode = GetCString(idx++, rec);
605 info->submode_mainid = GetCString(idx++, rec);
606 info->launch_mode = GetCString(idx++, rec);
607 info->ui_gadget = GetCString(idx++, rec);
608 info->support_disable = GetCString(idx++, rec);
609 info->process_pool = GetCString(idx++, rec);
610 bg_category_str = GetCString(idx++, rec);
611 info->package_type = GetCString(idx++, rec);
612 info->root_path = GetCString(idx++, rec);
613 info->api_version = GetCString(idx++, rec);
614 info->effective_appid = GetCString(idx++, rec);
615 info->splash_screen_display = GetCString(idx++, rec);
616 info->tep_name = GetCString(idx++, rec);
617 info->zip_mount_file = GetCString(idx++, rec);
618 info->component_type = GetCString(idx++, rec);
619 info->package = GetCString(idx++, rec);
620 info->package_system = GetCString(idx++, rec);
621 info->removable = GetCString(idx++, rec);
622 info->package_installed_time = GetCString(idx++, rec);
623 info->support_mode = GetCString(idx++, rec);
624 info->support_ambient = GetCString(idx++, rec);
625 info->setup_appid = GetCString(idx++, rec);
626 info->light_user_switch_mode = GetCString(idx++, rec);
627 info->background_category = __get_background_category(
629 free(bg_category_str);
632 info->for_all_users =
633 strdup((db_uid != global_user_uid) ?
636 if (db_uid != global_user_uid) {
639 tmp_record = GetCString(idx++, rec);
640 if (tmp_record != nullptr) {
641 if (strcasecmp(info->is_disabled, "false") == 0 &&
642 strcasecmp(tmp_record, "false") == 0) {
643 free(info->is_disabled);
644 info->is_disabled = tmp_record;
649 tmp_record = GetCString(idx++, rec);
650 if (tmp_record != nullptr) {
651 if (strcasecmp(info->splash_screen_display, "false") == 0 &&
652 strcasecmp(tmp_record, "false") == 0) {
653 free(info->splash_screen_display);
654 info->splash_screen_display = tmp_record;
661 if (flag & PMINFO_APPINFO_GET_LABEL) {
662 tmp_record = GetCString(idx++, rec);
663 if (_add_label_info_into_list(locale, tmp_record,
668 return PMINFO_R_ERROR;
672 if (flag & PMINFO_APPINFO_GET_ICON) {
673 tmp_record = GetCString(idx++, rec);
674 if (_add_icon_info_into_list(locale, tmp_record,
679 return PMINFO_R_ERROR;
683 if (pkg_disable_filter_status != PackageDisableFilterStatus::None) {
684 tmp_record = GetCString(idx++, rec);
686 bool filter_passed = CheckPkgDisableFilter(pkg_disable_filter_status,
695 if (flag & PMINFO_APPINFO_GET_CATEGORY) {
696 if (GetCategory(db, info->appid, &info->category))
697 return PMINFO_R_ERROR;
700 if (flag & PMINFO_APPINFO_GET_APP_CONTROL) {
701 if (GetAppControl(db, info->appid, &info->appcontrol))
702 return PMINFO_R_ERROR;
705 if (flag & PMINFO_APPINFO_GET_METADATA) {
706 if (GetMetadata(db, info->appid, &info->metadata))
707 return PMINFO_R_ERROR;
710 if (flag & PMINFO_APPINFO_GET_SPLASH_SCREEN) {
711 if (GetSplashScreens(db, info->appid, &info->splashscreens))
712 return PMINFO_R_ERROR;
715 if (flag & PMINFO_APPINFO_GET_RES_CONTROL) {
716 if (GetResControl(db, info->appid, &info->res_control))
717 return PMINFO_R_ERROR;
720 if (is_check_storage &&
721 __appinfo_check_installed_storage(info) !=
726 if (!CheckAppDisableFilter(filter, info))
729 if (!(flag & PMINFO_APPINFO_GET_BASICINFO) && info->is_disabled) {
730 free(info->is_disabled);
731 info->is_disabled = nullptr;
734 applications.push_back(std::move(info_auto));
742 namespace pkgmgr_server {
745 API bool CheckAppStorageStatus(pkgmgrinfo_filter_x* tmp_filter) {
746 return ::__check_app_storage_status(tmp_filter);
749 API int GetAppInfo(const tizen_base::Database& db,
750 pkgmgrinfo_appinfo_filter_h filter, uid_t db_uid, uid_t uid,
751 const std::string& locale,
752 std::vector<std::shared_ptr<application_x>>& appinfo_list) {
753 if (!static_cast<bool>(db) || filter == nullptr) {
754 LOGE("Invalid argument");
755 return PMINFO_R_EINVAL;
758 return ::DoGetAppInfo(db, db_uid, uid, locale.c_str(),
759 static_cast<pkgmgrinfo_filter_x*>(filter), PMINFO_APPINFO_GET_ALL,
763 } // namesapce internal
764 } // namesapce pkgmgr_server