1 /*
2 * Copyright (C) 2024 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 #define MLOG_TAG "Scanner"
16
17 #include "ringtone_scanner_db.h"
18
19 #include "result_set_utils.h"
20 #include "rdb_errno.h"
21 #include "ringtone_errno.h"
22 #include "ringtone_file_utils.h"
23 #include "ringtone_log.h"
24 #include "ringtone_rdbstore.h"
25
26 namespace OHOS {
27 namespace Media {
28 using namespace std;
29 using namespace OHOS::NativeRdb;
30 using namespace OHOS::DataShare;
GetFileBasicInfo(const string & path,unique_ptr<RingtoneMetadata> & ptr)31 int32_t RingtoneScannerDb::GetFileBasicInfo(const string &path, unique_ptr<RingtoneMetadata> &ptr)
32 {
33 vector<string> columns = {};
34 string whereClause = RINGTONE_COLUMN_DATA + " = ?";
35 vector<string> args = { path };
36
37 Uri uri("");
38 RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::QUERY);
39 cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
40 cmd.GetAbsRdbPredicates()->SetWhereArgs(args);
41
42 shared_ptr<NativeRdb::ResultSet> resultSet;
43 int32_t ret = GetFileSet(cmd, columns, resultSet);
44 if (ret != E_OK) {
45 RINGTONE_ERR_LOG("Update operation failed. ret=%{public}d", ret);
46 return E_DB_FAIL;
47 }
48
49 return FillMetadata(resultSet, ptr);
50 }
51
GetVibrateFileBasicInfo(const string & path,unique_ptr<VibrateMetadata> & ptr)52 int32_t RingtoneScannerDb::GetVibrateFileBasicInfo(const string &path, unique_ptr<VibrateMetadata> &ptr)
53 {
54 vector<string> columns = {
55 VIBRATE_COLUMN_VIBRATE_ID, VIBRATE_COLUMN_SIZE, VIBRATE_COLUMN_DATE_MODIFIED, VIBRATE_COLUMN_TITLE,
56 VIBRATE_COLUMN_DATE_ADDED
57 };
58 string whereClause = VIBRATE_COLUMN_DATA + " = ?";
59 vector<string> args = { path };
60
61 Uri uri("");
62 RingtoneDataCommand cmd(uri, VIBRATE_TABLE, RingtoneOperationType::QUERY);
63 cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
64 cmd.GetAbsRdbPredicates()->SetWhereArgs(args);
65
66 shared_ptr<NativeRdb::ResultSet> resultSet;
67 int32_t ret = GetFileSet(cmd, columns, resultSet);
68 if (ret != E_OK) {
69 RINGTONE_ERR_LOG("Update operation failed. ret=%{public}d", ret);
70 return E_DB_FAIL;
71 }
72
73 return FillVibrateMetadata(resultSet, ptr);
74 }
75
QueryRingtoneRdb(const string & whereClause,vector<string> & whereArgs,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet,const string & tableName)76 int32_t RingtoneScannerDb::QueryRingtoneRdb(const string &whereClause, vector<string> &whereArgs,
77 const vector<string> &columns, shared_ptr<NativeRdb::ResultSet> &resultSet, const string &tableName)
78 {
79 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
80 if (rawRdb == nullptr) {
81 RINGTONE_ERR_LOG("get raw rdb failed");
82 return E_RDB;
83 }
84
85 AbsRdbPredicates absRdbPredicates(tableName);
86 absRdbPredicates.SetWhereClause(whereClause);
87 absRdbPredicates.SetWhereArgs(whereArgs);
88 resultSet = rawRdb->Query(absRdbPredicates, columns);
89 if (resultSet == nullptr) {
90 RINGTONE_ERR_LOG("return nullptr when query rdb");
91 return E_RDB;
92 }
93
94 return E_OK;
95 }
96
UpdateRingtoneRdb(ValuesBucket & values,const string & whereClause,vector<string> & whereArgs,const string & tableName)97 int32_t RingtoneScannerDb::UpdateRingtoneRdb(ValuesBucket &values, const string &whereClause,
98 vector<string> &whereArgs, const string &tableName)
99 {
100 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
101 if (rawRdb == nullptr) {
102 RINGTONE_ERR_LOG("get raw rdb failed");
103 return E_RDB;
104 }
105 int32_t updateCount = 0;
106 int32_t result = rawRdb->Update(updateCount, tableName, values, whereClause, whereArgs);
107 if (result != NativeRdb::E_OK) {
108 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
109 return E_DB_FAIL;
110 }
111 return updateCount;
112 }
113
FillMetadata(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<RingtoneMetadata> & ptr)114 int32_t RingtoneScannerDb::FillMetadata(const shared_ptr<NativeRdb::ResultSet> &resultSet,
115 unique_ptr<RingtoneMetadata> &ptr)
116 {
117 std::vector<std::string> columnNames;
118 int32_t err = resultSet->GetAllColumnNames(columnNames);
119 if (err != NativeRdb::E_OK) {
120 RINGTONE_ERR_LOG("failed to get all column names");
121 return E_RDB;
122 }
123
124 for (const auto &col : columnNames) {
125 ExtractMetaFromColumn(resultSet, ptr, col);
126 }
127
128 return E_OK;
129 }
130
FillVibrateMetadata(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<VibrateMetadata> & ptr)131 int32_t RingtoneScannerDb::FillVibrateMetadata(const shared_ptr<NativeRdb::ResultSet> &resultSet,
132 unique_ptr<VibrateMetadata> &ptr)
133 {
134 std::vector<std::string> columnNames;
135 int32_t err = resultSet->GetAllColumnNames(columnNames);
136 if (err != NativeRdb::E_OK) {
137 RINGTONE_ERR_LOG("failed to get all column names");
138 return E_RDB;
139 }
140
141 for (const auto &col : columnNames) {
142 ExtractVibrateMetaFromColumn(resultSet, ptr, col);
143 }
144
145 return E_OK;
146 }
147
ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<RingtoneMetadata> & metadata,const std::string & col)148 void RingtoneScannerDb::ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> &resultSet,
149 unique_ptr<RingtoneMetadata> &metadata, const std::string &col)
150 {
151 RingtoneResultSetDataType dataType = RingtoneResultSetDataType::DATA_TYPE_NULL;
152 RingtoneMetadata::RingtoneMetadataFnPtr requestFunc = nullptr;
153 auto itr = metadata->memberFuncMap_.find(col);
154 if (itr != metadata->memberFuncMap_.end()) {
155 dataType = itr->second.first;
156 requestFunc = itr->second.second;
157 } else {
158 RINGTONE_ERR_LOG("invalid column name %{private}s", col.c_str());
159 return;
160 }
161
162 std::variant<int32_t, std::string, int64_t, double> data =
163 ResultSetUtils::GetValFromColumn<const shared_ptr<NativeRdb::ResultSet>>(col, resultSet, dataType);
164
165 // Use the function pointer from map and pass data to fn ptr
166 if (requestFunc != nullptr) {
167 (metadata.get()->*requestFunc)(data);
168 }
169 }
170
ExtractVibrateMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<VibrateMetadata> & metadata,const std::string & col)171 void RingtoneScannerDb::ExtractVibrateMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> &resultSet,
172 unique_ptr<VibrateMetadata> &metadata, const std::string &col)
173 {
174 RingtoneResultSetDataType dataType = RingtoneResultSetDataType::DATA_TYPE_NULL;
175 VibrateMetadata::VibrateMetadataFnPtr requestFunc = nullptr;
176 auto itr = metadata->memberFuncMap_.find(col);
177 if (itr != metadata->memberFuncMap_.end()) {
178 dataType = itr->second.first;
179 requestFunc = itr->second.second;
180 } else {
181 RINGTONE_ERR_LOG("invalid column name %{private}s", col.c_str());
182 return;
183 }
184
185 std::variant<int32_t, std::string, int64_t, double> data =
186 ResultSetUtils::GetValFromColumn<const shared_ptr<NativeRdb::ResultSet>>(col, resultSet, dataType);
187
188 // Use the function pointer from map and pass data to fn ptr
189 if (requestFunc != nullptr) {
190 (metadata.get()->*requestFunc)(data);
191 }
192 }
193
GetFileSet(RingtoneDataCommand & cmd,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet)194 int32_t RingtoneScannerDb::GetFileSet(RingtoneDataCommand &cmd, const vector<string> &columns,
195 shared_ptr<NativeRdb::ResultSet> &resultSet)
196 {
197 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
198 if (rawRdb == nullptr) {
199 RINGTONE_ERR_LOG("get raw rdb failed");
200 return E_RDB;
201 }
202 resultSet = rawRdb->Query(*cmd.GetAbsRdbPredicates(), columns);
203 if (resultSet == nullptr) {
204 RINGTONE_ERR_LOG("return nullptr when query rdb");
205 return E_RDB;
206 }
207
208 int32_t rowCount = 0;
209 int32_t ret = resultSet->GetRowCount(rowCount);
210 if (ret != NativeRdb::E_OK) {
211 RINGTONE_ERR_LOG("failed to get row count");
212 return E_RDB;
213 }
214 if (rowCount == 0) {
215 return E_OK;
216 }
217
218 ret = resultSet->GoToFirstRow();
219 if (ret != NativeRdb::E_OK) {
220 RINGTONE_ERR_LOG("failed to go to first row");
221 return E_RDB;
222 }
223 return E_OK;
224 }
225
InsertDateAdded(const RingtoneMetadata & metadata,ValuesBucket & outValues)226 static void InsertDateAdded(const RingtoneMetadata &metadata, ValuesBucket &outValues)
227 {
228 int64_t dateAdded = metadata.GetDateAdded();
229 if (dateAdded == 0) {
230 int64_t dateTaken = metadata.GetDateTaken();
231 if (dateTaken == 0) {
232 int64_t dateModified = metadata.GetDateModified();
233 if (dateModified == 0) {
234 dateAdded = RingtoneFileUtils::UTCTimeMilliSeconds();
235 RINGTONE_WARN_LOG("Invalid dateAdded time, use current time instead: %{public}" PRId64, dateAdded);
236 } else {
237 dateAdded = dateModified;
238 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateModified instead: %{public}" PRId64, dateAdded);
239 }
240 } else {
241 dateAdded = dateTaken * MSEC_TO_SEC;
242 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateTaken instead: %{public}" PRId64, dateAdded);
243 }
244 }
245 outValues.PutLong(RINGTONE_COLUMN_DATE_ADDED, dateAdded);
246 }
247
InsertVibrateDateAdded(const VibrateMetadata & metadata,ValuesBucket & outValues)248 static void InsertVibrateDateAdded(const VibrateMetadata &metadata, ValuesBucket &outValues)
249 {
250 int64_t dateAdded = metadata.GetDateAdded();
251 if (dateAdded == 0) {
252 int64_t dateTaken = metadata.GetDateTaken();
253 if (dateTaken == 0) {
254 int64_t dateModified = metadata.GetDateModified();
255 if (dateModified == 0) {
256 dateAdded = RingtoneFileUtils::UTCTimeMilliSeconds();
257 RINGTONE_WARN_LOG("Invalid dateAdded time, use current time instead: %{public}" PRId64, dateAdded);
258 } else {
259 dateAdded = dateModified;
260 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateModified instead: %{public}" PRId64, dateAdded);
261 }
262 } else {
263 dateAdded = dateTaken * MSEC_TO_SEC;
264 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateTaken instead: %{public}" PRId64, dateAdded);
265 }
266 }
267 outValues.PutLong(VIBRATE_COLUMN_DATE_ADDED, dateAdded);
268 }
269
SetValuesFromMetaData(const RingtoneMetadata & metadata,ValuesBucket & values,bool isInsert)270 static void SetValuesFromMetaData(const RingtoneMetadata &metadata, ValuesBucket &values, bool isInsert)
271 {
272 values.PutString(RINGTONE_COLUMN_DATA, metadata.GetData());
273 values.PutLong(RINGTONE_COLUMN_SIZE, metadata.GetSize());
274 values.PutString(RINGTONE_COLUMN_DISPLAY_NAME, metadata.GetDisplayName());
275 values.PutString(RINGTONE_COLUMN_TITLE, metadata.GetTitle());
276 values.PutInt(RINGTONE_COLUMN_MEDIA_TYPE, metadata.GetMediaType());
277 values.PutInt(RINGTONE_COLUMN_TONE_TYPE, metadata.GetToneType());
278 values.PutString(RINGTONE_COLUMN_MIME_TYPE, metadata.GetMimeType());
279 values.PutInt(RINGTONE_COLUMN_SOURCE_TYPE, metadata.GetSourceType());
280 values.PutLong(RINGTONE_COLUMN_DATE_MODIFIED, metadata.GetDateModified());
281 values.PutLong(RINGTONE_COLUMN_DATE_TAKEN, metadata.GetDateTaken());
282 values.PutInt(RINGTONE_COLUMN_DURATION, metadata.GetDuration());
283 values.PutInt(RINGTONE_COLUMN_SHOT_TONE_TYPE, metadata.GetShotToneType());
284 values.PutInt(RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, metadata.GetShotToneSourceType());
285 values.PutInt(RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE, metadata.GetNotificationToneType());
286 values.PutInt(RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE, metadata.GetNotificationToneSourceType());
287 values.PutInt(RINGTONE_COLUMN_RING_TONE_TYPE, metadata.GetRingToneType());
288 values.PutInt(RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, metadata.GetRingToneSourceType());
289 values.PutInt(RINGTONE_COLUMN_ALARM_TONE_TYPE, metadata.GetAlarmToneType());
290 values.PutInt(RINGTONE_COLUMN_ALARM_TONE_SOURCE_TYPE, metadata.GetAlarmToneSourceType());
291
292 if (isInsert) {
293 InsertDateAdded(metadata, values);
294 return;
295 }
296 }
297
SetValuesFromVibrateMetaData(const VibrateMetadata & metadata,ValuesBucket & values,bool isInsert)298 static void SetValuesFromVibrateMetaData(const VibrateMetadata &metadata, ValuesBucket &values, bool isInsert)
299 {
300 values.PutString(VIBRATE_COLUMN_DATA, metadata.GetData());
301 values.PutLong(VIBRATE_COLUMN_SIZE, metadata.GetSize());
302 values.PutString(VIBRATE_COLUMN_DISPLAY_NAME, metadata.GetDisplayName());
303 values.PutString(VIBRATE_COLUMN_TITLE, metadata.GetTitle());
304 values.PutString(VIBRATE_COLUMN_DISPLAY_LANGUAGE, metadata.GetDisplayLanguage());
305 values.PutInt(VIBRATE_COLUMN_VIBRATE_TYPE, metadata.GetVibrateType());
306 values.PutInt(VIBRATE_COLUMN_SOURCE_TYPE, metadata.GetSourceType());
307 values.PutLong(VIBRATE_COLUMN_DATE_MODIFIED, metadata.GetDateModified());
308 values.PutLong(VIBRATE_COLUMN_DATE_TAKEN, metadata.GetDateTaken());
309 values.PutInt(VIBRATE_COLUMN_PLAY_MODE, metadata.GetPlayMode());
310
311 if (isInsert) {
312 InsertVibrateDateAdded(metadata, values);
313 }
314 }
315
UpdateMetadata(const RingtoneMetadata & metadata,string & tableName)316 int32_t RingtoneScannerDb::UpdateMetadata(const RingtoneMetadata &metadata, string &tableName)
317 {
318 int32_t updateCount = 0;
319 ValuesBucket values;
320 string whereClause = RINGTONE_COLUMN_TONE_ID + " = ?";
321 vector<string> whereArgs = { to_string(metadata.GetToneId()) };
322
323 SetValuesFromMetaData(metadata, values, false);
324
325 tableName = RINGTONE_TABLE;
326 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
327 if (rawRdb == nullptr) {
328 RINGTONE_ERR_LOG("get raw rdb failed");
329 return E_RDB;
330 }
331 int32_t result = rawRdb->Update(updateCount, tableName, values, whereClause, whereArgs);
332 if (result != NativeRdb::E_OK || updateCount <= 0) {
333 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
334 return E_DB_FAIL;
335 }
336 return updateCount;
337 }
338
UpdateVibrateMetadata(const VibrateMetadata & metadata,string & tableName)339 int32_t RingtoneScannerDb::UpdateVibrateMetadata(const VibrateMetadata &metadata, string &tableName)
340 {
341 int32_t updateCount = 0;
342 ValuesBucket values;
343 string whereClause = VIBRATE_COLUMN_VIBRATE_ID + " = ?";
344 vector<string> whereArgs = { to_string(metadata.GetVibrateId()) };
345
346 SetValuesFromVibrateMetaData(metadata, values, false);
347
348 tableName = VIBRATE_TABLE;
349 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
350 if (rawRdb == nullptr) {
351 RINGTONE_ERR_LOG("get raw rdb failed");
352 return E_RDB;
353 }
354 int32_t result = rawRdb->Update(updateCount, tableName, values, whereClause, whereArgs);
355 if (result != NativeRdb::E_OK || updateCount <= 0) {
356 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
357 return E_DB_FAIL;
358 }
359 return updateCount;
360 }
361
InsertMetadata(const RingtoneMetadata & metadata,string & tableName)362 int32_t RingtoneScannerDb::InsertMetadata(const RingtoneMetadata &metadata, string &tableName)
363 {
364 ValuesBucket values;
365 int32_t rowNum = 0;
366 tableName = RINGTONE_TABLE;
367
368 SetValuesFromMetaData(metadata, values, true);
369 if (!InsertData(values, tableName, rowNum)) {
370 return E_DB_FAIL;
371 }
372
373 return rowNum;
374 }
375
InsertVibrateMetadata(const VibrateMetadata & metadata,string & tableName)376 int32_t RingtoneScannerDb::InsertVibrateMetadata(const VibrateMetadata &metadata, string &tableName)
377 {
378 ValuesBucket values;
379 int32_t rowNum = 0;
380 tableName = VIBRATE_TABLE;
381
382 SetValuesFromVibrateMetaData(metadata, values, true);
383 if (!InsertData(values, tableName, rowNum)) {
384 return E_DB_FAIL;
385 }
386
387 return rowNum;
388 }
389
InsertData(const ValuesBucket values,const string & tableName,int32_t & rowNum)390 bool RingtoneScannerDb::InsertData(const ValuesBucket values, const string &tableName, int32_t &rowNum)
391 {
392 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
393 if (rawRdb == nullptr) {
394 RINGTONE_ERR_LOG("get raw rdb failed");
395 return E_RDB;
396 }
397
398 int64_t nRow = static_cast<int64_t>(rowNum);
399 int32_t result = rawRdb->Insert(nRow, tableName, values);
400 if (nRow <= 0) {
401 RINGTONE_ERR_LOG("Ringtone library Insert functionality is failed, rowNum %{public}ld", (long) nRow);
402 return false;
403 }
404
405 if (result != NativeRdb::E_OK) {
406 RINGTONE_ERR_LOG("Ringtone library Insert functionality is failed, return %{public}d", result);
407 return false;
408 }
409
410 if (nRow < std::numeric_limits<int32_t>::min() || nRow > std::numeric_limits<int32_t>::max()) {
411 return false;
412 }
413 rowNum = static_cast<int32_t>(nRow);
414
415 return true;
416 }
417 } // namespace Media
418 } // namespace OHOS
419