1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "call_records_handler.h"
17
18 #include "call_manager_base.h"
19 #include "call_manager_errors.h"
20 #include "call_manager_inner_type.h"
21 #include "ffrt.h"
22 #include "call_number_utils.h"
23
24 namespace OHOS {
25 namespace Telephony {
CallRecordsHandler()26 CallRecordsHandler::CallRecordsHandler() : callDataPtr_(nullptr)
27 {
28 callDataPtr_ = DelayedSingleton<CallDataBaseHelper>::GetInstance();
29 if (callDataPtr_ == nullptr) {
30 TELEPHONY_LOGE("callDataPtr_ is nullptr!");
31 }
32 }
33
QueryCallerInfo(ContactInfo & contactInfo,std::string phoneNumber)34 void CallRecordsHandler::QueryCallerInfo(ContactInfo &contactInfo, std::string phoneNumber)
35 {
36 std::shared_ptr<CallDataBaseHelper> callDataPtr = DelayedSingleton<CallDataBaseHelper>::GetInstance();
37 if (callDataPtr == nullptr) {
38 TELEPHONY_LOGE("callDataPtr is nullptr!");
39 return;
40 }
41 DataShare::DataSharePredicates predicates;
42 predicates.EqualTo(CALL_DETAIL_INFO, phoneNumber);
43 predicates.And();
44 predicates.EqualTo(CALL_CONTENT_TYPE, CALL_PHONE);
45 bool ret = callDataPtr->Query(contactInfo, predicates);
46 if (!ret) {
47 TELEPHONY_LOGE("Query contact database fail!");
48 }
49 }
50
AddCallLogInfo(const CallRecordInfo & info)51 int32_t CallRecordsHandler::AddCallLogInfo(const CallRecordInfo &info)
52 {
53 if (callDataPtr_ == nullptr) {
54 TELEPHONY_LOGE("callDataPtr is nullptr!");
55 return TELEPHONY_ERR_LOCAL_PTR_NULL;
56 }
57 std::string numberLocation = CheckNumberLocationInfo(info);
58 ContactInfo contactInfo = {
59 .name = "",
60 .number = "",
61 .isContacterExists = false,
62 .ringtonePath = "",
63 .isSendToVoicemail = false,
64 .isEcc = false,
65 .isVoiceMail = false,
66 };
67 QueryCallerInfo(contactInfo, std::string(info.phoneNumber));
68 std::string displayName = "";
69 if (std::string(contactInfo.name) != "") {
70 displayName = std::string(contactInfo.name);
71 } else if (info.numberMarkInfo.markType == MarkType::MARK_TYPE_YELLOW_PAGE && !info.numberMarkInfo.isCloud) {
72 displayName = std::string(info.numberMarkInfo.markContent);
73 }
74
75 DataShare::DataShareValuesBucket bucket;
76 TELEPHONY_LOGI("callLog Insert begin.");
77 MakeCallLogInsertBucket(bucket, info, displayName, numberLocation);
78 bool ret = callDataPtr_->Insert(bucket);
79 if (!ret) {
80 TELEPHONY_LOGE("add call log database fail!");
81 return TELEPHONY_ERR_DATABASE_WRITE_FAIL;
82 }
83 TELEPHONY_LOGI("callLog Insert success.");
84 DeleteCallLogForLimit(info);
85 return TELEPHONY_SUCCESS;
86 }
87
DeleteCallLogForLimit(const CallRecordInfo & info)88 void CallRecordsHandler::DeleteCallLogForLimit(const CallRecordInfo &info)
89 {
90 DataShare::DataSharePredicates queryPredicates;
91 if (info.answerType == CallAnswerType::CALL_ANSWER_BLOCKED) {
92 queryPredicates.EqualTo(CALL_ANSWER_STATE, static_cast<int32_t>(CallAnswerType::CALL_ANSWER_BLOCKED));
93 } else {
94 queryPredicates.NotEqualTo(CALL_ANSWER_STATE, static_cast<int32_t>(CallAnswerType::CALL_ANSWER_BLOCKED));
95 }
96 queryPredicates.OrderByDesc(CALL_CREATE_TIME);
97 queryPredicates.Limit(-1, LOG_LIMIT_NUM);
98 callDataPtr_->QueryAndDeleteLimitedIds(queryPredicates);
99 }
100
MakeCallLogInsertBucket(DataShare::DataShareValuesBucket & bucket,const CallRecordInfo & info,std::string displayName,std::string numberLocation)101 void CallRecordsHandler::MakeCallLogInsertBucket(DataShare::DataShareValuesBucket &bucket,
102 const CallRecordInfo &info, std::string displayName, std::string numberLocation)
103 {
104 bucket.Put(CALL_PHONE_NUMBER, std::string(info.phoneNumber));
105 bucket.Put(CALL_DISPLAY_NAME, displayName);
106 bucket.Put(CALL_DIRECTION, static_cast<int32_t>(info.directionType));
107 bucket.Put(CALL_VOICEMAIL_URI, std::string(""));
108 bucket.Put(CALL_SIM_TYPE, 0);
109 bucket.Put(CALL_IS_HD, static_cast<int32_t>(info.callType));
110 bucket.Put(CALL_IS_READ, 0);
111 bucket.Put(CALL_RING_DURATION, static_cast<int32_t>(info.ringDuration));
112 bucket.Put(CALL_TALK_DURATION, static_cast<int32_t>(info.callDuration));
113 bucket.Put(CALL_FORMAT_NUMBER, std::string(info.formattedNumber));
114 bucket.Put(CALL_QUICKSEARCH_KEY, std::string(""));
115 bucket.Put(CALL_NUMBER_TYPE, 0);
116 bucket.Put(CALL_NUMBER_TYPE_NAME, std::string(""));
117 bucket.Put(CALL_BEGIN_TIME, info.callBeginTime);
118 bucket.Put(CALL_END_TIME, info.callEndTime);
119 bucket.Put(CALL_ANSWER_STATE, static_cast<int32_t>(info.answerType));
120 bucket.Put(CALL_CREATE_TIME, info.callCreateTime);
121 bucket.Put(CALL_NUMBER_LOCATION, numberLocation);
122 bucket.Put(CALL_PHOTO_ID, 0);
123 bucket.Put(CALL_SLOT_ID, info.slotId);
124 bucket.Put(CALL_FEATURES, info.features);
125 }
126
CheckNumberLocationInfo(const CallRecordInfo & info)127 std::string CallRecordsHandler::CheckNumberLocationInfo(const CallRecordInfo &info)
128 {
129 std::string str(info.numberLocation);
130 if (str == "default") {
131 TELEPHONY_LOGI("AddCallLogInfo, number location is default");
132 str = "";
133 DelayedSingleton<CallNumberUtils>::GetInstance()->QueryNumberLocationInfo(str, std::string(info.phoneNumber));
134 }
135 if (str == "") {
136 str = "N";
137 }
138 return str;
139 }
140
QueryAndNotifyUnReadMissedCall()141 int32_t CallRecordsHandler::QueryAndNotifyUnReadMissedCall()
142 {
143 if (callDataPtr_ == nullptr) {
144 TELEPHONY_LOGE("callDataPtr is nullptr!");
145 return TELEPHONY_ERR_LOCAL_PTR_NULL;
146 }
147 missedCallNotification_ = std::make_shared<MissedCallNotification>();
148 if (missedCallNotification_ == nullptr) {
149 TELEPHONY_LOGE("missedCallNotification_ is null!");
150 return TELEPHONY_ERR_LOCAL_PTR_NULL;
151 }
152 DataShare::DataSharePredicates predicates;
153 std::map<std::string, int32_t> phoneNumAndUnreadCountMap;
154 predicates.EqualTo(CALL_IS_READ, static_cast<int32_t>(CallLogReadState::CALL_IS_UNREAD));
155 predicates.And();
156 predicates.EqualTo(CALL_DIRECTION, static_cast<int32_t>(CallDirection::CALL_DIRECTION_IN));
157 predicates.And();
158 predicates.EqualTo(CALL_ANSWER_STATE, static_cast<int32_t>(CallAnswerType::CALL_ANSWER_MISSED));
159 bool ret = callDataPtr_->QueryCallLog(phoneNumAndUnreadCountMap, predicates);
160 if (phoneNumAndUnreadCountMap.empty() || !ret) {
161 TELEPHONY_LOGE("Don't have unread missed call in call log!");
162 return TELEPHONY_ERR_DATABASE_READ_FAIL;
163 }
164 int32_t result = missedCallNotification_->NotifyUnReadMissedCall(phoneNumAndUnreadCountMap);
165 if (result != TELEPHONY_SUCCESS) {
166 TELEPHONY_LOGE("Notify unread missed call error!");
167 return TELEPHONY_ERR_PUBLISH_BROADCAST_FAIL;
168 }
169 return TELEPHONY_SUCCESS;
170 }
171
CallRecordsHandlerService()172 CallRecordsHandlerService::CallRecordsHandlerService() : handler_(nullptr) {}
173
~CallRecordsHandlerService()174 CallRecordsHandlerService::~CallRecordsHandlerService() {}
175
Start()176 void CallRecordsHandlerService::Start()
177 {
178 handler_ = std::make_shared<CallRecordsHandler>();
179 return;
180 }
181
StoreCallRecord(const CallRecordInfo & info)182 int32_t CallRecordsHandlerService::StoreCallRecord(const CallRecordInfo &info)
183 {
184 if (handler_.get() == nullptr) {
185 TELEPHONY_LOGE("handler_ is nullptr");
186 return TELEPHONY_ERR_LOCAL_PTR_NULL;
187 }
188 ffrt::submit([=]() { handler_->AddCallLogInfo(info); });
189 return TELEPHONY_SUCCESS;
190 }
191
RemoveMissedIncomingCallNotification()192 int32_t CallRecordsHandlerService::RemoveMissedIncomingCallNotification()
193 {
194 std::shared_ptr<CallDataBaseHelper> callDataPtr = DelayedSingleton<CallDataBaseHelper>::GetInstance();
195 if (callDataPtr == nullptr) {
196 TELEPHONY_LOGE("callDataPtr is nullptr!");
197 return TELEPHONY_ERR_LOCAL_PTR_NULL;
198 }
199 DataShare::DataSharePredicates predicates;
200 DataShare::DataShareValuesBucket bucket;
201 bucket.Put(CALL_IS_READ, static_cast<int32_t>(CallLogReadState::CALL_IS_READ));
202 predicates.EqualTo(CALL_IS_READ, static_cast<int32_t>(CallLogReadState::CALL_IS_UNREAD));
203 predicates.And();
204 predicates.EqualTo(CALL_DIRECTION, static_cast<int32_t>(CallDirection::CALL_DIRECTION_IN));
205 predicates.And();
206 predicates.EqualTo(CALL_ANSWER_STATE, static_cast<int32_t>(CallAnswerType::CALL_ANSWER_MISSED));
207 bool ret = callDataPtr->Update(predicates, bucket);
208 if (ret) {
209 TELEPHONY_LOGE("Update call log database fail!");
210 return TELEPHONY_ERR_DATABASE_WRITE_FAIL;
211 }
212 TELEPHONY_LOGI("Update call log database success!");
213 return TELEPHONY_SUCCESS;
214 }
215
QueryUnReadMissedCallLog()216 int32_t CallRecordsHandlerService::QueryUnReadMissedCallLog()
217 {
218 if (handler_.get() == nullptr) {
219 TELEPHONY_LOGE("handler_ is nullptr");
220 return TELEPHONY_ERR_LOCAL_PTR_NULL;
221 }
222 ffrt::submit([=]() { handler_->QueryAndNotifyUnReadMissedCall(); });
223 return TELEPHONY_SUCCESS;
224 }
225 } // namespace Telephony
226 } // namespace OHOS
227