}
+void MsgThreadChangeListener(msg_storage_change_type_t storageChangeType, msg_thread_id_t threadId)
+{
+ MSG_BEGIN();
+
+ MSG_DEBUG("StorageChangeType : [%d], thread ID : [%d]", storageChangeType, threadId);
+
+ /* establish connection to msgfw daemon */
+ MsgIpcClientSocket client;
+ try {
+ client.connect(MSG_SOCKET_PATH);
+ } catch (MsgException& e) {
+ MSG_FATAL("%s", e.what());
+ return;
+ }
+
+ /* composing command */
+ int cmdSize = sizeof(MSG_CMD_S) + sizeof(msg_thread_id_t);
+
+ char cmdBuf[cmdSize];
+ bzero(cmdBuf, cmdSize);
+
+ MSG_CMD_S* pCmd = (MSG_CMD_S*)cmdBuf;
+
+ /* Set Command Parameters */
+ pCmd->cmdType = MSG_CMD_PLG_THREAD_CHANGE_IND;
+
+ memset(pCmd->cmdCookie, 0x00, MAX_COOKIE_LEN);
+
+ memcpy((void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN), &threadId, sizeof(msg_thread_id_t));
+ memcpy((void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN+sizeof(msg_thread_id_t)), &storageChangeType, sizeof(msg_storage_change_type_t));
+
+ /* Send Command to Transaction Manager */
+ client.write(cmdBuf, cmdSize);
+
+ /* Receive result from Transaction Manager */
+ MSG_DEBUG("Waiting result for STORAGE CHANGE");
+
+ char *temp = NULL;
+ unique_ptr<char*, void(*)(char**)> wrap(&temp, unique_ptr_deleter);
+ unsigned int len;
+ client.read(&temp, &len);
+
+ /* close connection to msgfw daemon */
+ client.close();
+
+ MSG_END();
+}
+
+
msg_error_t MsgIncomingMessageListener(MSG_MESSAGE_INFO_S *pMsg)
{
MSG_BEGIN();
MSG_PLUGIN_LISTENER_S fwListener = {0};
fwListener.pfSentStatusCb = &MsgSentStatusListener;
fwListener.pfStorageChangeCb = &MsgStorageChangeListener;
+ fwListener.pfThreadChangeCb = &MsgThreadChangeListener;
fwListener.pfMsgIncomingCb = &MsgIncomingMessageListener;
fwListener.pfInitSimBySatCb = &MsgInitSimBySatListener;
fwListener.pfSyncMLMsgIncomingCb = &MsgIncomingSyncMLMessageListener;
}
dbHandle->endTrans(true);
+ /* Update Thread Callback */
+ if (bCheckIndication == true && MsgExistConversation(dbHandle, convId) == true)
+ MsgTransactionManager::instance()->broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_UPDATE, convId);
+
if (msgType.mainType == MSG_SMS_TYPE && folderId == MSG_INBOX_ID) {
msgType.classType = MSG_CLASS_NONE;
char sqlQuery[MAX_QUERY_LEN+1];
- queue<msg_thread_id_t> threadList;
+ queue<msg_thread_id_t> threadList, threadList2;
#ifdef FEATURE_SMS_CDMA
const char *tableList[] = {MSGFW_PUSH_MSG_TABLE_NAME, MSGFW_CB_MSG_TABLE_NAME,
for (int i = 1; i <= rowCnt; i++) {
MSG_DEBUG("thread ID : %d", dbHandle->getColumnToInt(i));
threadList.push((msg_thread_id_t)dbHandle->getColumnToInt(i));
+ threadList2.push((msg_thread_id_t)dbHandle->getColumnToInt(i));
}
dbHandle->freeTable();
dbHandle->endTrans(true);
+ /* Update Thread Callback */
+ while (!threadList2.empty()) {
+ msg_thread_id_t cur_thread_id = threadList2.front();
+ if (MsgExistConversation(dbHandle, cur_thread_id) == true)
+ MsgTransactionManager::instance()->broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_UPDATE, cur_thread_id);
+
+ threadList2.pop();
+ }
+
/* Set pMsgIdList */
if (pMsgIdList != NULL && pToDeleteMsgIdList->nCount > 0) {
pMsgIdList->nCount = pToDeleteMsgIdList->nCount;
char sqlQuery[MAX_QUERY_LEN+1];
- queue<msg_thread_id_t> threadList1, threadList2;
+ queue<msg_thread_id_t> threadList1, threadList2, threadList3;
#ifdef FEATURE_SMS_CDMA
const char *tableList[] = {MMS_PLUGIN_MESSAGE_TABLE_NAME, MSGFW_MMS_PREVIEW_TABLE_NAME,
MSG_DEBUG("thread ID : %d", dbHandle->getColumnToInt(i));
threadList1.push((msg_thread_id_t)dbHandle->getColumnToInt(i));
threadList2.push((msg_thread_id_t)dbHandle->getColumnToInt(i));
+ threadList3.push((msg_thread_id_t)dbHandle->getColumnToInt(i));
}
dbHandle->freeTable();
return err;
}
+ /* Update Thread Callback */
+ while (!threadList3.empty()) {
+ msg_thread_id_t cur_thread_id = threadList3.front();
+ if (MsgExistConversation(dbHandle, cur_thread_id) == true)
+ MsgTransactionManager::instance()->broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_UPDATE, cur_thread_id);
+
+ threadList3.pop();
+ }
+
if (g_idle_add(resetNotification, NULL) == 0) {
MSG_DEBUG("resetNotification() Error");
}
}
+int MsgRegThreadChangeCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent)
+{
+ /* input check */
+ if (!pCmd || !ppEvent) {
+ MSG_DEBUG("pCmd or ppEvent is null");
+ return 0;
+ }
+
+ /* Get Message Request */
+ int listenerFd = 0;
+ memcpy(&listenerFd, (void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN), sizeof(int));
+ MSG_DEBUG("Registering storage change CB for %d", listenerFd);
+
+ /* storing dst fd in list */
+ MsgTransactionManager::instance()->setThreadChangeCB(listenerFd);
+
+ /* Make Event Data */
+ int eventSize = MsgMakeEvent(NULL, 0, MSG_EVENT_REG_THREAD_CHANGE_CB, MsgException::SUCCESS, (void**)ppEvent);
+
+ return eventSize;
+}
+
+
int MsgRegIncomingReportMsgCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent)
{
/* input check */
return eventSize;
}
+int MsgThreadChangeHandler(const MSG_CMD_S *pCmd, char **ppEvent)
+{
+ /* input check */
+ if (!pCmd || !ppEvent) {
+ MSG_DEBUG("pCmd or ppEvent is null");
+ return 0;
+ }
+
+ msg_storage_change_type_t storageChangeType;
+ msg_thread_id_t threadId;
+
+ memcpy(&threadId, (void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN), sizeof(msg_thread_id_t));
+ memcpy(&storageChangeType, (void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN+sizeof(msg_thread_id_t)), sizeof(msg_storage_change_type_t));
+
+ char* encodedData = NULL;
+ unique_ptr<char*, void(*)(char**)> buf(&encodedData, unique_ptr_deleter);
+
+ int eventSize = 0;
+
+ MSG_DEBUG("storageChangeType : [%d], thread Id : [%d]", storageChangeType, threadId);
+
+ /* broadcast to listener threads, here */
+ MsgTransactionManager::instance()->broadcastThreadChangeCB(MSG_SUCCESS, storageChangeType, threadId);
+
+ /* Make Event Data to Client */
+ eventSize = MsgMakeEvent(NULL, 0, MSG_EVENT_PLG_THREAD_CHANGE_IND, MSG_SUCCESS, (void**)ppEvent);
+
+ return eventSize;
+}
+
int MsgResendMessageHandler(const MSG_CMD_S *pCmd, char **ppEvent)
{
msg_error_t err = MSG_SUCCESS;
#include <sys/socket.h>
#include <sys/stat.h>
#include <pthread.h>
+#include <algorithm>
#include <bundle.h>
#include <eventsystem.h>
#include "MsgContact.h"
#include "MsgIpcSocket.h"
#include "MsgGconfWrapper.h"
+#include "MsgSqliteWrapper.h"
+#include "MsgUtilStorage.h"
#include "MsgUtilFunction.h"
#include "MsgUtilFile.h"
#include "MsgLbs.h"
#define MSG_CHECK_PRIVILEGE
+std::list<msg_thread_id_t> cur_conv_list;
+
void MsgMakeErrorEvent(MSG_CMD_TYPE_T cmdType, msg_error_t errType, int *pEventSize, char **ppEvent)
{
if (*ppEvent) delete [] *ppEvent;
pMsgEvent->result = errType;
}
+void initConversationList()
+{
+ MsgDbHandler *dbHandle = getDbHandle();
+
+ msg_error_t err = MSG_SUCCESS;
+ int rowCnt = 0;
+
+ char sqlQuery[MAX_QUERY_LEN+1] = {0};
+ snprintf(sqlQuery, MAX_QUERY_LEN, "SELECT CONV_ID FROM %s;", MSGFW_CONVERSATION_TABLE_NAME);
+
+ err = dbHandle->getTable(sqlQuery, &rowCnt, NULL);
+ if (err != MSG_SUCCESS) {
+ MSG_DEBUG("getTable failed [%d]", err);
+ dbHandle->freeTable();
+ return;
+ }
+
+ for (int i = 0; i < rowCnt; i++)
+ cur_conv_list.push_back((msg_thread_id_t)dbHandle->getColumnToInt(i+1));
+
+ dbHandle->freeTable();
+}
+
/*==================================================================================================
IMPLEMENTATION OF MsgTransactionManager - Member Functions
==================================================================================================*/
handlerMap.clear();
+ initConversationList();
+
/* Fill in mMsgHandlers, as given in the below. */
handlerMap[MSG_CMD_ADD_MSG] = &MsgAddMessageHandler;
handlerMap[MSG_CMD_ADD_SYNCML_MSG] = &MsgAddSyncMLMessageHandler;
handlerMap[MSG_CMD_REG_SENT_STATUS_CB] = &MsgRegSentStatusCallbackHandler;
handlerMap[MSG_CMD_REG_STORAGE_CHANGE_CB] = &MsgRegStorageChangeCallbackHandler;
+ handlerMap[MSG_CMD_REG_THREAD_CHANGE_CB] = &MsgRegThreadChangeCallbackHandler;
handlerMap[MSG_CMD_REG_INCOMING_MSG_CB] = &MsgRegIncomingMsgCallbackHandler;
handlerMap[MSG_CMD_REG_INCOMING_MMS_CONF_MSG_CB] = &MsgRegIncomingMMSConfMsgCallbackHandler;
handlerMap[MSG_CMD_REG_INCOMING_SYNCML_MSG_CB] = &MsgRegIncomingSyncMLMsgCallbackHandler;
case MSG_CMD_GET_MEMSIZE:
case MSG_CMD_BACKUP_MESSAGE:
case MSG_CMD_REG_STORAGE_CHANGE_CB:
+ case MSG_CMD_REG_THREAD_CHANGE_CB:
case MSG_CMD_GET_REPORT_STATUS:
case MSG_CMD_GET_THREAD_ID_BY_ADDRESS:
case MSG_CMD_GET_THREAD_INFO:
}
+void MsgTransactionManager::setThreadChangeCB(int listenerFd)
+{
+ if (listenerFd <= 0)
+ THROW(MsgException::INVALID_PARAM, "InParam Error: listenerFd %d", listenerFd);
+
+ MsgMutexLocker lock(mx);
+
+ threadChangeFdMap[listenerFd] = true;
+}
+
+
void MsgTransactionManager::setReportMsgCB(int listenerFd)
{
if (listenerFd <= 0)
}
+bool compare_func(msg_thread_id_t const &a, msg_thread_id_t const &b)
+{
+ if (a == b)
+ return true;
+
+ return false;
+}
+
+
void MsgTransactionManager::broadcastStorageChangeCB(const msg_error_t err, const msg_storage_change_type_t storageChangeType, const msg_id_list_s *pMsgIdList)
{
MSG_BEGIN();
write(it->first, pEventData, eventSize);
}
+ MsgDbHandler *dbHandle = getDbHandle();
+ MsgSimpleQ<msg_thread_id_t> updatedConvQ;
+
+ if (storageChangeType == MSG_STORAGE_CHANGE_INSERT) {
+ for (int i = 0; i < pMsgIdList->nCount; i++) {
+ msg_thread_id_t conv_id = MsgGetThreadId(dbHandle, pMsgIdList->msgIdList[i]);
+ bool found = (std::find(cur_conv_list.begin(), cur_conv_list.end(), conv_id) != cur_conv_list.end());
+
+ if (found == false) {
+ cur_conv_list.push_back(conv_id);
+ updatedConvQ.push_back(conv_id);
+ broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_INSERT, conv_id);
+ } else {
+ if (updatedConvQ.checkExist(conv_id, compare_func) == false) {
+ broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_UPDATE, conv_id);
+ updatedConvQ.push_back(conv_id);
+ }
+ }
+ }
+ } else if (storageChangeType == MSG_STORAGE_CHANGE_UPDATE) {
+ for (int i = 0; i < pMsgIdList->nCount; i++) {
+ msg_thread_id_t conv_id = MsgGetThreadId(dbHandle, pMsgIdList->msgIdList[i]);
+ if (updatedConvQ.checkExist(conv_id, compare_func) == false) {
+ broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_UPDATE, conv_id);
+ updatedConvQ.push_back(conv_id);
+ }
+ }
+ } else if (storageChangeType == MSG_STORAGE_CHANGE_DELETE) {
+ std::list<msg_thread_id_t>::iterator it = cur_conv_list.begin();
+ for (; it != cur_conv_list.end(); ) {
+ if (MsgExistConversation(dbHandle, *it) == false) {
+ broadcastThreadChangeCB(MSG_SUCCESS, MSG_STORAGE_CHANGE_DELETE, *it);
+ it = cur_conv_list.erase(it);
+ } else{
+ it++;
+ }
+ }
+ }
+
+ updatedConvQ.clear();
+
+ MSG_END();
+}
+
+
+void MsgTransactionManager::broadcastThreadChangeCB(const msg_error_t err, const msg_storage_change_type_t storageChangeType, const msg_thread_id_t threadId)
+{
+ MSG_BEGIN();
+
+ MSG_DEBUG("storageChangeType [%d], threadId [%d]", storageChangeType, threadId);
+
+ int dataSize = 0;
+
+ char* pEventData = NULL;
+ unique_ptr<char*, void(*)(char**)> eventBuf(&pEventData, unique_ptr_deleter);
+
+ char* encodedData = NULL;
+ unique_ptr<char*, void(*)(char**)> buf(&encodedData, unique_ptr_deleter);
+
+ /* Encoding Thread Change Data */
+ dataSize = MsgEncodeThreadChangeData(storageChangeType, threadId, &encodedData);
+
+ int eventSize = MsgMakeEvent(encodedData, dataSize, MSG_EVENT_PLG_THREAD_CHANGE_IND, err, (void**)(&pEventData));
+
+ MsgMutexLocker lock(mx);
+
+ fd_map::iterator it = threadChangeFdMap.begin();
+
+ for (; it != threadChangeFdMap.end(); it++) {
+ MSG_DEBUG("Send Thread Change Callback to listener %d", it->first);
+ write(it->first, pEventData, eventSize);
+ }
+
MSG_END();
}
#endif
MSG_CMD_CHECK_PERMISSION,
+ MSG_CMD_REG_THREAD_CHANGE_CB,
+ MSG_CMD_PLG_THREAD_CHANGE_IND,
+
/* end of MSG_CMD; new CMD should be defined before MSG_CMD_NUM */
MSG_CMD_NUM
};
MSG_EVENT_PLG_CHECK_UNIQUENESS,
#endif
MSG_EVENT_CHECK_PERMISSION,
+ MSG_EVENT_REG_THREAD_CHANGE_CB,
+ MSG_EVENT_PLG_THREAD_CHANGE_IND,
/* Enums that does not match _MSG_CMD_TYPE_E */
MSG_EVENT_PLG_REPORT_MSG_INCOMING_IND,
/* framework defined callbacks. */
typedef void (*MsgPlgOnSentStatus)(MSG_SENT_STATUS_S *pSentStatus);
typedef void (*MsgPlgOnStorageChange)(msg_storage_change_type_t storageChangeType, msg_id_list_s *pMsgIdList);
+typedef void (*MsgPlgOnThreadChange)(msg_storage_change_type_t storageChangeType, msg_thread_id_t threadId);
typedef msg_error_t (*MsgPlgOnMsgIncoming)(MSG_MESSAGE_INFO_S *pMsgInfo);
typedef msg_error_t (*MsgPlgOnInitSimBySat)(void);
typedef msg_error_t (*MsgPlgOnSyncMLMsgIncoming)(MSG_SYNCML_MESSAGE_DATA_S *pSyncMLData);
struct _MSG_PLUGIN_LISTENER_S {
MsgPlgOnSentStatus pfSentStatusCb; /** The function pointer of sent status callback. */
MsgPlgOnStorageChange pfStorageChangeCb; /** The function pointer of storage change callback. */
+ MsgPlgOnThreadChange pfThreadChangeCb; /** The function pointer of thread change callback. */
MsgPlgOnMsgIncoming pfMsgIncomingCb; /** The function pointer of receive message callback. */
MsgPlgOnInitSimBySat pfInitSimBySatCb; /** The function pointer of init SIM callback. */
MsgPlgOnSyncMLMsgIncoming pfSyncMLMsgIncomingCb; /** The function pointer of receive syncML message callback. */
int MsgRegIncomingLBSMsgCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent);
int MsgRegSyncMLMsgOperationCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent);
int MsgRegStorageChangeCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent);
+int MsgRegThreadChangeCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent);
int MsgStorageChangeHandler(const MSG_CMD_S *pCmd, char **ppEvent);
+int MsgThreadChangeHandler(const MSG_CMD_S *pCmd, char **ppEvent);
int MsgRegIncomingReportMsgCallbackHandler(const MSG_CMD_S *pCmd, char **ppEvent);
int MsgSentStatusHandler(const MSG_CMD_S *pCmd, char **ppEvent);
void setJavaMMSList(MSG_CMD_REG_INCOMING_JAVAMMS_TRID_S *pTrId);
void setSyncMLMsgOperationCB(MSG_CMD_REG_SYNCML_MSG_OPERATION_CB_S *pCbinfo);
void setStorageChangeCB(int listenerFd);
+ void setThreadChangeCB(int listenerFd);
void setReportMsgCB(int listenerFd);
javamms_list &getJavaMMSList();
void broadcastLBSMsgCB(const msg_error_t err, const MSG_LBS_MESSAGE_DATA_S *lbsData);
void broadcastSyncMLMsgOperationCB(const msg_error_t err, const int msgId, const int extId);
void broadcastStorageChangeCB(const msg_error_t err, const msg_storage_change_type_t storageChangeType, const msg_id_list_s *pMsgIdList);
+ void broadcastThreadChangeCB(const msg_error_t err, const msg_storage_change_type_t storageChangeType, const msg_thread_id_t threadId);
void broadcastReportMsgCB(const msg_error_t err, const msg_report_type_t reportMsgType, const MSG_MESSAGE_INFO_S *pMsgInfo);
bool initCynara();
syncmlop_list operationSyncMLMsgCBList;
fd_map storageChangeFdMap;
+ fd_map threadChangeFdMap;
fd_map reportMsgCBFdMap;
MsgMutex mx; /* mutex for shared resources like callback listeners */
/**
+ * @brief Registers a callback function about the change of thread status to Message handle.
+ * @details This API is used to register a callback function about the change of thread status "msg_thread_change_cb" to Message handle.
+ *
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/message.read
+ *
+ * @remarks This function MUST be called after Message handle is opened.
+ *
+ * @param[in] handle The Message handle
+ * @param[in] cb The function to be called
+ * @param[in] user_param A pointer to user data
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ *
+ * @retval MSG_SUCCESS Success in operation
+ * @retval MSG_ERR_INVALID_PARAMETER Parameter is invalid
+ * @retval MSG_ERR_MSGHANDLE_NOT_CONNECTED Message handle is not connected
+ * @retval MSG_ERR_MEMORY_ERROR Memory is error
+ * @retval MSG_ERR_PERMISSION_DENIED The application does not have the privilege to call this method
+ * @retval MSG_ERR_NOT_SUPPORTED Not supported
+ */
+
+int msg_reg_thread_change_callback(msg_handle_t handle, msg_thread_change_cb cb, void *user_param);
+
+
+/**
* @brief Gets the report status information of message.
*
* @since_tizen 2.3
typedef void (*msg_storage_change_cb)(msg_handle_t handle, msg_storage_change_type_t storageChangeType, msg_id_list_s *pMsgIdList, void *user_param);
+/** @brief Called when the threads of message framework is changed.
+ * Applications SHOULD implement this callback function and register it into Message handle.
+ * For how to register this callback function, please refer to msg_reg_thread_change_callback().
+ * The callback function runs in the application process, not in the framework process.
+ * @param[in] handle The Message handle.
+ * @param[in] user_param A pointer to user data
+ */
+typedef void (*msg_thread_change_cb)(msg_handle_t handle, msg_storage_change_type_t storageChangeType, msg_thread_id_t threadId, void *user_param);
+
+
/*==================================================================================================
ENUMS
==================================================================================================*/
msg_error_t getRejectMsgList(const char *pNumber, msg_struct_list_s *pRejectMsgList);
msg_error_t regStorageChangeCallback(msg_storage_change_cb onStorageChange, void *pUserParam);
+ msg_error_t regThreadChangeCallback(msg_thread_change_cb onThreadChange, void *pUserParam);
msg_error_t getReportStatus(msg_message_id_t msg_id, msg_struct_list_s *report_list);
msg_error_t getThreadIdByAddress(msg_struct_list_s *pAddrList, msg_thread_id_t *pThreadId);
msg_error_t getThreadIdByAddress(msg_list_handle_t msg_address_list, msg_thread_id_t *pThreadId);
typedef struct {
MsgHandle* hAddr;
int fd;
+ msg_thread_change_cb pfThreadChangeCB;
+ void* userParam;
+} MSG_THREAD_CHANGE_CB_ITEM_S;
+
+
+typedef struct {
+ MsgHandle* hAddr;
+ int fd;
msg_report_msg_incoming_cb pfReportMsgIncomingCB;
void* userParam;
} MSG_REPORT_INCOMING_CB_ITEM_S;
typedef std::list<MSG_LBS_INCOMING_CB_ITEM_S> MsgNewLBSMessageCBList;
typedef std::list<MSG_SYNCML_OPERATION_CB_ITEM_S> MsgOperationSyncMLMessageCBList;
typedef std::list<MSG_STORAGE_CHANGE_CB_ITEM_S> MsgStorageChangeCBList;
+typedef std::list<MSG_THREAD_CHANGE_CB_ITEM_S> MsgThreadChangeCBList;
typedef std::list<MSG_REPORT_INCOMING_CB_ITEM_S> MsgReportMessageCBList;
typedef std::set<MsgHandle*> handle_set;
bool regLBSMessageIncomingEventCB(MsgHandle* pMsgHandle, int fd, msg_lbs_msg_incoming_cb pfNewLBSMsgIncoming, void *pUserParam);
bool regSyncMLMessageOperationEventCB(MsgHandle* pMsgHandle, int fd, msg_syncml_msg_operation_cb pfSyncMLMessageOperation, void *pUserParam);
bool regStorageChangeEventCB(MsgHandle* pMsgHandle, int fd, msg_storage_change_cb pfStorageChangeOperation, void *pUserParam);
+ bool regThreadChangeEventCB(MsgHandle* pMsgHandle, int fd, msg_thread_change_cb pfThreadChangeOperation, void *pUserParam);
bool regReportMsgIncomingCB(MsgHandle* pMsgHandle, int fd, msg_report_msg_incoming_cb pfReportMessage, void *pUserParam);
void clearListOfClosedHandle(MsgHandle* pMsgHandle);
MsgNewLBSMessageCBList newLBSMessageCBList;
MsgOperationSyncMLMessageCBList operationSyncMLMessageCBList;
MsgStorageChangeCBList storageChangeCBList;
+ MsgThreadChangeCBList threadChangeCBList;
MsgReportMessageCBList reportMessageCBList;
GIOChannel *channel;
int MsgEncodeStorageChangeData(const msg_storage_change_type_t storageChangeType, const msg_id_list_s *pMsgIdList, char **ppDest);
+int MsgEncodeThreadChangeData(const msg_storage_change_type_t storageChangeType, const msg_thread_id_t threadId, char **ppDest);
+
int MsgEncodeReportMsgData(const msg_report_type_t msgReportType, const MSG_MESSAGE_INFO_S *pMsgInfo, char **ppDest);
int MsgEncodeReportStatus(MSG_REPORT_STATUS_INFO_S* pReportStatus, int count, char **ppDest);
return err;
}
+EXPORT_API int msg_reg_thread_change_callback(msg_handle_t handle, msg_thread_change_cb cb, void *user_param)
+{
+ CHECK_MSG_SUPPORTED(MSG_TELEPHONY_SMS_FEATURE);
+ msg_error_t err = MSG_SUCCESS;
+
+ if (handle == NULL || cb == NULL)
+ return MSG_ERR_INVALID_PARAMETER;
+
+ MsgHandle* pHandle = (MsgHandle*)handle;
+
+ try {
+ err = pHandle->regThreadChangeCallback(cb, user_param);
+ } catch (MsgException& e) {
+ MSG_FATAL("%s", e.what());
+ if (e.errorCode() == MsgException::SERVER_READY_ERROR)
+ return MSG_ERR_PERMISSION_DENIED;
+ else
+ return MSG_ERR_CALLBACK_ERROR;
+ }
+
+ return err;
+
+}
+
EXPORT_API int msg_get_report_status(msg_handle_t handle, msg_message_id_t msg_id, msg_struct_list_s *report_list)
{
CHECK_MSG_SUPPORTED(MSG_TELEPHONY_SMS_FEATURE);
}
+msg_error_t SmsPluginEventHandler::callbackThreadChange(msg_storage_change_type_t storageChangeType, msg_thread_id_t threadId)
+{
+ /* Callback to MSG FW */
+ listener.pfThreadChangeCb(storageChangeType, threadId);
+
+ return MSG_SUCCESS;
+}
+
+
void SmsPluginEventHandler::convertTpduToMsginfo(SMS_TPDU_S *pTpdu, MSG_MESSAGE_INFO_S *msgInfo)
{
switch (pTpdu->tpduType) {
#include "MsgNotificationWrapper.h"
#include "SmsPluginMain.h"
#include "SmsPluginSimMsg.h"
+#include "SmsPluginEventHandler.h"
#include "SmsPluginStorage.h"
dbHandle->endTrans(true);
+ memset(sqlQuery, 0x00, sizeof(sqlQuery));
+ snprintf(sqlQuery, sizeof(sqlQuery), "SELECT CONV_ID FROM %s WHERE CONV_ID = %d;", MSGFW_CONVERSATION_TABLE_NAME, convId);
+ if (dbHandle->prepareQuery(sqlQuery) != MSG_SUCCESS)
+ return MSG_ERR_DB_PREPARE;
+
+ if (dbHandle->stepQuery() == MSG_ERR_DB_ROW)
+ SmsPluginEventHandler::instance()->callbackThreadChange(MSG_STORAGE_CHANGE_UPDATE, convId);
+
+ dbHandle->finalizeQuery();
+
signed char folder_id = (signed char)folderId;
if (folder_id == MSG_INBOX_ID) {
msgType.classType = MSG_CLASS_NONE;
msg_error_t callbackCBMsgIncoming(MSG_CB_MSG_S *pCbMsg, MSG_MESSAGE_INFO_S *pMsgInfo);
msg_error_t callbackInitSimBySat();
msg_error_t callbackStorageChange(msg_storage_change_type_t storageChangeType, MSG_MESSAGE_INFO_S *pMsgInfo);
+ msg_error_t callbackThreadChange(msg_storage_change_type_t storageChangeType, msg_thread_id_t threadId);
msg_error_t handleSimMsg(MSG_MESSAGE_INFO_S *pMsgInfo, int *simIdList, msg_message_id_t *retMsgId, int listSize);
msg_error_t updateIMSI(int sim_idx);
void handleSimMemoryFull(int simIndex);
case MSG_EVENT_PLG_INCOMING_SYNCML_MSG_IND:
case MSG_EVENT_PLG_INCOMING_LBS_MSG_IND:
case MSG_EVENT_PLG_STORAGE_CHANGE_IND:
+ case MSG_EVENT_PLG_THREAD_CHANGE_IND:
case MSG_EVENT_PLG_INCOMING_CB_MSG_IND:
case MSG_EVENT_PLG_INCOMING_PUSH_MSG_IND:
case MSG_EVENT_PLG_REPORT_MSG_INCOMING_IND:
}
+msg_error_t MsgHandle::regThreadChangeCallback(msg_thread_change_cb onThreadChange, void *pUserParam)
+{
+ if (!onThreadChange)
+ THROW(MsgException::INVALID_PARAM, "onThreadChange is null");
+
+ MsgProxyListener* eventListener = MsgProxyListener::instance();
+
+ eventListener->start(this);
+
+ int remoteFd = eventListener->getRemoteFd(); /* fd that is reserved to the "listener thread" by msgfw daemon */
+
+ if (remoteFd == -1 ) {
+ eventListener->stop();
+ return MSG_ERR_INVALID_MSGHANDLE;
+ }
+
+ if (eventListener->regThreadChangeEventCB(this, remoteFd, onThreadChange, pUserParam) == false) {
+ eventListener->stop();
+ return MSG_ERR_INVALID_PARAMETER;
+ }
+
+ /* Allocate Memory to Command Data */
+ int cmdSize = sizeof(MSG_CMD_S) + sizeof(int); /* cmd type, listenerFd */
+ char cmdBuf[cmdSize];
+ bzero(cmdBuf, cmdSize);
+ MSG_CMD_S* pCmd = (MSG_CMD_S*) cmdBuf;
+
+ /* Set Command Parameters */
+ pCmd->cmdType = MSG_CMD_REG_THREAD_CHANGE_CB;
+
+ /* Copy Cookie */
+ memcpy(pCmd->cmdCookie, mCookie, MAX_COOKIE_LEN);
+
+ MSG_DEBUG("remote fd %d", remoteFd);
+
+ memcpy((void*)((char*)pCmd+sizeof(MSG_CMD_TYPE_T)+MAX_COOKIE_LEN), &remoteFd, sizeof(remoteFd));
+
+ MSG_DEBUG("reg status [%d : %s], %d", pCmd->cmdType, MsgDbgCmdStr(pCmd->cmdType), remoteFd);
+
+ /* Send Command to Messaging FW */
+ char* pEventData = NULL;
+ unique_ptr<char*, void(*)(char**)> eventBuf(&pEventData, unique_ptr_deleter);
+
+ write((char*)pCmd, cmdSize, &pEventData);
+
+ /* Get Return Data */
+ MSG_EVENT_S* pEvent = (MSG_EVENT_S*)pEventData;
+
+ if (pEvent == NULL)
+ THROW(MsgException::INVALID_RESULT, "Event is NULL");
+
+ if (pEvent->eventType != MSG_EVENT_REG_THREAD_CHANGE_CB) {
+ THROW(MsgException::INVALID_PARAM, "Event Data Error");
+ }
+
+ return pEvent->result;
+}
+
+
msg_error_t MsgHandle::getReportStatus(msg_message_id_t msg_id, msg_struct_list_s *report_list)
{
/* Allocate Memory to Command Data */
}
+bool MsgProxyListener::regThreadChangeEventCB(MsgHandle* pMsgHandle, int fd, msg_thread_change_cb pfThreadChangeOperation, void *pUserParam)
+{
+ MsgMutexLocker lock(mx);
+
+ std::list<MSG_THREAD_CHANGE_CB_ITEM_S>::iterator it = threadChangeCBList.begin();
+
+ for (; it != threadChangeCBList.end(); it++) {
+ if (it->hAddr == pMsgHandle && it->pfThreadChangeCB == pfThreadChangeOperation) {
+ if (it->fd == fd) {
+ MSG_DEBUG("msg_thread_change_cb() callback : [%p] is already registered!!!", pfThreadChangeOperation);
+ return false;
+ } else {
+ MSG_DEBUG("callback is registered by restarting server");
+ it->fd = fd;
+ return true;
+ }
+ }
+ }
+
+ MSG_THREAD_CHANGE_CB_ITEM_S changeCB = {pMsgHandle, fd, pfThreadChangeOperation, pUserParam};
+
+ threadChangeCBList.push_back(changeCB);
+
+ return true;
+}
+
+
void MsgProxyListener::clearListOfClosedHandle(MsgHandle* pMsgHandle)
{
MSG_BEGIN();
}
mx.unlock();
+ } else if (pMsgEvent->eventType == MSG_EVENT_PLG_THREAD_CHANGE_IND) {
+ msg_storage_change_type_t storageChangeType;
+ msg_thread_id_t threadId;
+
+ /* Decode event data */
+ memcpy(&storageChangeType, (void*)((char*)pMsgEvent+sizeof(MSG_EVENT_TYPE_T)+sizeof(msg_error_t)), sizeof(msg_storage_change_type_t));
+ memcpy(&threadId, (void*)((char*)pMsgEvent+sizeof(MSG_EVENT_TYPE_T)+sizeof(msg_error_t)+sizeof(msg_storage_change_type_t)), sizeof(msg_thread_id_t));
+
+ MSG_DEBUG("storageChangeType [%d], threadId [%d]", storageChangeType, threadId);
+
+ mx.lock();
+
+ MsgThreadChangeCBList::iterator it = threadChangeCBList.begin();
+
+ for ( ; it != threadChangeCBList.end(); it++) {
+ MsgHandle* pHandle = it->hAddr;
+
+ msg_thread_change_cb pfunc = it->pfThreadChangeCB;
+
+ void* param = it->userParam;
+
+ pfunc((msg_handle_t)pHandle, storageChangeType, threadId, param);
+ }
+
+ mx.unlock();
} else if (pMsgEvent->eventType == MSG_EVENT_PLG_INCOMING_CB_MSG_IND) {
MSG_CB_MSG_S *pCbMsg = (MSG_CB_MSG_S *)pMsgEvent->data;
#endif
case MSG_CMD_CHECK_PERMISSION:
return "MSG_CMD_CHECK_PERMISSION";
+ case MSG_CMD_REG_THREAD_CHANGE_CB:
+ return "MSG_CMD_REG_THREAD_CHANGE_CB";
+ case MSG_CMD_PLG_THREAD_CHANGE_IND:
+ return "MSG_CMD_PLG_THREAD_CHANGE_IND";
default:
return "Unknown Command Type!!!";
case MSG_EVENT_PLG_REPORT_MSG_INCOMING_IND:
return "MSG_EVENT_PLG_REPORT_MSG_INCOMING_IND";
+ case MSG_EVENT_REG_THREAD_CHANGE_CB:
+ return "MSG_EVENT_REG_THREAD_CHANGE_CB";
+ case MSG_EVENT_PLG_THREAD_CHANGE_IND:
+ return "MSG_EVENT_PLG_THREAD_CHANGE_IND";
default:
return "Unknown Event Type!!!";
}
+int MsgEncodeThreadChangeData(const msg_storage_change_type_t storageChangeType, const msg_thread_id_t threadId, char **ppDest)
+{
+ int dataSize = 0;
+
+ dataSize = sizeof(msg_storage_change_type_t) + sizeof(msg_thread_id_t);
+
+ *ppDest = (char*)new char[dataSize];
+
+ void* p = (void*)*ppDest;
+
+ memcpy(p, &storageChangeType, sizeof(msg_storage_change_type_t));
+ p = (void*)((char*)p + sizeof(msg_storage_change_type_t));
+
+ memcpy(p, &threadId, sizeof(msg_thread_id_t));
+
+ return dataSize;
+}
+
+
int MsgEncodeReportMsgData(const msg_report_type_t msgReportType, const MSG_MESSAGE_INFO_S *pMsgInfo, char **ppDest)
{
int dataSize = 0;