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 int DoGetAppInfo(const tizen_base::Database& db, uid_t db_uid, uid_t uid,
389 const char* locale, pkgmgrinfo_filter_x* filter, int flag,
390 std::vector<std::shared_ptr<application_x>>& applications) {
391 static const char query_raw[] =
392 "SELECT DISTINCT ai.app_id, ai.app_installed_storage, "
393 "ai.app_external_path";
394 static const char query_basic[] =
395 ", ai.app_component, ai.app_exec, "
396 "ai.app_nodisplay, ai.app_type, ai.app_onboot, "
397 "ai.app_multiple, ai.app_autorestart, ai.app_taskmanage, "
398 "ai.app_hwacceleration, ai.app_screenreader, "
399 "ai.app_mainapp, ai.app_recentimage, ai.app_launchcondition, "
400 "ai.app_indicatordisplay, ai.app_portraitimg, "
401 "ai.app_landscapeimg, ai.app_guestmodevisibility, "
402 "ai.app_permissiontype, ai.app_preload, ai.app_submode, "
403 "ai.app_submode_mainid, ai.app_launch_mode, ai.app_ui_gadget, "
404 "ai.app_support_disable, ai.app_process_pool, "
405 "ai.app_background_category, ai.app_package_type, "
406 "ai.app_root_path, ai.app_api_version, ai.app_effective_appid, "
407 "ai.app_disable, ai.app_splash_screen_display, ai.app_tep_name, "
408 "ai.app_zip_mount_file, ai.component_type, ai.package, "
409 "ai.app_package_system, ai.app_removable, "
410 "ai.app_package_installed_time, ai.app_support_mode, "
411 "ai.app_support_ambient, ai.app_setup_appid, ai.light_user_switch_mode";
412 static const char query_uid_info[] =
413 ", ui.is_disabled, ui.is_splash_screen_enabled";
414 static const char query_label[] =
416 "(SELECT app_label FROM package_app_localized_info WHERE "
417 "ai.app_id=app_id AND app_locale=?), "
418 "(SELECT app_label FROM package_app_localized_info WHERE "
419 "ai.app_id=app_id AND app_locale='No Locale'))";
420 static const char query_icon[] =
422 "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
423 "AND app_locale=?), "
424 "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
425 "AND app_locale='No Locale'))";
426 static const char query_from_clause[] = " FROM package_app_info as ai";
427 static const char query_uid_info_clause[] =
428 " LEFT OUTER JOIN package_app_info_for_uid AS ui "
429 "ON (ai.app_id=ui.app_id AND ui.uid=?)";
430 char* bg_category_str = nullptr;
431 char* tmp_record = nullptr;
432 std::list<std::string> bind_params;
433 bool is_check_storage = true;
434 const uid_t global_user_uid = GLOBAL_USER;
435 std::string query = query_raw;
437 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
438 query += query_basic;
439 query += query_uid_info;
442 if (flag & PMINFO_APPINFO_GET_LABEL) {
443 query += query_label;
444 bind_params.push_back(locale);
447 if (flag & PMINFO_APPINFO_GET_ICON) {
449 bind_params.push_back(locale);
452 bind_params.push_back(std::to_string(uid));
453 is_check_storage = __check_app_storage_status(filter);
455 std::string constraint;
456 int ret = GetFilteredQuery(filter, locale, uid, constraint, bind_params);
457 if (ret != PMINFO_R_OK) {
458 LOGE("Failed to get WHERE clause");
459 return PMINFO_R_ERROR;
462 query += query_from_clause;
463 query += query_uid_info_clause;
465 if (!constraint.empty())
468 auto q = tizen_base::Database::Sql(query);
469 for (auto& i : bind_params)
470 q.Bind(std::move(i));
474 _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
475 return PMINFO_R_ERROR;
478 for (const auto& rec : r) {
479 application_x* info = static_cast<application_x*>(
480 calloc(1, sizeof(application_x)));
481 if (info == nullptr) {
482 LOGE("out of memory");
483 return PMINFO_R_ERROR;
485 std::shared_ptr<application_x> info_auto(info,
486 pkgmgrinfo_basic_free_application);
488 info->locale = strdup(locale);
489 if (info->locale == nullptr) {
490 LOGE("Out of memory");
491 return PMINFO_R_ERROR;
495 info->appid = GetCString(idx++, rec);
496 info->installed_storage = GetCString(idx++, rec);
497 info->external_path = GetCString(idx++, rec);
498 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
499 info->component = GetCString(idx++, rec);
500 info->exec = GetCString(idx++, rec);
501 info->nodisplay = GetCString(idx++, rec);
502 info->type = GetCString(idx++, rec);
503 info->onboot = GetCString(idx++, rec);
504 info->multiple = GetCString(idx++, rec);
505 info->autorestart = GetCString(idx++, rec);
506 info->taskmanage = GetCString(idx++, rec);
507 info->hwacceleration = GetCString(idx++, rec);
508 info->screenreader = GetCString(idx++, rec);
509 info->mainapp = GetCString(idx++, rec);
510 info->recentimage = GetCString(idx++, rec);
511 info->launchcondition = GetCString(idx++, rec);
512 info->indicatordisplay = GetCString(idx++, rec);
513 info->portraitimg = GetCString(idx++, rec);
514 info->landscapeimg = GetCString(idx++, rec);
515 info->guestmode_visibility = GetCString(idx++, rec);
516 info->permission_type = GetCString(idx++, rec);
517 info->preload = GetCString(idx++, rec);
518 info->submode = GetCString(idx++, rec);
519 info->submode_mainid = GetCString(idx++, rec);
520 info->launch_mode = GetCString(idx++, rec);
521 info->ui_gadget = GetCString(idx++, rec);
522 info->support_disable = GetCString(idx++, rec);
523 info->process_pool = GetCString(idx++, rec);
524 bg_category_str = GetCString(idx++, rec);
525 info->package_type = GetCString(idx++, rec);
526 info->root_path = GetCString(idx++, rec);
527 info->api_version = GetCString(idx++, rec);
528 info->effective_appid = GetCString(idx++, rec);
529 info->is_disabled = GetCString(idx++, rec);
530 info->splash_screen_display = GetCString(idx++, rec);
531 info->tep_name = GetCString(idx++, rec);
532 info->zip_mount_file = GetCString(idx++, rec);
533 info->component_type = GetCString(idx++, rec);
534 info->package = GetCString(idx++, rec);
535 info->package_system = GetCString(idx++, rec);
536 info->removable = GetCString(idx++, rec);
537 info->package_installed_time = GetCString(idx++, rec);
538 info->support_mode = GetCString(idx++, rec);
539 info->support_ambient = GetCString(idx++, rec);
540 info->setup_appid = GetCString(idx++, rec);
541 info->light_user_switch_mode = GetCString(idx++, rec);
542 info->background_category = __get_background_category(
544 free(bg_category_str);
547 info->for_all_users =
548 strdup((db_uid != global_user_uid) ?
551 if (db_uid != global_user_uid) {
554 tmp_record = GetCString(idx++, rec);
555 if (tmp_record != nullptr) {
556 if (strcasecmp(info->is_disabled, "false") == 0 &&
557 strcasecmp(tmp_record, "false") == 0) {
558 free(info->is_disabled);
559 info->is_disabled = tmp_record;
564 tmp_record = GetCString(idx++, rec);
565 if (tmp_record != nullptr) {
566 if (strcasecmp(info->splash_screen_display, "false") == 0 &&
567 strcasecmp(tmp_record, "false") == 0) {
568 free(info->splash_screen_display);
569 info->splash_screen_display = tmp_record;
576 if (flag & PMINFO_APPINFO_GET_LABEL) {
577 tmp_record = GetCString(idx++, rec);
578 if (_add_label_info_into_list(locale, tmp_record,
580 return PMINFO_R_ERROR;
584 if (flag & PMINFO_APPINFO_GET_ICON) {
585 tmp_record = GetCString(idx++, rec);
586 if (_add_icon_info_into_list(locale, tmp_record,
588 return PMINFO_R_ERROR;
592 if (flag & PMINFO_APPINFO_GET_CATEGORY) {
593 if (GetCategory(db, info->appid, &info->category))
594 return PMINFO_R_ERROR;
597 if (flag & PMINFO_APPINFO_GET_APP_CONTROL) {
598 if (GetAppControl(db, info->appid, &info->appcontrol))
599 return PMINFO_R_ERROR;
602 if (flag & PMINFO_APPINFO_GET_METADATA) {
603 if (GetMetadata(db, info->appid, &info->metadata))
604 return PMINFO_R_ERROR;
607 if (flag & PMINFO_APPINFO_GET_SPLASH_SCREEN) {
608 if (GetSplashScreens(db, info->appid, &info->splashscreens))
609 return PMINFO_R_ERROR;
612 if (flag & PMINFO_APPINFO_GET_RES_CONTROL) {
613 if (GetResControl(db, info->appid, &info->res_control))
614 return PMINFO_R_ERROR;
617 if (is_check_storage &&
618 __appinfo_check_installed_storage(info) !=
623 applications.push_back(std::move(info_auto));
631 namespace pkgmgr_server {
634 API bool CheckAppStorageStatus(pkgmgrinfo_filter_x* tmp_filter) {
635 return ::__check_app_storage_status(tmp_filter);
638 API int GetAppInfo(const tizen_base::Database& db,
639 pkgmgrinfo_appinfo_filter_h filter, uid_t db_uid, uid_t uid,
640 const std::string& locale,
641 std::vector<std::shared_ptr<application_x>>& appinfo_list) {
642 if (!static_cast<bool>(db) || filter == nullptr) {
643 LOGE("Invalid argument");
644 return PMINFO_R_EINVAL;
647 return ::DoGetAppInfo(db, db_uid, uid, locale.c_str(),
648 static_cast<pkgmgrinfo_filter_x*>(filter), PMINFO_APPINFO_GET_ALL,
652 } // namesapce internal
653 } // namesapce pkgmgr_server