• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "calllog_ability.h"
17 
18 #include <mutex>
19 
20 #include "common.h"
21 #include "contacts_common_event.h"
22 #include "contacts_datashare_stub_impl.h"
23 #include "datashare_ext_ability_context.h"
24 #include "datashare_predicates.h"
25 #include "file_utils.h"
26 #include "predicates_convert.h"
27 #include "rdb_predicates.h"
28 #include "rdb_utils.h"
29 #include "sql_analyzer.h"
30 #include "uri_utils.h"
31 
32 namespace OHOS {
33 namespace AbilityRuntime {
34 namespace {
35 std::mutex g_mutex;
36 }
37 std::shared_ptr<Contacts::CallLogDataBase> CallLogAbility::callLogDataBase_ = nullptr;
38 std::map<std::string, int> CallLogAbility::uriValueMap_ = {
39     {"/com.ohos.calllogability/calls/calllog", Contacts::CALLLOG}
40 };
41 
Create()42 CallLogAbility* CallLogAbility::Create()
43 {
44     return new CallLogAbility();
45 }
46 
CallLogAbility()47 CallLogAbility::CallLogAbility() : DataShareExtAbility()
48 {
49 }
50 
~CallLogAbility()51 CallLogAbility::~CallLogAbility()
52 {
53 }
54 
OnConnect(const AAFwk::Want & want)55 sptr<IRemoteObject> CallLogAbility::OnConnect(const AAFwk::Want &want)
56 {
57     HILOG_INFO("CallLogAbility %{public}s begin.", __func__);
58     Extension::OnConnect(want);
59     sptr<DataShare::ContactsDataShareStubImpl> remoteObject =
60         new (std::nothrow) DataShare::ContactsDataShareStubImpl();
61     if (remoteObject == nullptr) {
62         HILOG_ERROR("%{public}s No memory allocated for DataShareStubImpl", __func__);
63         return nullptr;
64     }
65     remoteObject->SetCallLogAbility(std::static_pointer_cast<CallLogAbility>(shared_from_this()));
66     HILOG_INFO("CallLogAbility %{public}s end.", __func__);
67     return remoteObject->AsObject();
68 }
69 
OnStart(const Want & want)70 void CallLogAbility::OnStart(const Want &want)
71 {
72     HILOG_INFO("CallLogAbility %{public}s begin.", __func__);
73     Extension::OnStart(want);
74     auto context = AbilityRuntime::Context::GetApplicationContext();
75     if (context != nullptr) {
76         context->SwitchArea(0);
77         std::string basePath = context->GetDatabaseDir();
78         Contacts::ContactsPath::RDB_PATH = basePath + "/";
79         Contacts::ContactsPath::RDB_BACKUP_PATH = basePath + "/backup/";
80     }
81 }
82 
UriParse(Uri & uri)83 int CallLogAbility::UriParse(Uri &uri)
84 {
85     Contacts::UriUtils uriUtils;
86     int parseCode = uriUtils.UriParse(uri, uriValueMap_);
87     return parseCode;
88 }
89 
90 /**
91  * @brief CallLogAbility BeginTransaction emptiness problems
92  *
93  * @param code the return number of BeginTransaction
94  * @param mutex transmission parameter : lock
95  *
96  * @return BeginTransaction emptiness true or false
97  */
IsBeginTransactionOK(int code,std::mutex & mutex)98 bool CallLogAbility::IsBeginTransactionOK(int code, std::mutex &mutex)
99 {
100     mutex.try_lock();
101     if (code != 0) {
102         HILOG_ERROR("IsBeginTransactionOK fail");
103         mutex.unlock();
104         return false;
105     }
106     return true;
107 }
108 
109 /**
110  * @brief CallLogAbility Commit emptiness problems
111  *
112  * @param code the return number of Commit
113  * @param mutex transmission parameter : lock
114  *
115  * @return Commit emptiness true or false
116  */
IsCommitOk(int code,std::mutex & mutex)117 bool CallLogAbility::IsCommitOk(int code, std::mutex &mutex)
118 {
119     mutex.try_lock();
120     if (code != 0) {
121         HILOG_ERROR("IsCommitOk fail");
122         mutex.unlock();
123         return false;
124     }
125     return true;
126 }
127 
128 /**
129  * @brief CallLogAbility Insert database
130  *
131  * @param uri Determine the data table name based on the URI
132  * @param value Insert the data value of the database
133  *
134  * @return Insert database results code
135  */
Insert(const Uri & uri,const DataShare::DataShareValuesBucket & value)136 int CallLogAbility::Insert(const Uri &uri, const DataShare::DataShareValuesBucket &value)
137 {
138     if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::WRITE_CALL_LOG)) {
139         HILOG_ERROR("Permission denied!");
140         return Contacts::RDB_PERMISSION_ERROR;
141     }
142     OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
143     Contacts::SqlAnalyzer sqlAnalyzer;
144     bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
145     if (!isOk) {
146         HILOG_ERROR("CallLogAbility CheckValuesBucket is error");
147         return Contacts::RDB_EXECUTE_FAIL;
148     }
149     g_mutex.lock();
150     callLogDataBase_ = Contacts::CallLogDataBase::GetInstance();
151     int ret = callLogDataBase_->BeginTransaction();
152     if (!IsBeginTransactionOK(ret, g_mutex)) {
153         g_mutex.unlock();
154         return Contacts::RDB_EXECUTE_FAIL;
155     }
156     int resultId = InsertExecute(uri, valuesBucket);
157     if (resultId == Contacts::OPERATION_ERROR) {
158         callLogDataBase_->RollBack();
159         g_mutex.unlock();
160         return Contacts::OPERATION_ERROR;
161     }
162     ret = callLogDataBase_->Commit();
163     if (!IsCommitOk(ret, g_mutex)) {
164         callLogDataBase_->RollBack();
165         g_mutex.unlock();
166         return Contacts::RDB_EXECUTE_FAIL;
167     }
168     g_mutex.unlock();
169     DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
170     return resultId;
171 }
172 
InsertExecute(const Uri & uri,const OHOS::NativeRdb::ValuesBucket & value)173 int CallLogAbility::InsertExecute(const Uri &uri, const OHOS::NativeRdb::ValuesBucket &value)
174 {
175     int rowId = Contacts::RDB_EXECUTE_FAIL;
176     OHOS::Uri uriTemp = uri;
177     int parseCode = UriParse(uriTemp);
178     switch (parseCode) {
179         case Contacts::CALLLOG:
180             rowId = callLogDataBase_->InsertCallLog(value);
181             break;
182         default:
183             HILOG_ERROR("CallLogAbility ====>no match uri action");
184             break;
185     }
186     return rowId;
187 }
188 
189 /**
190  * @brief CallLogAbility BatchInsert database
191  *
192  * @param uri Determine the data table name based on the URI
193  * @param value Insert the data values of the database
194  *
195  * @return Insert database results code
196  */
BatchInsert(const Uri & uri,const std::vector<DataShare::DataShareValuesBucket> & values)197 int CallLogAbility::BatchInsert(const Uri &uri, const std::vector<DataShare::DataShareValuesBucket> &values)
198 {
199     if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::WRITE_CALL_LOG)) {
200         HILOG_ERROR("Permission denied!");
201         return Contacts::RDB_PERMISSION_ERROR;
202     }
203     int rowRet = Contacts::RDB_EXECUTE_FAIL;
204     unsigned int size = values.size();
205     if (size < 1) {
206         HILOG_ERROR("BatchInsert value is error");
207         return rowRet;
208     }
209     g_mutex.lock();
210     callLogDataBase_ = Contacts::CallLogDataBase::GetInstance();
211     int ret = callLogDataBase_->BeginTransaction();
212     if (!IsBeginTransactionOK(ret, g_mutex)) {
213         g_mutex.unlock();
214         return Contacts::RDB_EXECUTE_FAIL;
215     }
216     int count = 0;
217     for (unsigned int i = 0; i < size; i++) {
218         ++count;
219         DataShare::DataShareValuesBucket rawContactValues = values[i];
220         OHOS::NativeRdb::ValuesBucket value = RdbDataShareAdapter::RdbUtils::ToValuesBucket(rawContactValues);
221         int code = InsertExecute(uri, value);
222         if (code == Contacts::RDB_EXECUTE_FAIL) {
223             callLogDataBase_->RollBack();
224             g_mutex.unlock();
225             return code;
226         }
227         if (count % Contacts::BATCH_INSERT_COUNT == 0) {
228             int markRet = callLogDataBase_->Commit();
229             int beginRet = callLogDataBase_->BeginTransaction();
230             if (!IsCommitOk(markRet, g_mutex) || !IsBeginTransactionOK(beginRet, g_mutex)) {
231                 callLogDataBase_->RollBack();
232                 g_mutex.unlock();
233                 return Contacts::RDB_EXECUTE_FAIL;
234             }
235         }
236     }
237     int markRet = callLogDataBase_->Commit();
238     if (!IsCommitOk(markRet, g_mutex)) {
239         callLogDataBase_->RollBack();
240         g_mutex.unlock();
241         return Contacts::RDB_EXECUTE_FAIL;
242     }
243     g_mutex.unlock();
244     DataBaseNotifyChange(Contacts::CONTACT_INSERT, uri);
245     return Contacts::RDB_EXECUTE_OK;
246 }
247 
248 /**
249  * @brief CallLogAbility Update database
250  *
251  * @param uri Determine the data table name based on the URI
252  * @param predicates Update the data value of the condition
253  *
254  * @return Update database results code
255  */
Update(const Uri & uri,const DataShare::DataSharePredicates & predicates,const DataShare::DataShareValuesBucket & value)256 int CallLogAbility::Update(
257     const Uri &uri, const DataShare::DataSharePredicates &predicates, const DataShare::DataShareValuesBucket &value)
258 {
259     if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::WRITE_CALL_LOG)) {
260         HILOG_ERROR("Permission denied!");
261         return Contacts::RDB_PERMISSION_ERROR;
262     }
263     OHOS::NativeRdb::ValuesBucket valuesBucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
264     Contacts::SqlAnalyzer sqlAnalyzer;
265     bool isOk = sqlAnalyzer.CheckValuesBucket(valuesBucket);
266     if (!isOk) {
267         HILOG_ERROR("CallLogAbility CheckValuesBucket is error");
268         return Contacts::RDB_EXECUTE_FAIL;
269     }
270     g_mutex.lock();
271     callLogDataBase_ = Contacts::CallLogDataBase::GetInstance();
272     Contacts::PredicatesConvert predicatesConvert;
273     int ret = Contacts::RDB_EXECUTE_FAIL;
274     OHOS::Uri uriTemp = uri;
275     int parseCode = UriParse(uriTemp);
276     DataShare::DataSharePredicates dataSharePredicates = predicates;
277     OHOS::NativeRdb::RdbPredicates rdbPredicates("");
278     switch (parseCode) {
279         case Contacts::CALLLOG:
280             rdbPredicates =
281                 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::CALLLOG, dataSharePredicates);
282             ret = callLogDataBase_->UpdateCallLog(valuesBucket, rdbPredicates);
283             break;
284         default:
285             HILOG_ERROR("CallLogAbility ====>no match uri action");
286             break;
287     }
288     g_mutex.unlock();
289     DataBaseNotifyChange(Contacts::CONTACT_UPDATE, uri);
290     return ret;
291 }
292 
293 /**
294  * @brief CallLogAbility Delete database
295  *
296  * @param uri Determine the data table name based on the URI
297  * @param predicates Delete the data values of the condition
298  *
299  * @return Delete database results code
300  */
Delete(const Uri & uri,const DataShare::DataSharePredicates & predicates)301 int CallLogAbility::Delete(const Uri &uri, const DataShare::DataSharePredicates &predicates)
302 {
303     if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::WRITE_CALL_LOG)) {
304         HILOG_ERROR("Permission denied!");
305         return Contacts::RDB_PERMISSION_ERROR;
306     }
307     g_mutex.lock();
308     callLogDataBase_ = Contacts::CallLogDataBase::GetInstance();
309     Contacts::PredicatesConvert predicatesConvert;
310     int ret = Contacts::RDB_EXECUTE_FAIL;
311     OHOS::Uri uriTemp = uri;
312     int parseCode = UriParse(uriTemp);
313     DataShare::DataSharePredicates dataSharePredicates = predicates;
314     OHOS::NativeRdb::RdbPredicates rdbPredicates("");
315     switch (parseCode) {
316         case Contacts::CALLLOG:
317             rdbPredicates =
318                 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::CALLLOG, dataSharePredicates);
319             ret = callLogDataBase_->DeleteCallLog(rdbPredicates);
320             break;
321         default:
322             HILOG_ERROR("CallLogAbility ====>no match uri action");
323             break;
324     }
325     g_mutex.unlock();
326     DataBaseNotifyChange(Contacts::CONTACT_DELETE, uri);
327     return ret;
328 }
329 
330 /**
331  * @brief CallLogAbility Query database
332  *
333  * @param uri Determine the data table name based on the URI
334  * @param columns Columns returned by query
335  * @param predicates Query the data values of the condition
336  *
337  * @return Query database results
338  */
Query(const Uri & uri,const DataShare::DataSharePredicates & predicates,std::vector<std::string> & columns,DataShare::DatashareBusinessError & businessError)339 std::shared_ptr<DataShare::DataShareResultSet> CallLogAbility::Query(const Uri &uri,
340     const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns,
341     DataShare::DatashareBusinessError &businessError)
342 {
343     if (!Telephony::TelephonyPermission::CheckPermission(Telephony::Permission::READ_CALL_LOG)) {
344         HILOG_ERROR("Permission denied!");
345         return nullptr;
346     }
347     HILOG_INFO("CallLogAbility ====>Query start");
348     g_mutex.lock();
349     callLogDataBase_ = Contacts::CallLogDataBase::GetInstance();
350     if (callLogDataBase_ == nullptr) {
351         HILOG_ERROR("AbsSharedResultSet is nullptr");
352         return nullptr;
353     }
354     Contacts::PredicatesConvert predicatesConvert;
355     std::shared_ptr<OHOS::NativeRdb::ResultSet> result;
356     OHOS::Uri uriTemp = uri;
357     Contacts::UriUtils uriUtils;
358     int parseCode = uriUtils.UriParse(uriTemp, uriValueMap_);
359     HILOG_INFO("CallLogAbility ====>Query parseCode");
360     DataShare::DataSharePredicates dataSharePredicates = predicates;
361     OHOS::NativeRdb::RdbPredicates rdbPredicates("");
362     std::vector<std::string> columnsTemp = columns;
363     bool isUriMatch = true;
364     switch (parseCode) {
365         case Contacts::CALLLOG:
366             rdbPredicates =
367                 predicatesConvert.ConvertPredicates(Contacts::CallsTableName::CALLLOG, dataSharePredicates);
368             result = callLogDataBase_->Query(rdbPredicates, columnsTemp);
369             break;
370         default:
371             isUriMatch = false;
372             HILOG_ERROR("CallLogAbility ====>no match uri action");
373             break;
374     }
375     if (!isUriMatch) {
376         g_mutex.unlock();
377         return nullptr;
378     }
379     if (result == nullptr) {
380         HILOG_ERROR("AbsSharedResultSet is nullptr");
381         g_mutex.unlock();
382         return nullptr;
383     }
384     auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(result);
385     std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult =
386         std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
387     g_mutex.unlock();
388     HILOG_INFO("CallLogAbility ====>Query end");
389     return sharedPtrResult;
390 }
391 
DataBaseNotifyChange(int code,Uri uri)392 void CallLogAbility::DataBaseNotifyChange(int code, Uri uri)
393 {
394     Contacts::ContactsCommonEvent::SendCallLogChange(code);
395 }
396 } // namespace AbilityRuntime
397 } // namespace OHOS
398