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