Add pkg update info features 64/121964/23
authorJunghyun Yeon <jungh.yeon@samsung.com>
Wed, 29 Mar 2017 12:52:35 +0000 (21:52 +0900)
committerJunghyun Yeon <jungh.yeon@samsung.com>
Thu, 20 Apr 2017 00:41:56 +0000 (17:41 -0700)
- Provides methods to register, unregister, get update info of certain pkg
- Provides methods to clear update infos of all pkgs including global pkgs
  whether caller is admin user or not.

Related changes:
[pkgmgr-server] : https://review.tizen.org/gerrit/122067
[slp-pkgmgr] : https://review.tizen.org/gerrit/122068

Change-Id: I70c55bf1ed8878a2ec254e79752d9863daef5511
Signed-off-by: Junghyun Yeon <jungh.yeon@samsung.com>
include/pkgmgr-info.h
include/pkgmgrinfo_basic.h
include/pkgmgrinfo_type.h
parser/include/pkgmgr_parser_db.h
parser/src/pkgmgr_parser_db.c
src/pkgmgrinfo_updateinfo.c [new file with mode: 0644]

index b761663..5bb8bd4 100644 (file)
@@ -1053,6 +1053,302 @@ static int get_pkg_installed_time(const char *pkgid)
 int pkgmgrinfo_pkginfo_get_installed_time(pkgmgrinfo_pkginfo_h handle, int *installed_time);
 
 /**
+ * @fn int pkgmgrinfo_updateinfo_create(pkgmgrinfo_updateinfo_h *update_handle)
+ * @brief      This API creates the update info handle
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[out] handle  pointer to package update info handle
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @post       pkgmgrinfo_updateinfo_destroy()
+ * @see                pkgmgrinfo_updateinfo_set_pkgid()
+ * @see                pkgmgrinfo_updateinfo_set_version()
+ * @see                pkgmgrinfo_updateinfo_set_type()
+ * @see                pkgmgr_client_register_pkg_updateinfo()
+ * @code
+static int updateinfo_handle_create()
+{
+       int ret = 0;
+
+       pkgmgrinfo_updateinfo_h handle;
+       ret = pkgmgrinfo_updateinfo_create(&handle);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       pkgmgrinfo_update_infodestroy(handle);
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_create(pkgmgrinfo_updateinfo_h *update_handle);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_destroy(pkgmgrinfo_updateinfo_h update_handle)
+ * @brief      This API destroy the update info handle
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @pre                pkgmgrinfo_updateinfo_create()
+ * @see                pkgmgr_client_register_pkg_updateinfo()
+ * @code
+static int updateinfo_handle_destroy(pkgmgrinfo_updateinfo_h handle)
+{
+       int ret = 0;
+
+       ret = pkgmgrinfo_updateinfo_destroy(handle);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_destroy(pkgmgrinfo_updateinfo_h update_handle);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_get_updateinfo(const char *pkgid, pkgmgrinfo_updateinfo_h *update_handle)
+ * @brief      This API creates the package update information handle from db
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  pkgid   pointer to package ID
+ * @param[in]  uid     the addressee user id of the instruction
+ * @param[out] update_handle           pointer to the package update info handle.
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @pre                None
+ * @post               pkgmgrinfo_updateinfo_destroy()
+ * @see                pkgmgrinfo_updateinfo_get_pkgid()
+ * @see                pkgmgrinfo_updateinfo_get_version()
+ * @see                pkgmgrinfo_updateinfo_get_update_type()
+ * @code
+static int get_pkg_update_info(const char *pkgid)
+{
+       int ret = 0;
+       char *version;
+       pkgmgrinfo_updateinfo_h handle;
+       ret = pkgmgrinfo_updateinfo_get_updateinfo(pkgid, &handle);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       ret = pkgmgrinfo_updateinfo_get_version(handle, &version);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_updateinfo_destroy(handle);
+               return -1;
+       }
+       printf("pkg update version: %s\n", version
+       pkgmgrinfo_updateinfo_destroy(handle);
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_get_updateinfo(const char *pkgid, pkgmgrinfo_updateinfo_h *update_handle);
+int pkgmgrinfo_updateinfo_get_usr_updateinfo(const char *pkgid, pkgmgrinfo_updateinfo_h *update_handle, uid_t uid);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_set_pkgid(pkgmgrinfo_updateinfo_h updateinfo_handle, const char *pkgid)
+ * @brief      This API sets given pkgid into handle
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[in]  pkgid   package id
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int set_pkgid_to_handle(pkgmgrinfo_updateinfo_h handle, const char *pkgid)
+{
+       int ret = 0;
+
+       ret = pkgmgrinfo_updateinfo_set_pkgid(handle, pkgid);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_set_pkgid(pkgmgrinfo_updateinfo_h updateinfo_handle, const char *pkgid);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_set_version(pkgmgrinfo_updateinfo_h updateinfo_handle, const char *version)
+ * @brief      This API sets given version into handle
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[in]  version update version
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int set_version_to_handle(pkgmgrinfo_updateinfo_h handle, const char *version)
+{
+       int ret = 0;
+
+       ret = pkgmgrinfo_updateinfo_set_version(handle, version);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_set_version(pkgmgrinfo_updateinfo_h updateinfo_handle, const char *version);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_set_type(pkgmgrinfo_updateinfo_h updateinfo_handle, pkgmgrinfo_updateinfo_update_type type)
+ * @brief      This API sets given update type into handle
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[in]  type    update type
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int set_type_to_handle(pkgmgrinfo_updateinfo_h handle, pkgmgrinfo_updateinfo_update_type type)
+{
+       int ret = 0;
+
+       ret = pkgmgrinfo_updateinfo_set_type(handle, type);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_set_type(pkgmgrinfo_updateinfo_h updateinfo_handle, pkgmgrinfo_updateinfo_update_type type);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_get_pkgid(pkgmgrinfo_updateinfo_h update_handle, char **pkgid)
+ * @brief      This API retrieves the pkgid from given update info
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[out] pkgid   package id
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int get_pkgid_from_handle(pkgmgrinfo_updateinfo_h handle)
+{
+       int ret = 0;
+       char *pkgid;
+
+       ret = pkgmgrinfo_updateinfo_get_pkgid(handle, &pkgid);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_get_pkgid(pkgmgrinfo_updateinfo_h update_handle, char **pkgid);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_get_version(pkgmgrinfo_updateinfo_h updateinfo_handle, char **version)
+ * @brief      This API retrieves the version from given update info
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[out] version update version
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int get_version_from_handle(pkgmgrinfo_updateinfo_h handle)
+{
+       int ret = 0;
+       char *version;
+
+       ret = pkgmgrinfo_updateinfo_get_version(handle, &version);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_get_version(pkgmgrinfo_updateinfo_h updateinfo_handle, char **version);
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_get_update_type(pkgmgrinfo_updateinfo_h updateinfo_handle, pkgmgrinfo_updateinfo_update_type *type)
+ * @brief      This API retrieves the update type from given update info
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  pointer to package update info handle
+ * @param[out] type    update type
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int get_type_from_handle(pkgmgrinfo_updateinfo_h handle)
+{
+       int ret = 0;
+       pkgmgrinfo_updateinfo_update_type *type;
+
+       ret = pkgmgrinfo_updateinfo_get_type(handle, &type);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_get_update_type(pkgmgrinfo_updateinfo_h updateinfo_handle, pkgmgrinfo_updateinfo_update_type *type);
+
+
+/**
+ * @fn int pkgmgrinfo_updateinfo_foreach_updateinfo(pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data)
+ * @brief      This API retrieve the update informations and invoke given callback for it.
+ *
+ * @par                This API is for package-manager client application
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  callback        callback to be invoked for each retrieved informations
+ * @param[in]  user_data       user data to be passed to callback
+ * @return     0 if success, error code(<0) if fail
+ * @retval     PMINFO_R_OK     success
+ * @retval     PMINFO_R_EINVAL invalid argument
+ * @retval     PMINFO_R_ERROR  internal error
+ * @code
+static int foreach_pkg_updateinfo(pkgmgrinfo_foreach_updateinfo_cb callback)
+{
+       int ret = 0;
+
+       ret = pkgmgrinfo_updateinfo_foreach_updateinfo(callback, NULL);
+       if (ret != PMINFO_R_OK)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgrinfo_updateinfo_foreach_updateinfo(pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data);
+int pkgmgrinfo_updateinfo_usr_foreach_updateinfo(uid_t uid, pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data);
+
+/**
  * @fn int pkgmgrinfo_appinfo_get_launch_mode(pkgmgrinfo_appinfo_h handle, char **mode)
  * @brief      This API gets the launch mode of package from the package ID
  *
index 420b1c0..b5a63cc 100644 (file)
@@ -211,6 +211,12 @@ typedef struct package_x {
        GList *deviceprofile;           /**< package device profile, element*/
 } package_x;
 
+typedef struct updateinfo_x {
+       char *pkgid;
+       char *version;
+       int type;
+} updateinfo_x;
+
 typedef struct package_x manifest_x;
 
 void pkgmgrinfo_basic_free_application(application_x *application);
index 4bb96b9..b46e24e 100644 (file)
@@ -137,6 +137,27 @@ enum {
  */
 #define        PMINFO_PKGINFO_INSTALL_LOCATION_EXTERNAL        "LOCATION_EXTERNAL"
 
+/**
+ * @brief Value to be used when get/set update information
+ */
+#define PMINFO_UPDATEINFO_TYPE_FORCE   "force"
+
+/**
+ * @brief Value to be used when get/set update information
+ */
+#define PMINFO_UPDATEINFO_TYPE_OPTIONAL        "optional"
+
+/**
+ * @brief Value to be used when get/set update information
+ */
+#define PMINFO_UPDATEINFO_TYPE_NONE    "none"
+
+typedef enum {
+       PMINFO_UPDATEINFO_NONE = 0,             /**<No update info exists*/
+       PMINFO_UPDATEINFO_FORCE,                /**<Don't launch application if it's not updated*/
+       PMINFO_UPDATEINFO_OPTIONAL              /**<Update exists but not force user to update it*/
+} pkgmgrinfo_updateinfo_update_type;
+
 typedef enum {
        PMINFO_HWACCELERATION_OFF = 0,          /**< Don't use hardware acceleration*/
        PMINFO_HWACCELERATION_ON = 1,           /**< Use hardware acceleration*/
@@ -176,6 +197,11 @@ typedef void *pkgmgrinfo_certinfo_h;
 typedef void *pkgmgrinfo_pkginfo_filter_h;
 
 /**
+ * @brief A handle to get/set package update information
+ */
+typedef void *pkgmgrinfo_updateinfo_h;
+
+/**
  * @brief A handle to filter application information
  */
 typedef void *pkgmgrinfo_appinfo_filter_h;
@@ -196,6 +222,21 @@ typedef void *pkgmgrinfo_appcontrol_h;
 typedef void pkgmgrinfo_client;
 
 /**
+ * @fn int (*pkgmgrinfo_foreach_updateinfo_cb) (const pkgmgrinfo_updateinfo_h handle, void *user_data)
+ *
+ * @brief Specifies the type of function passed to pkgmgrinfo_updateinfo_foreach_updateinfo()
+ *
+ * @param[in] handle the package update info handle
+ * @param[in] user_data user data passed to pkgmgrinfo_foreach_pkg_update info()
+ *
+ * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative.\n
+ *
+ * @see  pkgmgrinfo_updateinfo_foreach_updateinfo()
+ */
+typedef int (*pkgmgrinfo_foreach_updateinfo_cb) (const pkgmgrinfo_updateinfo_h handle,
+                                                       void *user_data);
+
+/**
  * @fn int (*pkgmgrinfo_pkg_list_cb) (const pkgmgrinfo_pkginfo_h handle, void *user_data)
  *
  * @brief Specifies the type of function passed to pkgmgrinfo_pkginfo_get_list(), pkgmgrinfo_pkginfo_filter_foreach_pkginfo()
index e9735ae..ba9a660 100644 (file)
@@ -332,6 +332,151 @@ int pkgmgr_parser_update_app_label_info_in_usr_db(const char *appid, uid_t uid,
 
 int pkgmgr_parser_create_and_initialize_db(uid_t uid);
 
+/**
+ * @fn int pkgmgr_parser_register_pkg_update_info_in_usr_db(pkgmgrinfo_updateinfo_h handle, uid_t uid)
+ * @brief      This API registers update informations of given packages for user specified by uid
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  handle  update information handle
+ * @param[in]  uid     user ID
+ * @return     0 if success, error code(<0) if fail
+ * @pre None
+ * @post        None
+ * @code
+static int register_pkg_update_info(pkgmgrinfo_updateinfo_h update_info, uid_t uid)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(update_info, uid);
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_register_pkg_update_info_in_usr_db(pkgmgrinfo_updateinfo_h handle, uid_t uid);
+
+/**
+ * @fn int pkgmgr_parser_register_pkg_update_info_in_db(pkgmgrinfo_updateinfo_h update_info)
+ * @brief      This API registers update informations of given packages
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  update_info     update information handle
+ * @return     0 if success, error code(<0) if fail
+ * @pre        None
+ * @post       None
+ * @code
+static int register_pkg_update_info(pkgmgrinfo_updateinfo_h update_info)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_register_pkg_update_info_in_db(update_info);
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_register_pkg_update_info_in_db(pkgmgrinfo_updateinfo_h update_info);
+
+/**
+ * @fn int pkgmgr_parser_unregister_pkg_update_info_in_usr_db(const char *pkgid, uid_t uid)
+ * @brief      This API unregister update information of certain package for user specified by uid.
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  pkgid   package ID
+ * @param[in]  uid     user ID
+ * @return     0 if success, error code(<0) if fail
+ * @pre        None
+ * @post       None
+ * @code
+static int register_pkg_update_info(pkgmgrinfo_updateinfo_h update_info, uid_t uid)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_register_pkg_update_info_in_db(update_info, uid);
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_unregister_pkg_update_info_in_usr_db(const char *pkgid, uid_t uid);
+
+/**
+ * @fn int pkgmgr_parser_unregister_pkg_update_info_in_db(const char * pkgid)
+ * @brief      This API unregister update information of certain package
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  pkgid   package ID
+ * @return     0 if success, error code(<0) if fail
+ * @pre        None
+ * @post       None
+ * @code
+static int unregister_pkg_update_info(const char *pkgid)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_unregister_pkg_update_info_in_db(pkgid);
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_unregister_pkg_update_info_in_db(const char *pkgid);
+
+/**
+ * @fn int pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid_t uid)
+ * @brief      This API unregister update information of all packages
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in]  uid     user ID
+ * @return     0 if success, error code(<0) if fail
+ * @pre        None
+ * @post       None
+ * @code
+static int unregister_all_pkg_update_info(uid_t uid)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid);
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid_t uid);
+
+/**
+ * @fn int pkgmgr_parser_unregister_all_pkg_update_info_in_db()
+ * @brief      This API unregisters update information of all packages
+ *
+ * @par                This API is only for internal usage
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @return     0 if success, error code(<0) if fail
+ * @pre None
+ * @post        None
+ * @code
+static int unregister_all_pkg_update_info(void)
+{
+       int ret = 0;
+       ret = pkgmgr_parser_unregister_all_pkg_update_info_in_db();
+       if (ret < 0)
+               return -1;
+       return 0;
+}
+ * @endcode
+ */
+int pkgmgr_parser_unregister_all_pkg_update_info_in_db();
+
 
 /** @} */
 #ifdef __cplusplus
index e0b8097..944651d 100644 (file)
@@ -136,6 +136,14 @@ sqlite3 *pkgmgr_cert_db;
                                                "REFERENCES package_info(package) " \
                                                "ON DELETE CASCADE)"
 
+#define QUERY_CREATE_TABLE_PACKAGE_UPDATE_INFO "CREATE TABLE IF NOT EXISTS package_update_info " \
+                                               "(package TEXT PRIMARY KEY, " \
+                                               "update_version TEXT NOT NULL, " \
+                                               "update_type TEXT NOT NULL DEFAULT 'none', " \
+                                               "FOREIGN KEY(package) " \
+                                               "REFERENCES package_info(package) " \
+                                               "ON DELETE CASCADE)"
+
 #define QUERY_CREATE_TABLE_PACKAGE_APP_INFO "CREATE TABLE IF NOT EXISTS package_app_info " \
                                                "(app_id TEXT PRIMARY KEY NOT NULL, " \
                                                "app_component TEXT NOT NULL, " \
@@ -1207,6 +1215,23 @@ static char *__get_bool(char *value, bool is_true)
        return (is_true) ? "true" : "false";
 }
 
+static int __insert_pkg_updateinfo_in_db(manifest_x *mfx, uid_t uid)
+{
+       char query[MAX_QUERY_LEN] = {'\0'};
+       int ret;
+
+       if (mfx == NULL)
+               return -1;
+
+       sqlite3_snprintf(MAX_QUERY_LEN, query,
+                       "INSERT INTO package_update_info(" \
+                       "package, update_version) VALUES(%Q, %Q)",
+                       mfx->package, mfx->version);
+       ret = __exec_query(query);
+
+       return ret;
+}
+
 /* _PRODUCT_LAUNCHING_ENHANCED_
 *  app->indicatordisplay, app->portraitimg, app->landscapeimg, app->guestmode_appstatus
 */
@@ -1769,6 +1794,12 @@ static int __insert_manifest_info_in_db(manifest_x *mfx, uid_t uid)
                return -1;
        }
 
+       ret = __insert_pkg_updateinfo_in_db(mfx, uid);
+       if (ret == -1) {
+               _LOGE("Package Update Info DB Insert Failed\n");
+               return -1;
+       }
+
        /*Insert in the package_privilege_info DB*/
        for (tmp = mfx->privileges; tmp; tmp = tmp->next) {
                pv = (privilege_x *)tmp->data;
@@ -1974,6 +2005,16 @@ static int __delete_manifest_info_from_db(manifest_x *mfx, uid_t uid)
        }
        memset(query, '\0', MAX_QUERY_LEN);
 
+       /*Delete from Package Update Info DB*/
+       sqlite3_snprintf(MAX_QUERY_LEN, query,
+                "DELETE FROM package_update_info WHERE package=%Q", mfx->package);
+       ret = __exec_query(query);
+       if (ret == -1) {
+               _LOGD("Package Update Info DB Delete Failed\n");
+               return -1;
+       }
+       memset(query, '\0', MAX_QUERY_LEN);
+
        /*Delete from Package Localized Info*/
        sqlite3_snprintf(MAX_QUERY_LEN, query,
                 "DELETE FROM package_localized_info WHERE package=%Q", mfx->package);
@@ -2264,6 +2305,11 @@ API int pkgmgr_parser_initialize_db(uid_t uid)
                _LOGD("package app app privilege DB initialization failed\n");
                return ret;
        }
+       ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_UPDATE_INFO);
+       if (ret == -1) {
+               _LOGD("package update info DB initialization failed\n");
+               return ret;
+       }
        ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_APP_INFO);
        if (ret == -1) {
                _LOGD("package app info DB initialization failed\n");
@@ -2843,6 +2889,168 @@ API int pkgmgr_parser_delete_manifest_info_from_db(manifest_x *mfx)
        return pkgmgr_parser_delete_manifest_info_from_usr_db(mfx, _getuid());
 }
 
+static int _convert_update_type(pkgmgrinfo_updateinfo_update_type type, char **convert_type)
+{
+       if (type == PMINFO_UPDATEINFO_NONE)
+               *convert_type = PMINFO_UPDATEINFO_TYPE_NONE;
+       else if (type == PMINFO_UPDATEINFO_FORCE)
+               *convert_type = PMINFO_UPDATEINFO_TYPE_FORCE;
+       else if (type == PMINFO_UPDATEINFO_OPTIONAL)
+               *convert_type = PMINFO_UPDATEINFO_TYPE_OPTIONAL;
+       else
+               return -1;
+       return 0;
+}
+
+API int pkgmgr_parser_register_pkg_update_info_in_usr_db(pkgmgrinfo_updateinfo_h handle, uid_t uid)
+{
+       int ret;
+       updateinfo_x *update_info;
+       updateinfo_x *prev_update_info;
+       pkgmgrinfo_updateinfo_h prev_update_handle;
+       pkgmgrinfo_pkginfo_h pkginfo;
+       pkgmgrinfo_version_compare_type compare_result;
+       bool is_global_pkg;
+       char query[MAX_QUERY_LEN] = {'\0'};
+       char *convert_type;
+
+       if (handle == NULL)
+               return PMINFO_R_EINVAL;
+
+       update_info = (updateinfo_x *)handle;
+       if (update_info->pkgid == NULL || update_info->version == NULL)
+               return PMINFO_R_EINVAL;
+       if (_convert_update_type(update_info->type, &convert_type) != 0)
+               return PMINFO_R_EINVAL;
+
+       ret = pkgmgrinfo_updateinfo_get_usr_updateinfo(update_info->pkgid,
+                       &prev_update_handle, uid);
+       if (ret != PMINFO_R_OK)
+               return PMINFO_R_ERROR;
+
+       prev_update_info = (updateinfo_x *)prev_update_handle;
+       ret = pkgmgrinfo_compare_package_version(update_info->version,
+                       prev_update_info->version, &compare_result);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_updateinfo_destroy(prev_update_handle);
+               return PMINFO_R_ERROR;
+       }
+
+       if (compare_result == PMINFO_VERSION_SAME &&
+                       prev_update_info->type == PMINFO_UPDATEINFO_NONE) {
+               _LOGI("Given update info version[%s] of pkgid[%s] will be ignored",
+                               update_info->version, update_info->pkgid);
+               pkgmgrinfo_updateinfo_destroy(prev_update_handle);
+               return PMINFO_R_OK;
+       }
+       pkgmgrinfo_updateinfo_destroy(prev_update_handle);
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(update_info->pkgid, uid,
+                       &pkginfo);
+       if (ret != PMINFO_R_OK)
+               return PMINFO_R_ERROR;
+
+       ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+               return PMINFO_R_ERROR;
+       }
+       pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+
+       ret = pkgmgr_parser_check_and_create_db(
+                       (is_global_pkg) ? GLOBAL_USER : uid);
+       if (ret != PMINFO_R_OK)
+               return PMINFO_R_ERROR;
+
+       sqlite3_snprintf(MAX_QUERY_LEN, query,
+                       "UPDATE package_update_info SET update_version=%Q, " \
+                       "update_type=%Q WHERE package=%Q",
+                       update_info->version,
+                       convert_type,
+                       update_info->pkgid);
+
+       ret = __exec_query(query);
+       pkgmgr_parser_close_db();
+
+       return ret;
+}
+
+API int pkgmgr_parser_register_pkg_update_info_in_db(pkgmgrinfo_updateinfo_h handle)
+{
+       return pkgmgr_parser_register_pkg_update_info_in_usr_db(handle, _getuid());
+}
+
+API int pkgmgr_parser_unregister_pkg_update_info_in_usr_db(const char *pkgid, uid_t uid)
+{
+       pkgmgrinfo_pkginfo_h pkginfo = NULL;
+       int ret;
+       bool is_global_pkg;
+       char query[MAX_QUERY_LEN] = {'\0'};
+
+       if (pkgid == NULL)
+               return PMINFO_R_EINVAL;
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &pkginfo);
+       if (ret != PMINFO_R_OK)
+               return -1;
+
+       ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+               return PMINFO_R_ERROR;
+       }
+       pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+       ret = pkgmgr_parser_check_and_create_db((is_global_pkg) ? GLOBAL_USER : uid);
+       if (ret != PMINFO_R_OK)
+               return ret;
+
+       sqlite3_snprintf(MAX_QUERY_LEN, query,
+                       "UPDATE package_update_info SET update_type='none' " \
+                       "WHERE package=%Q", pkgid);
+
+       ret = __exec_query(query);
+       pkgmgr_parser_close_db();
+
+       return ret;
+}
+
+API int pkgmgr_parser_unregister_pkg_update_info_in_db(const char *pkgid)
+{
+       return pkgmgr_parser_unregister_pkg_update_info_in_usr_db(pkgid, _getuid());
+}
+
+API int pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid_t uid)
+{
+       int ret;
+       char query[MAX_QUERY_LEN] = {'\0'};
+       char *error_message = NULL;
+
+       ret = pkgmgr_parser_check_and_create_db(uid);
+       if (ret != 0)
+               return PMINFO_R_ERROR;
+
+       sqlite3_snprintf(MAX_QUERY_LEN, query,
+                       "UPDATE package_update_info SET update_type='none'");
+       ret = sqlite3_exec(pkgmgr_parser_db, query, NULL, NULL, &error_message);
+       if (ret != SQLITE_OK) {
+               _LOGE("Don't execute query = %s error message = %s\n", query,
+                      error_message);
+               sqlite3_free(error_message);
+               pkgmgr_parser_close_db();
+               return PMINFO_R_ERROR;
+       }
+       sqlite3_free(error_message);
+       error_message = NULL;
+       pkgmgr_parser_close_db();
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgr_parser_unregister_all_pkg_update_info_in_db(void)
+{
+       return pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(_getuid());
+}
+
 API int pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(const char *appid, uid_t uid, int is_disable)
 {
        int ret = -1;
diff --git a/src/pkgmgrinfo_updateinfo.c b/src/pkgmgrinfo_updateinfo.c
new file mode 100644 (file)
index 0000000..e599b8c
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Junghyun Yeon(jungh.yeon@samsung.com>,
+ * Jongmyeong Ko(jongmyeong.ko@samsung.com>, Sangyoon Jang(s89.jang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdbool.h>
+#include <ctype.h>
+
+#include <sqlite3.h>
+#include <glib.h>
+
+#include "pkgmgrinfo_basic.h"
+#include "pkgmgrinfo_private.h"
+#include "pkgmgrinfo_debug.h"
+#include "pkgmgr-info.h"
+
+static void __free_update_info(gpointer data)
+{
+       updateinfo_x *update_info = (updateinfo_x *)data;
+       if (update_info == NULL)
+               return;
+
+       if (update_info->pkgid)
+               free((void *)update_info->pkgid);
+       if (update_info->version)
+               free((void *)update_info->version);
+       free((void *)update_info);
+
+}
+
+static int __convert_update_type(const char *type, pkgmgrinfo_updateinfo_update_type *convert_type)
+{
+       if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_NONE,
+                       strlen(PMINFO_UPDATEINFO_TYPE_NONE)) == 0)
+               *convert_type = PMINFO_UPDATEINFO_NONE;
+       else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_FORCE,
+                       strlen(PMINFO_UPDATEINFO_TYPE_FORCE)) == 0)
+               *convert_type = PMINFO_UPDATEINFO_FORCE;
+       else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_OPTIONAL,
+                       strlen(PMINFO_UPDATEINFO_TYPE_OPTIONAL)) == 0)
+               *convert_type = PMINFO_UPDATEINFO_OPTIONAL;
+       else
+               return -1;
+       return 0;
+}
+
+API int pkgmgrinfo_updateinfo_create(
+               pkgmgrinfo_updateinfo_h *updateinfo_handle)
+{
+       updateinfo_x *update_info;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update handle output parameter is NULL\n");
+
+       update_info = (updateinfo_x *)calloc(
+                       1, sizeof(updateinfo_x));
+       if (update_info == NULL) {
+               _LOGE("Out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       *updateinfo_handle = update_info;
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_destroy(
+               pkgmgrinfo_updateinfo_h updateinfo_handle)
+{
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info handle parameter is NULL\n");
+
+       __free_update_info(updateinfo_handle);
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_set_pkgid(
+               pkgmgrinfo_updateinfo_h updateinfo_handle, const char *pkgid)
+{
+       updateinfo_x *updateinfo;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info handle parameter is NULL\n");
+       retvm_if(pkgid == NULL, PMINFO_R_EINVAL,
+                               "pkgid parameter is NULL\n");
+
+       updateinfo = (updateinfo_x *)updateinfo_handle;
+       if (updateinfo->pkgid)
+               free(updateinfo->pkgid);
+
+       updateinfo->pkgid = strdup(pkgid);
+       if (updateinfo->pkgid == NULL) {
+               _LOGE("Out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_set_version(
+               pkgmgrinfo_updateinfo_h updateinfo_handle, const char *version)
+{
+       updateinfo_x *updateinfo;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info handle parameter is NULL\n");
+       retvm_if(version == NULL, PMINFO_R_EINVAL,
+                               "pkgid parameter is NULL\n");
+
+       updateinfo = (updateinfo_x *)updateinfo_handle;
+       if (updateinfo->version)
+               free(updateinfo->version);
+
+       updateinfo->version = strdup(version);
+       if (updateinfo->version == NULL) {
+               _LOGE("Out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_set_type(
+               pkgmgrinfo_updateinfo_h updateinfo_handle,
+               pkgmgrinfo_updateinfo_update_type type)
+{
+       updateinfo_x *updateinfo;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info handle parameter is NULL\n");
+
+       updateinfo = (updateinfo_x *)updateinfo_handle;
+       updateinfo->type = type;
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_get_pkgid(
+               pkgmgrinfo_updateinfo_h updateinfo_handle, char **pkgid)
+{
+       updateinfo_x *update_info;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info node parameter is NULL\n");
+
+       update_info = (updateinfo_x *)updateinfo_handle;
+       if (update_info->pkgid == NULL)
+               return PMINFO_R_ERROR;
+
+       *pkgid = update_info->pkgid;
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_get_version(
+               pkgmgrinfo_updateinfo_h updateinfo_handle, char **version)
+{
+       updateinfo_x *update_info;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info node parameter is NULL\n");
+
+       update_info = (updateinfo_x *)updateinfo_handle;
+       if (update_info->version == NULL)
+               return PMINFO_R_ERROR;
+
+       *version = update_info->version;
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_get_update_type(
+               pkgmgrinfo_updateinfo_h updateinfo_handle,
+               pkgmgrinfo_updateinfo_update_type *type)
+{
+       updateinfo_x *update_info;
+
+       retvm_if(updateinfo_handle == NULL, PMINFO_R_EINVAL,
+                       "Update info node parameter is NULL\n");
+
+       update_info = (updateinfo_x *)updateinfo_handle;
+       *type = update_info->type;
+
+       return PMINFO_R_OK;
+}
+
+static int _get_pkg_updateinfo_from_db(const char *pkgid,
+               GSList **update_info_list, uid_t uid)
+{
+       char *dbpath;
+       char *type;
+       char query[MAX_QUERY_LEN] = { '\0' };
+       int ret;
+       int idx;
+       sqlite3 *db;
+       sqlite3_stmt *stmt;
+       updateinfo_x *update_info = NULL;
+       pkgmgrinfo_updateinfo_update_type convert_type;
+
+       dbpath = getUserPkgParserDBPathUID(uid);
+       if (dbpath == NULL)
+               return PMINFO_R_ERROR;
+
+       ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY);
+       if (ret != SQLITE_OK) {
+               _LOGD("failed to open db: %d", ret);
+               free(dbpath);
+               return -1;
+       }
+
+       if (pkgid == NULL)
+               sqlite3_snprintf(MAX_QUERY_LEN, query,
+                                               "SELECT package, update_version, update_type " \
+                                               "FROM package_update_info");
+       else
+               sqlite3_snprintf(MAX_QUERY_LEN, query,
+                                               "SELECT package, update_version, update_type " \
+                                               "FROM package_update_info WHERE package=%Q",
+                                               pkgid);
+
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("Don't execute query = %s error message = %s\n", query,
+               sqlite3_errmsg(db));
+               free(dbpath);
+               return -1;
+       }
+
+       while (sqlite3_step(stmt) == SQLITE_ROW) {
+               update_info = calloc(1, sizeof(updateinfo_x));
+               if (update_info == NULL) {
+                       _LOGE("Out of memory");
+                       free(dbpath);
+                       sqlite3_finalize(stmt);
+                       sqlite3_close_v2(db);
+                       return -1;
+               }
+               idx = 0;
+               _save_column_str(stmt, idx++, &update_info->pkgid);
+               _save_column_str(stmt, idx++, &update_info->version);
+               _save_column_str(stmt, idx, &type);
+               ret = __convert_update_type(type, &convert_type);
+               if (ret != 0) {
+                       __free_update_info(update_info);
+                       free(dbpath);
+                       sqlite3_finalize(stmt);
+                       sqlite3_close_v2(db);
+                       return -1;
+               }
+               update_info->type = convert_type;
+               *update_info_list = g_slist_append(*update_info_list, update_info);
+       }
+
+       free(dbpath);
+       sqlite3_finalize(stmt);
+       sqlite3_close_v2(db);
+
+       return 0;
+}
+
+API int pkgmgrinfo_updateinfo_get_usr_updateinfo(const char *pkgid,
+               pkgmgrinfo_updateinfo_h *update_handle, uid_t uid)
+{
+       int ret;
+       pkgmgrinfo_pkginfo_h pkginfo = NULL;
+       bool is_global_pkg;
+       updateinfo_x *update_info;
+       GSList *info_list = NULL;
+
+       if (update_handle == NULL || pkgid == NULL)
+               return PMINFO_R_EINVAL;
+
+       update_info = calloc(1, sizeof(updateinfo_x));
+       if (update_info == NULL) {
+               _LOGE("Out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &pkginfo);
+       if (ret != PMINFO_R_OK) {
+               free(update_info);
+               return ret;
+       }
+       ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
+       if (ret != PMINFO_R_OK) {
+               free(update_info);
+               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+               return ret;
+       }
+       pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+
+       ret = _get_pkg_updateinfo_from_db(pkgid, &info_list,
+                       (is_global_pkg) ? GLOBAL_USER : uid);
+
+       if (ret != PMINFO_R_OK) {
+               g_slist_free_full(info_list, __free_update_info);
+               return PMINFO_R_ERROR;
+       }
+       *update_handle = (pkgmgrinfo_updateinfo_h)info_list->data;
+       g_slist_free(info_list);
+
+       return ret;
+}
+
+API int pkgmgrinfo_updateinfo_get_updateinfo(const char *pkgid,
+               pkgmgrinfo_updateinfo_h *update_handle)
+{
+       return pkgmgrinfo_updateinfo_get_usr_updateinfo(pkgid, update_handle, _getuid());
+}
+
+API int pkgmgrinfo_updateinfo_usr_foreach_updateinfo(uid_t uid,
+               pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data)
+{
+       int ret;
+       GSList *info_list;
+       GSList *tmp_list;
+
+       if (callback == NULL)
+               return PMINFO_R_EINVAL;
+
+       info_list = calloc(1, sizeof(updateinfo_x));
+       if (info_list == NULL) {
+               _LOGE("Out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       ret = _get_pkg_updateinfo_from_db(NULL, &info_list, uid);
+       if (ret != 0) {
+               _LOGE("Failed to get pkg update info for user[%d]", (int)uid);
+               pkgmgrinfo_updateinfo_destroy(info_list);
+               return PMINFO_R_ERROR;
+       }
+
+       ret = _get_pkg_updateinfo_from_db(NULL, &info_list, GLOBAL_USER);
+       if (ret != 0) {
+               _LOGE("Failed to get pkg update info for user[%d]",
+                               (int)GLOBAL_USER);
+               pkgmgrinfo_updateinfo_destroy(info_list);
+               return PMINFO_R_ERROR;
+       }
+
+       for (tmp_list = info_list; tmp_list; tmp_list = g_slist_next(tmp_list)) {
+               ret = callback((pkgmgrinfo_updateinfo_h)tmp_list->data, user_data);
+               if (ret < 0)
+                       break;
+       }
+
+       g_slist_free_full(info_list, __free_update_info);
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_updateinfo_foreach_updateinfo(
+               pkgmgrinfo_foreach_updateinfo_cb callback, void *user_data)
+{
+       return pkgmgrinfo_updateinfo_usr_foreach_updateinfo(_getuid(),
+                       callback, user_data);
+}