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>
29 #include <API/Call/CallDefine.h>
31 #include <contacts-svc.h>
33 #include "CallHistoryFilter.h"
36 using namespace TizenApis::Api::Tizen;
37 using namespace TizenApis::Api::Call;
38 using namespace WrtDeviceApis;
39 using namespace WrtDeviceApis::Commons;
46 std::vector<CallHistory::WatcherPtr> CallHistory::m_watchers;
48 CallHistory::CallHistory()
52 if (calllog_connect() == CALLLOG_ERROR_NONE) {
53 LogDebug("Successful to connect Call history DB ");
55 LogDebug("Failed to connect Call history DB ");
59 CallHistory::~CallHistory()
63 if (calllog_disconnect() == CALLLOG_ERROR_NONE) {
64 LogDebug("Successful to disconnect Call history DB ");
66 LogDebug("Failed to disconnect Call history DB ");
69 std::vector<CallHistory::WatcherPtr>::iterator it = CallHistory::m_watchers.begin();
71 if (m_watchers.size() > 0) {
72 for (;it < CallHistory::m_watchers.end();) {
73 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_PLOG_CHANGE, addedListenerCB);
74 contacts_svc_unsubscribe_change(CTS_SUBSCRIBE_MISSED_CALL_CHANGE, changedListenerCB);
75 it = CallHistory::m_watchers.erase(it);
78 LogDebug("CallHistory Watcher is removed. (" << CallHistory::m_watchers.size() << ")");
82 bool CallHistory::convertCallHistory(callhistory_query_s *query_log, CallHistoryEntryListPtr &callEntries)
84 if (query_log == NULL || callEntries == NULL)
87 CallHistoryEntryPropertiesPtr callHistoryItem(new CallHistoryEntryProperties());
88 StringArrayPtr stringArray(new StringArray());
89 RemotePartyPtr remoteParty(new RemoteParty());
90 RemotePartyListPtr remotePartyList(new RemotePartyList());
91 Api::Contact::ContactRefPtr contactRef(new Api::Contact::ContactRef());
93 std::string callType("");
95 std::string direction("");
96 std::string number("");
98 if (query_log->phone_number != NULL) {
99 number.append(query_log->phone_number);
102 switch(query_log->calllog_type) {
103 case CALLLOG_TYPE_VOICE_ANSWERED:
104 callType.append(STR_TIZEN_TEL);
105 tags.append(STR_CALL_VOICE);
106 direction.append(STR_RECEIVED);
108 case CALLLOG_TYPE_VOICE_OUTGOING:
109 callType.append(STR_TIZEN_TEL);
110 tags.append(STR_CALL_VOICE);
111 direction.append(STR_DIALED);
113 case CALLLOG_TYPE_VOICE_MISSED_CHECKED:
114 callType.append(STR_TIZEN_TEL);
115 tags.append(STR_CALL_VOICE);
116 direction.append(STR_MISSED);
118 case CALLLOG_TYPE_VOICE_MISSED_UNCHECKED:
119 callType.append(STR_TIZEN_TEL);
120 tags.append(STR_CALL_VOICE);
121 direction.append(STR_MISSED_NEW);
123 case CALLLOG_TYPE_VOICE_REJECTED:
124 callType.append(STR_TIZEN_TEL);
125 tags.append(STR_CALL_VOICE);
126 direction.append(STR_REJECTED);
128 case CALLLOG_TYPE_VOICE_BLOCKED:
129 callType.append(STR_TIZEN_TEL);
130 tags.append(STR_CALL_VOICE);
131 direction.append(STR_BLOCKED);
133 case CALLLOG_TYPE_VIDEO_ANSWERED:
134 callType.append(STR_TIZEN_TEL);
135 tags.append(STR_CALL_VIDEO);
136 direction.append(STR_RECEIVED);
138 case CALLLOG_TYPE_VIDEO_OUTGOING:
139 callType.append(STR_TIZEN_TEL);
140 tags.append(STR_CALL_VIDEO);
141 direction.append(STR_DIALED);
143 case CALLLOG_TYPE_VIDEO_MISSED_CHECKED:
144 callType.append(STR_TIZEN_TEL);
145 tags.append(STR_CALL_VIDEO);
146 direction.append(STR_MISSED);
148 case CALLLOG_TYPE_VIDEO_MISSED_UNCHECKED:
149 callType.append(STR_TIZEN_TEL);
150 tags.append(STR_CALL_VIDEO);
151 direction.append(STR_MISSED_NEW);
153 case CALLLOG_TYPE_VIDEO_REJECTED:
154 callType.append(STR_TIZEN_TEL);
155 tags.append(STR_CALL_VIDEO);
156 direction.append(STR_REJECTED);
158 case CALLLOG_TYPE_VIDEO_BLOCKED:
159 callType.append(STR_TIZEN_TEL);
160 tags.append(STR_CALL_VIDEO);
161 direction.append(STR_BLOCKED);
167 callHistoryItem->setEntryId(query_log->calllog_db_id);
168 callHistoryItem->setCallType(callType);
169 stringArray->push_back(tags);
170 callHistoryItem->setTags(stringArray);
172 remoteParty->setRemoteParty(number);
173 contactRef->setContactId(query_log->contact_db_id);
174 remoteParty->setContactRef(contactRef);
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 id DESC LIMIT 1");
228 executeQuery(query, callHistoryListPtr);
230 if (callHistoryListPtr->size() > 0) {
231 watcher->setCurrentLogId((*callHistoryListPtr)[0]->getEntryId());
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);
269 query.append(" WHERE log_type <= 12 AND id > ");
271 std::stringstream currentLogId;
272 currentLogId << static_cast<int>(((CallHistory::Watcher*)user_data)->getCurrentLogId());
273 query.append(currentLogId.str());
274 query.append(" ORDER BY id DESC");
276 ((CallHistory::Watcher*)user_data)->executeQuery(query, callHistoryListPtr);
278 if (callHistoryListPtr->size() > 0) {
279 ((CallHistory::Watcher*)user_data)->setCurrentLogId((*callHistoryListPtr)[0]->getEntryId());
280 ((CallHistory::Watcher*)user_data)->stateHasChanged(callHistoryListPtr, EventCallHistoryListener::ADDED);
281 ((CallHistory::Watcher*)user_data)->addMissedCall(callHistoryListPtr);
285 void CallHistory::changedListenerCB(void *user_data)
287 MissedCallListPtr missedCallListPtr(((CallHistory::Watcher*)user_data)->getMissedCallList());
288 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
289 if (missedCallListPtr->size() > 0) {
290 std::string query(STR_BASE_QUERY);
291 query.append(" WHERE log_type <= 12 AND (");
293 MissedCallList::iterator itM = missedCallListPtr->begin();
294 std::stringstream id;
297 if (itM != missedCallListPtr->begin()) {
298 query.append(" OR ");
300 query.append(" id = ");
301 id << static_cast<unsigned long>(*itM);
302 query.append(id.str());
305 } while(itM < missedCallListPtr->end());
309 ((CallHistory::Watcher*)user_data)->executeQuery(query, callHistoryListPtr);
311 CallHistoryEntryList::iterator itC = callHistoryListPtr->begin();
313 for (;itC != callHistoryListPtr->end();) {
314 if ((*itC)->getDirection().compare(STR_MISSED) != 0) {
315 itC = callHistoryListPtr->erase(itC);
321 if (callHistoryListPtr->size() > 0) {
322 ((CallHistory::Watcher*)user_data)->updateCurrentMissedCall();
323 ((CallHistory::Watcher*)user_data)->stateHasChanged(callHistoryListPtr, EventCallHistoryListener::CHANGED);
328 bool CallHistory::executeQuery(std::string &query, CallHistoryEntryListPtr &callEntries)
330 callhistory_query_s query_data;
335 hstmt = _query_prepare((char *)(query.c_str()));
338 ret = _query_step(hstmt);
339 if (ret == SQLITE_ROW) {
340 query_data.calllog_db_id = (unsigned long)_query_column_int64(hstmt, 0);
341 query_data.calllog_type = (calllog_type_e)_query_column_int(hstmt, 1);
342 query_data.contact_db_id = _query_column_int(hstmt, 2);
343 query_data.phone_number = _query_column_text(hstmt, 3);
344 query_data.timestamp = (time_t)_query_column_int(hstmt, 4);
345 query_data.duration_sec = _query_column_int(hstmt, 5);
347 convertCallHistory(&query_data, callEntries);
348 } else if (ret == SQLITE_DONE) {
355 _query_finalize(hstmt);
359 std::string CallHistory::convertAttrName(std::string &name)
361 std::string attrName("");
362 if (name.compare(STR_RP_REMOTEPARTY) == 0) {
363 return attrName.append(STR_NUMBER);
364 } else if (name.compare(STR_START_TIME) == 0) {
365 return attrName.append(STR_LOG_TIME);
366 } else if (name.compare(STR_DURATION) == 0) {
367 return attrName.append(STR_DATA1);
368 } else if (name.compare(STR_DIRECTION) == 0) {
369 return attrName.append(STR_LOG_TYPE);
375 std::string CallHistory::makeQuerySortMode(SortModePtr attr)
377 std::string query("");
378 std::string attriName;
380 attriName = attr->getAttributeName();
381 attriName = convertAttrName(attriName);
382 if (attriName.compare("") != 0) {
383 query.append(" ORDER BY ");
384 query.append(attriName);
386 if (attr->getOrder() == Api::Tizen::ASCENDING_SORT_ORDER) {
387 query.append(" ASC");
389 query.append(" DESC");
396 MissedCallListPtr CallHistory::updateCurrentMissedCall()
398 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
399 std::string query(STR_BASE_QUERY);
400 query.append(" WHERE log_type = 5 OR log_type = 7 ORDER BY log_time DESC");
401 executeQuery(query, callHistoryListPtr);
402 LogDebug("result counter [" << callHistoryListPtr->size() << "]");
404 CallHistoryEntryList::iterator it = callHistoryListPtr->begin();
405 MissedCallListPtr missedCallList(new MissedCallList());
407 for (;it != callHistoryListPtr->end(); ++it) {
408 missedCallList->push_back((*it)->getEntryId());
410 LogDebug("missed Call size (" << missedCallList->size() << ")");
412 return missedCallList;
415 void CallHistory::OnRequestReceived(const EventFindCallHistoryPtr& event)
418 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
420 std::string query(STR_BASE_QUERY);
422 CallHistoryFilterPtr filtering(new CallHistoryFilter());
423 IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<IFilterVisitor>(filtering);
425 if (event->getFilterIsSet()) {
426 FilterPtr filter = event->getFilter();
427 filter->travel(filterTraversal, 0);
428 query.append(filtering->getResult());
429 query.append(" AND log_type <= 12");
431 query.append(" WHERE log_type <= 12");
434 if (event->getSortModesIsSet()) {
435 query.append(makeQuerySortMode(event->getSortMode()));
437 query.append(" ORDER BY log_time DESC");
440 if (event->getLimitIsSet()) {
441 query.append(" LIMIT ");
442 std::stringstream limitStream;
443 limitStream << event->getLimit();
444 query.append(limitStream.str());
445 if (event->getOffsetIsSet()) {
446 query.append(" OFFSET ");
447 std::stringstream offsetStream;
448 offsetStream << event->getOffset();
449 query.append(offsetStream.str());
453 LogDebug("execute query [" << query << "]");
455 executeQuery(query, callHistoryListPtr);
456 event->setResult(callHistoryListPtr);
458 } catch (const Commons::PlatformException& ex) {
459 LogError("Exception: " << ex.GetMessage());
460 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
464 void CallHistory::OnRequestReceived(const EventRemoveBatchPtr& event)
467 std::vector<unsigned long> entryIds = event->getEntryIds();
468 unsigned int cnt = 0;
469 int ret = CALLLOG_ERROR_NONE;
470 for (cnt = 0; cnt < entryIds.size(); cnt++) {
471 ret = calllog_delete_from_db(static_cast<int>(entryIds[cnt]));
472 if (ret != CALLLOG_ERROR_NONE) {
473 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
477 } catch (const Commons::PlatformException& ex) {
478 LogError("Exception: " << ex.GetMessage());
479 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
483 void CallHistory::OnRequestReceived(const EventRemoveAllPtr& event)
486 int ret = CALLLOG_ERROR_NONE;
487 ret = calllog_delete_all_from_db();
488 if (ret != CALLLOG_ERROR_NONE) {
489 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
491 } catch (const Commons::PlatformException& ex) {
492 LogError("Exception: " << ex.GetMessage());
493 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
497 CallHistory::Watcher::Watcher(int handle, const Api::Call::EventCallHistoryListenerEmitterPtr& emitter) :
502 m_missedCallList = MissedCallListPtr(new MissedCallList());
506 CallHistory::Watcher::~Watcher()
511 void CallHistory::Watcher::stateHasChanged(CallHistoryEntryListPtr &entryList, EventCallHistoryListener::ResultStates state)
513 if (entryList == NULL)
516 EventCallHistoryListenerPtr event(new EventCallHistoryListener());
517 event->setResultState(state);
518 event->setResult(entryList);
519 m_emitter->emit(event);
522 bool CallHistory::Watcher::executeQuery(std::string &query, CallHistoryEntryListPtr &entryList)
524 CallHistory* callHistory = (CallHistory *) this;
525 if (callHistory != NULL) {
526 callHistory->executeQuery(query, entryList);
532 bool CallHistory::Watcher::addMissedCall(CallHistoryEntryListPtr &entryList)
534 if (entryList != NULL) {
535 CallHistoryEntryList::iterator it = entryList->begin();
536 for (; it != entryList->end(); it++) {
537 if ((*it)->getDirection().compare(STR_MISSED_NEW) == 0) {
538 m_missedCallList->push_back((*it)->getEntryId());
546 bool CallHistory::Watcher::updateCurrentMissedCall()
548 CallHistory* callHistory = (CallHistory *) this;
549 if (callHistory != NULL) {
550 setMissedCallList(callHistory->updateCurrentMissedCall());