2 * Copyright (c) 2011 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.
18 #include "CallHistory.h"
24 #include <Commons/Exception.h>
25 #include <dpl/shared_ptr.h>
26 #include <dpl/log/log.h>
27 #include <API/Filter/IFilter.h>
28 #include <API/Filter/IFilterVisitor.h>
30 #include <contacts-svc.h>
32 #include "CallHistoryFilter.h"
35 using namespace TizenApis::Api::Tizen;
36 using namespace TizenApis::Api::Call;
37 using namespace WrtDeviceApis;
38 using namespace WrtDeviceApis::Commons;
45 std::vector<CallHistory::WatcherPtr> CallHistory::m_watchers;
47 CallHistory::CallHistory()
51 if (calllog_connect() == CALLLOG_ERROR_NONE) {
52 LogDebug("Successful to connect Call history DB ");
54 LogDebug("Failed to connect Call history DB ");
58 CallHistory::~CallHistory()
62 if (calllog_disconnect() == CALLLOG_ERROR_NONE) {
63 LogDebug("Successful to disconnect Call history DB ");
65 LogDebug("Failed to disconnect Call history DB ");
68 std::vector<CallHistory::WatcherPtr>::iterator it = CallHistory::m_watchers.begin();
70 if (m_watchers.size() > 0) {
71 for (;it < CallHistory::m_watchers.end();) {
72 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_PLOG_CHANGE, addedListenerCB);
73 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_MISSED_CALL_CHANGE, changedListenerCB);
74 it = CallHistory::m_watchers.erase(it);
77 LogDebug("CallHistory Watcher is removed. (" << CallHistory::m_watchers.size() << ")");
81 bool CallHistory::convertCallHistory(callhistory_query_s *query_log, CallHistoryEntryListPtr &callEntries)
83 if (query_log == NULL || callEntries == NULL)
86 CallHistoryEntryPropertiesPtr callHistoryItem(new CallHistoryEntryProperties());
87 StringArrayPtr stringArray(new StringArray());
88 RemotePartyPtr remoteParty(new RemoteParty());
89 RemotePartyListPtr remotePartyList(new RemotePartyList());
91 std::string callType("");
93 std::string direction("");
94 std::string number("");
96 if (query_log->phone_number != NULL) {
97 number.append(query_log->phone_number);
100 switch(query_log->calllog_type) {
101 case CALLLOG_TYPE_VOICE_ANSWERED:
102 callType.append(STR_TIZEN_TEL);
103 tags.append(STR_CALL_VOICE);
104 direction.append(STR_RECEIVED);
106 case CALLLOG_TYPE_VOICE_OUTGOING:
107 callType.append(STR_TIZEN_TEL);
108 tags.append(STR_CALL_VOICE);
109 direction.append(STR_DIALED);
111 case CALLLOG_TYPE_VOICE_MISSED_CHECKED:
112 callType.append(STR_TIZEN_TEL);
113 tags.append(STR_CALL_VOICE);
114 direction.append(STR_MISSED);
116 case CALLLOG_TYPE_VOICE_MISSED_UNCHECKED:
117 callType.append(STR_TIZEN_TEL);
118 tags.append(STR_CALL_VOICE);
119 direction.append(STR_MISSED_NEW);
121 case CALLLOG_TYPE_VOICE_REJECTED:
122 callType.append(STR_TIZEN_TEL);
123 tags.append(STR_CALL_VOICE);
124 direction.append(STR_REJECTED);
126 case CALLLOG_TYPE_VOICE_BLOCKED:
127 callType.append(STR_TIZEN_TEL);
128 tags.append(STR_CALL_VOICE);
129 direction.append(STR_BLOCKED);
131 case CALLLOG_TYPE_VIDEO_ANSWERED:
132 callType.append(STR_TIZEN_TEL);
133 tags.append(STR_CALL_VIDEO);
134 direction.append(STR_RECEIVED);
136 case CALLLOG_TYPE_VIDEO_OUTGOING:
137 callType.append(STR_TIZEN_TEL);
138 tags.append(STR_CALL_VIDEO);
139 direction.append(STR_DIALED);
141 case CALLLOG_TYPE_VIDEO_MISSED_CHECKED:
142 callType.append(STR_TIZEN_TEL);
143 tags.append(STR_CALL_VIDEO);
144 direction.append(STR_MISSED);
146 case CALLLOG_TYPE_VIDEO_MISSED_UNCHECKED:
147 callType.append(STR_TIZEN_TEL);
148 tags.append(STR_CALL_VIDEO);
149 direction.append(STR_MISSED_NEW);
151 case CALLLOG_TYPE_VIDEO_REJECTED:
152 callType.append(STR_TIZEN_TEL);
153 tags.append(STR_CALL_VIDEO);
154 direction.append(STR_REJECTED);
156 case CALLLOG_TYPE_VIDEO_BLOCKED:
157 callType.append(STR_TIZEN_TEL);
158 tags.append(STR_CALL_VIDEO);
159 direction.append(STR_BLOCKED);
165 std::stringstream contactId;
166 contactId << query_log->contact_db_id;
168 callHistoryItem->setEntryId(query_log->calllog_db_id);
169 callHistoryItem->setCallType(callType);
170 stringArray->push_back(tags);
171 callHistoryItem->setTags(stringArray);
173 remoteParty->setRemoteParty(number);
174 remoteParty->setContactId(contactId.str());
175 remotePartyList->push_back(remoteParty);
176 callHistoryItem->setRemoteParties(remotePartyList);
178 callHistoryItem->setStartTime(query_log->timestamp);
179 callHistoryItem->setDuration((unsigned long)(query_log->duration_sec));
180 callHistoryItem->setDirection(direction);
182 callEntries->insert(callEntries->end(), callHistoryItem);
187 void CallHistory::find(const EventFindCallHistoryPtr& event)
189 EventRequestReceiver<EventFindCallHistory>::PostRequest(event);
192 bool CallHistory::remove(const unsigned long entryId)
195 int ret = calllog_delete_from_db(entryId);
197 if (ret == CALLLOG_ERROR_NONE) {
202 } catch (const Commons::PlatformException& ex) {
203 ThrowMsg(Commons::PlatformException, ex.GetMessage());
207 void CallHistory::removeBatch(const EventRemoveBatchPtr& event)
209 EventRequestReceiver<EventRemoveBatch>::PostRequest(event);
212 void CallHistory::removeAll(const EventRemoveAllPtr& event)
214 EventRequestReceiver<EventRemoveAll>::PostRequest(event);
217 long CallHistory::addListener(const EventCallHistoryListenerEmitterPtr& emitter)
220 if (CallHistory::m_watchers.size() == 0) {
221 WatcherPtr watcher(new Watcher(0, emitter));
222 ret = contacts_svc_subscribe_change(CTS_SUBSCRIBE_PLOG_CHANGE, addedListenerCB, watcher.Get());
224 if (ret == CTS_SUCCESS) {
225 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
226 std::string query(STR_BASE_QUERY);
227 query.append(" WHERE log_type <= 12 ORDER BY log_time DESC LIMIT 1");
228 executeQuery(query, callHistoryListPtr);
230 if (callHistoryListPtr->size() > 0) {
231 watcher->setCurrentLogTime((*callHistoryListPtr)[0]->getStartTime());
235 ret = contacts_svc_subscribe_change(CTS_SUBSCRIBE_MISSED_CALL_CHANGE, changedListenerCB, watcher.Get());
237 if (ret == CTS_SUCCESS) {
238 MissedCallListPtr missedCallList(updateCurrentMissedCall());
239 watcher->setMissedCallList(missedCallList);
242 CallHistory::m_watchers.push_back(watcher);
243 return static_cast<long>(emitter->getId());
249 void CallHistory::removeListener(EventCallHistoryListenerEmitter::IdType id)
251 std::vector<CallHistory::WatcherPtr>::iterator it = CallHistory::m_watchers.begin();
253 for (;it < CallHistory::m_watchers.end();) {
254 if (id == (*it)->getEmitter()->getId()) {
255 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_PLOG_CHANGE, addedListenerCB);
256 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_MISSED_CALL_CHANGE, changedListenerCB);
257 it = CallHistory::m_watchers.erase(it);
264 void CallHistory::addedListenerCB(void *user_data)
266 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
267 std::string query(STR_BASE_QUERY);
268 query.append(" WHERE log_type <= 12 AND log_time > ");
270 std::stringstream currentLogTime;
271 currentLogTime << static_cast<int>(((CallHistory::Watcher*)user_data)->getCurrentLogTime());
272 query.append(currentLogTime.str());
274 query.append(" ORDER BY log_time DESC");
275 ((CallHistory::Watcher*)user_data)->executeQuery(query, callHistoryListPtr);
277 if (callHistoryListPtr->size() > 0) {
278 ((CallHistory::Watcher*)user_data)->addMissedCall(callHistoryListPtr);
279 ((CallHistory::Watcher*)user_data)->setCurrentLogTime((*callHistoryListPtr)[callHistoryListPtr->size() - 1]->getStartTime());
280 ((CallHistory::Watcher*)user_data)->stateHasChanged(callHistoryListPtr, EventCallHistoryListener::ADDED);
284 void CallHistory::changedListenerCB(void *user_data)
286 MissedCallListPtr missedCallListPtr(((CallHistory::Watcher*)user_data)->getMissedCallList());
287 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
288 if (missedCallListPtr->size() > 0) {
289 std::string query(STR_BASE_QUERY);
290 query.append(" WHERE log_type <= 12 AND (");
292 MissedCallList::iterator itM = missedCallListPtr->begin();
293 std::stringstream id;
296 if (itM != missedCallListPtr->begin()) {
297 query.append(" OR ");
299 query.append(" id = ");
300 id << static_cast<unsigned long>(*itM);
301 query.append(id.str());
304 } while(itM < missedCallListPtr->end());
308 ((CallHistory::Watcher*)user_data)->executeQuery(query, callHistoryListPtr);
310 CallHistoryEntryList::iterator itC = callHistoryListPtr->begin();
312 for (;itC != callHistoryListPtr->end();) {
313 if ((*itC)->getDirection().compare(STR_MISSED) != 0) {
314 itC = callHistoryListPtr->erase(itC);
320 if (callHistoryListPtr->size() > 0) {
321 ((CallHistory::Watcher*)user_data)->updateCurrentMissedCall();
322 ((CallHistory::Watcher*)user_data)->stateHasChanged(callHistoryListPtr, EventCallHistoryListener::CHANGED);
327 bool CallHistory::executeQuery(std::string &query, CallHistoryEntryListPtr &callEntries)
329 callhistory_query_s query_data;
334 hstmt = _query_prepare((char *)(query.c_str()));
337 ret = _query_step(hstmt);
338 if (ret == SQLITE_ROW) {
339 query_data.calllog_db_id = (unsigned long)_query_column_int64(hstmt, 0);
340 query_data.calllog_type = (calllog_type_e)_query_column_int(hstmt, 1);
341 query_data.contact_db_id = _query_column_int(hstmt, 2);
342 query_data.phone_number = _query_column_text(hstmt, 3);
343 query_data.timestamp = (time_t)_query_column_int(hstmt, 4);
344 query_data.duration_sec = _query_column_int(hstmt, 5);
346 convertCallHistory(&query_data, callEntries);
347 } else if (ret == SQLITE_DONE) {
354 _query_finalize(hstmt);
358 std::string CallHistory::convertAttrName(std::string &name)
360 std::string attrName("");
361 if (name.compare("remoteParty") == 0) {
362 return attrName.append("number");
363 } else if (name.compare("startTime") == 0) {
364 return attrName.append("log_time");
365 } else if (name.compare("duration") == 0) {
366 return attrName.append("data1");
367 } else if (name.compare("direction") == 0) {
368 return attrName.append("log_type");
374 std::string CallHistory::makeQuerySortMode(SortModePtr attr)
376 std::string query("");
377 std::string attriName;
379 attriName = attr->getAttributeName();
380 attriName = convertAttrName(attriName);
381 if (attriName.compare("") != 0) {
382 query.append(" ORDER BY ");
383 query.append(attriName);
385 if (attr->getOrder() == Api::Tizen::ASCENDING_SORT_ORDER) {
386 query.append(" ASC");
388 query.append(" DESC");
395 MissedCallListPtr CallHistory::updateCurrentMissedCall()
397 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
398 std::string query(STR_BASE_QUERY);
399 query.append(" WHERE log_type = 5 OR log_type = 7 ORDER BY log_time DESC");
400 executeQuery(query, callHistoryListPtr);
401 LogDebug("result counter [" << callHistoryListPtr->size() << "]");
403 CallHistoryEntryList::iterator it = callHistoryListPtr->begin();
404 MissedCallListPtr missedCallList(new MissedCallList());
406 for (;it != callHistoryListPtr->end(); ++it) {
407 missedCallList->push_back((*it)->getEntryId());
409 LogDebug("missed Call size (" << missedCallList->size() << ")");
411 return missedCallList;
414 void CallHistory::OnRequestReceived(const EventFindCallHistoryPtr& event)
417 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
419 std::string query(STR_BASE_QUERY);
421 CallHistoryFilterPtr filtering(new CallHistoryFilter());
422 IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<IFilterVisitor>(filtering);
424 if (event->getFilterIsSet()) {
425 FilterPtr filter = event->getFilter();
426 filter->travel(filterTraversal, 0);
427 query.append(filtering->getResult());
428 query.append(" AND log_type <= 12");
430 query.append(" WHERE log_type <= 12");
433 if (event->getSortModesIsSet()) {
434 query.append(makeQuerySortMode(event->getSortMode()));
436 query.append(" ORDER BY log_time DESC");
439 if (event->getLimitIsSet()) {
440 query.append(" LIMIT ");
441 std::stringstream limitStream;
442 limitStream << event->getLimit();
443 query.append(limitStream.str());
444 if (event->getOffsetIsSet()) {
445 query.append(" OFFSET ");
446 std::stringstream offsetStream;
447 offsetStream << event->getOffset();
448 query.append(offsetStream.str());
452 LogDebug("execute query [" << query << "]");
454 executeQuery(query, callHistoryListPtr);
455 event->setResult(callHistoryListPtr);
457 } catch (const Commons::PlatformException& ex) {
458 LogError("Exception: " << ex.GetMessage());
459 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
463 void CallHistory::OnRequestReceived(const EventRemoveBatchPtr& event)
466 std::vector<unsigned long> entryIds = event->getEntryIds();
467 unsigned int cnt = 0;
468 int ret = CALLLOG_ERROR_NONE;
469 for (cnt = 0; cnt < entryIds.size(); cnt++) {
470 ret = calllog_delete_from_db(static_cast<int>(entryIds[cnt]));
471 if (ret != CALLLOG_ERROR_NONE) {
472 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
475 } catch (const Commons::PlatformException& ex) {
476 LogError("Exception: " << ex.GetMessage());
477 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
481 void CallHistory::OnRequestReceived(const EventRemoveAllPtr& event)
484 int ret = CALLLOG_ERROR_NONE;
485 ret = calllog_delete_all_from_db();
486 if (ret != CALLLOG_ERROR_NONE) {
487 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
489 } catch (const Commons::PlatformException& ex) {
490 LogError("Exception: " << ex.GetMessage());
491 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
495 CallHistory::Watcher::Watcher(int handle, const Api::Call::EventCallHistoryListenerEmitterPtr& emitter) :
500 m_missedCallList = MissedCallListPtr(new MissedCallList());
504 CallHistory::Watcher::~Watcher()
509 void CallHistory::Watcher::stateHasChanged(CallHistoryEntryListPtr &entryList, EventCallHistoryListener::ResultStates state)
511 if (entryList == NULL)
514 EventCallHistoryListenerPtr event(new EventCallHistoryListener());
515 event->setResultState(state);
516 event->setResult(entryList);
517 m_emitter->emit(event);
520 bool CallHistory::Watcher::executeQuery(std::string &query, CallHistoryEntryListPtr &entryList)
522 CallHistory* callHistory = (CallHistory *) this;
523 if (callHistory != NULL) {
524 callHistory->executeQuery(query, entryList);
530 bool CallHistory::Watcher::addMissedCall(CallHistoryEntryListPtr &entryList)
532 if (entryList != NULL) {
533 CallHistoryEntryList::iterator it = entryList->begin();
534 for (; it != entryList->end(); it++) {
535 if ((*it)->getDirection().compare(STR_MISSED_NEW) == 0) {
536 m_missedCallList->push_back((*it)->getEntryId());
544 bool CallHistory::Watcher::updateCurrentMissedCall()
546 CallHistory* callHistory = (CallHistory *) this;
547 if (callHistory != NULL) {
548 setMissedCallList(callHistory->updateCurrentMissedCall());