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 "download_data_ability.h"
17
18 #include <mutex>
19
20 #include "ability_loader.h"
21 #include "common_event.h"
22 #include "constant.h"
23 #include "data_ability_predicates.h"
24 #include "db_path.h"
25 #include "file_utils.h"
26 #include "log.h"
27 #include "predicates_convert.h"
28 #include "rdb_predicates.h"
29 #include "sql_analyzer.h"
30 #include "uri_utils.h"
31
32
33 namespace OHOS::AppExecFwk {
34 REGISTER_AA(DownloadDataAbility);
35 namespace {
36 std::mutex g_mutex;
37 }
38 using namespace OHOS::Request::Download;
39
40 std::shared_ptr<DownloadDataBase> DownloadDataAbility::database_ = nullptr;
41 std::map<std::string, int> DownloadDataAbility::uriValueMap_ = {
42 {"/com.ohos.download/download/downloadInfo", DOWNLOAD_INFO}};
43
DownloadDataAbility()44 DownloadDataAbility::DownloadDataAbility()
45 {
46 }
47
~DownloadDataAbility()48 DownloadDataAbility::~DownloadDataAbility()
49 {
50 }
51
Dump(const std::string & extra)52 void DownloadDataAbility::Dump(const std::string &extra)
53 {
54 DOWNLOAD_HILOGE("DownloadDataAbility ====>Dump:%{public}s", extra.c_str());
55 FileUtils fileUtils;
56 std::string dirStr = DBPath::DUMP_PATH;
57 fileUtils.WriteStringToFileAppend(dirStr, extra);
58 }
59
OnStart(const Want & want)60 void DownloadDataAbility::OnStart(const Want &want)
61 {
62 DOWNLOAD_HILOGE("DownloadDataAbility OnStart");
63 std::string basePath = GetDatabaseDir();
64 DBPath::RDB_PATH = basePath + "/";
65 DBPath::RDB_BACKUP_PATH = basePath + "/backup/";
66 DBPath::DUMP_PATH = GetFilesDir() + "/";
67 }
68
UriParse(Uri & uri)69 int DownloadDataAbility::UriParse(Uri &uri)
70 {
71 UriUtils uriUtils;
72 int parseCode = uriUtils.UriParse(uri, uriValueMap_);
73 return parseCode;
74 }
75
76 /**
77 * @brief DownloadDataAbility BeginTransaction emptiness problems
78 *
79 * @param code the return number of BeginTransaction
80 * @param mutex transmission parameter : lock
81 *
82 * @return BeginTransaction emptiness true or false
83 */
IsBeginTransactionOK(int code,std::mutex & mutex)84 bool DownloadDataAbility::IsBeginTransactionOK(int code, std::mutex &mutex)
85 {
86 mutex.try_lock();
87 if (code != 0) {
88 DOWNLOAD_HILOGE("IsBeginTransactionOK fail");
89 mutex.unlock();
90 return false;
91 }
92 return true;
93 }
94
95 /**
96 * @brief DownloadDataAbility Commit emptiness problems
97 *
98 * @param code the return number of Commit
99 * @param mutex transmission parameter : lock
100 *
101 * @return Commit emptiness true or false
102 */
IsCommitOk(int code,std::mutex & mutex)103 bool DownloadDataAbility::IsCommitOk(int code, std::mutex &mutex)
104 {
105 mutex.try_lock();
106 if (code != 0) {
107 DOWNLOAD_HILOGE("IsCommitOk fail");
108 mutex.unlock();
109 return false;
110 }
111 return true;
112 }
113
114 /**
115 * @brief DownloadDataAbility Insert database
116 *
117 * @param uri Determine the data table name based on the URI
118 * @param value Insert the data value of the database
119 *
120 * @return Insert database results code
121 */
Insert(const Uri & uri,const NativeRdb::ValuesBucket & value)122 int DownloadDataAbility::Insert(const Uri &uri, const NativeRdb::ValuesBucket &value)
123 {
124 DOWNLOAD_HILOGE("DownloadDataAbility Insert OnStart");
125 SqlAnalyzer sqlAnalyzer;
126 bool isOk = sqlAnalyzer.CheckValuesBucket(value);
127 if (!isOk) {
128 DOWNLOAD_HILOGE("DownloadDataAbility CheckValuesBucket is error");
129 return RDB_EXECUTE_FAIL;
130 }
131 g_mutex.lock();
132 database_ = DownloadDataBase::GetInstance();
133 int ret = database_->BeginTransaction();
134 if (!IsBeginTransactionOK(ret, g_mutex)) {
135 g_mutex.unlock();
136 return RDB_EXECUTE_FAIL;
137 }
138 int resultId = InsertExecute(uri, value);
139 DOWNLOAD_HILOGE("DownloadDataAbility Insert id %{public}d", resultId);
140 if (resultId == OPERATION_ERROR) {
141 DOWNLOAD_HILOGE("DownloadDataAbility Insert error");
142 ret = database_->RollBack();
143 g_mutex.unlock();
144 return OPERATION_ERROR;
145 }
146 ret = database_->Commit();
147 if (!IsCommitOk(ret, g_mutex)) {
148 DOWNLOAD_HILOGE("DownloadDataAbility Insert error Commit");
149 database_->RollBack();
150 g_mutex.unlock();
151 return RDB_EXECUTE_FAIL;
152 }
153 g_mutex.unlock();
154 DataBaseNotifyChange(DOWNLOAD_INSERT, uri);
155 return resultId;
156 }
157
InsertExecute(const Uri & uri,const NativeRdb::ValuesBucket & value)158 int DownloadDataAbility::InsertExecute(const Uri &uri, const NativeRdb::ValuesBucket &value)
159 {
160 int rowId = RDB_EXECUTE_FAIL;
161 OHOS::Uri uriTemp = uri;
162 int parseCode = UriParse(uriTemp);
163 switch (parseCode) {
164 case DOWNLOAD_INFO:
165 rowId = database_->Insert(value);
166 break;
167 default:
168 DOWNLOAD_HILOGE("DownloadDataAbility ====>no match uri action");
169 break;
170 }
171 DOWNLOAD_HILOGI("DownloadDataAbility InsertExecute id = %{public}d", rowId);
172 return rowId;
173 }
174
175 /**
176 * @brief DownloadDataAbility BatchInsert database
177 *
178 * @param uri Determine the data table name based on the URI
179 * @param value Insert the data values of the database
180 *
181 * @return Insert database results code
182 */
BatchInsert(const Uri & uri,const std::vector<NativeRdb::ValuesBucket> & values)183 int DownloadDataAbility::BatchInsert(const Uri &uri, const std::vector<NativeRdb::ValuesBucket> &values)
184 {
185 int rowRet = RDB_EXECUTE_FAIL;
186 int size = values.size();
187 if (size <= 0) {
188 DOWNLOAD_HILOGE("BatchInsert value is error");
189 return rowRet;
190 }
191 g_mutex.lock();
192 database_ = DownloadDataBase::GetInstance();
193 int ret = database_->BeginTransaction();
194 if (!IsBeginTransactionOK(ret, g_mutex)) {
195 g_mutex.unlock();
196 return RDB_EXECUTE_FAIL;
197 }
198 int count = 0;
199 for (int i = 0; i < size; i++) {
200 ++count;
201 OHOS::NativeRdb::ValuesBucket rawValues = values[i];
202 int code = InsertExecute(uri, rawValues);
203 if (code == RDB_EXECUTE_FAIL) {
204 database_->RollBack();
205 g_mutex.unlock();
206 return code;
207 }
208 if (count % TRANSACTION_COUNT == 0) {
209 int markRet = database_->Commit();
210 int beginRet = database_->BeginTransaction();
211 if (!IsCommitOk(markRet, g_mutex) || !IsBeginTransactionOK(beginRet, g_mutex)) {
212 database_->RollBack();
213 g_mutex.unlock();
214 return RDB_EXECUTE_FAIL;
215 }
216 }
217 }
218 int markRet = database_->Commit();
219 if (!IsCommitOk(markRet, g_mutex)) {
220 database_->RollBack();
221 g_mutex.unlock();
222 return RDB_EXECUTE_FAIL;
223 }
224 g_mutex.unlock();
225 DataBaseNotifyChange(DOWNLOAD_INSERT, uri);
226 return RDB_EXECUTE_OK;
227 }
228
229 /**
230 * @brief DownloadDataAbility Update database
231 *
232 * @param uri Determine the data table name based on the URI
233 * @param predicates Update the data value of the condition
234 *
235 * @return Update database results code
236 */
Update(const Uri & uri,const NativeRdb::ValuesBucket & value,const NativeRdb::DataAbilityPredicates & predicates)237 int DownloadDataAbility::Update(
238 const Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates)
239 {
240 SqlAnalyzer sqlAnalyzer;
241 bool isOk = sqlAnalyzer.CheckValuesBucket(value);
242 if (!isOk) {
243 DOWNLOAD_HILOGE("DownloadDataAbility CheckValuesBucket is error");
244 return RDB_EXECUTE_FAIL;
245 }
246 g_mutex.lock();
247 database_ = DownloadDataBase::GetInstance();
248 PredicatesConvert predicatesConvert;
249 int ret = RDB_EXECUTE_FAIL;
250 OHOS::Uri uriTemp = uri;
251 int parseCode = UriParse(uriTemp);
252 OHOS::NativeRdb::DataAbilityPredicates dataAbilityPredicates = predicates;
253 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
254 switch (parseCode) {
255 case DOWNLOAD_INFO:
256 rdbPredicates = predicatesConvert.ConvertPredicates(TABLE_NAME, dataAbilityPredicates);
257 ret = database_->Update(value, rdbPredicates);
258 break;
259 default:
260 DOWNLOAD_HILOGE("DownloadDataAbility ====>no match uri action");
261 break;
262 }
263 g_mutex.unlock();
264 DataBaseNotifyChange(DOWNLOAD_UPDATE, uri);
265 return ret;
266 }
267
268 /**
269 * @brief DownloadDataAbility Delete database
270 *
271 * @param uri Determine the data table name based on the URI
272 * @param predicates Delete the data values of the condition
273 *
274 * @return Delete database results code
275 */
Delete(const Uri & uri,const NativeRdb::DataAbilityPredicates & predicates)276 int DownloadDataAbility::Delete(const Uri &uri, const NativeRdb::DataAbilityPredicates &predicates)
277 {
278 g_mutex.lock();
279 database_ = DownloadDataBase::GetInstance();
280 PredicatesConvert predicatesConvert;
281 int ret = RDB_EXECUTE_FAIL;
282 OHOS::Uri uriTemp = uri;
283 int parseCode = UriParse(uriTemp);
284 OHOS::NativeRdb::DataAbilityPredicates dataAbilityPredicates = predicates;
285 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
286 switch (parseCode) {
287 case DOWNLOAD_INFO:
288 rdbPredicates = predicatesConvert.ConvertPredicates(TABLE_NAME, dataAbilityPredicates);
289 ret = database_->Delete(rdbPredicates);
290 break;
291 default:
292 DOWNLOAD_HILOGE("DownloadDataAbility ====>no match uri action");
293 break;
294 }
295 g_mutex.unlock();
296 DataBaseNotifyChange(DOWNLOAD_DELETE, uri);
297 return ret;
298 }
299
300 /**
301 * @brief DownloadDataAbility Query database
302 *
303 * @param uri Determine the data table name based on the URI
304 * @param columns Columns returned by query
305 * @param predicates Query the data values of the condition
306 *
307 * @return Query database results
308 */
Query(const Uri & uri,const std::vector<std::string> & columns,const NativeRdb::DataAbilityPredicates & predicates)309 std::shared_ptr<NativeRdb::AbsSharedResultSet> DownloadDataAbility::Query(
310 const Uri &uri, const std::vector<std::string> &columns, const NativeRdb::DataAbilityPredicates &predicates)
311 {
312 DOWNLOAD_HILOGI("DownloadDataAbility ====>Query start");
313 database_ = DownloadDataBase::GetInstance();
314 PredicatesConvert predicatesConvert;
315 std::shared_ptr<NativeRdb::AbsSharedResultSet> result;
316 OHOS::Uri uriTemp = uri;
317 UriUtils uriUtils;
318 int parseCode = uriUtils.UriParse(uriTemp, uriValueMap_);
319 OHOS::NativeRdb::DataAbilityPredicates dataAbilityPredicates = predicates;
320 OHOS::NativeRdb::RdbPredicates rdbPredicates("");
321 std::vector<std::string> columnsTemp = columns;
322 switch (parseCode) {
323 case DOWNLOAD_INFO:
324 rdbPredicates = predicatesConvert.ConvertPredicates(TABLE_NAME, dataAbilityPredicates);
325 result = database_->Query(rdbPredicates, columnsTemp);
326 break;
327 default:
328 DOWNLOAD_HILOGE("DownloadDataAbility ====>no match uri action");
329 break;
330 }
331 std::shared_ptr<OHOS::NativeRdb::AbsSharedResultSet> sharedPtrResult = std::move(result);
332 DOWNLOAD_HILOGI("DownloadDataAbility ====>Query end");
333 return sharedPtrResult;
334 }
335
DataBaseNotifyChange(int code,Uri uri)336 void DownloadDataAbility::DataBaseNotifyChange(int code, Uri uri)
337 {
338 CommonEvent::SendChange(code);
339 }
340 } // namespace OHOS::AppExecFwk