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 RINGTONE_COLUMN_TONE_ID, RINGTONE_COLUMN_SIZE, RINGTONE_COLUMN_DATE_MODIFIED, RINGTONE_COLUMN_TITLE,
35 RINGTONE_COLUMN_DATE_ADDED
36 };
37 string whereClause = RINGTONE_COLUMN_DATA + " = ?";
38 vector<string> args = { path };
39
40 Uri uri("");
41 RingtoneDataCommand cmd(uri, RINGTONE_TABLE, RingtoneOperationType::QUERY);
42 cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
43 cmd.GetAbsRdbPredicates()->SetWhereArgs(args);
44
45 shared_ptr<NativeRdb::ResultSet> resultSet;
46 int32_t ret = GetFileSet(cmd, columns, resultSet);
47 if (ret != E_OK) {
48 RINGTONE_ERR_LOG("Update operation failed. ret=%{public}d", ret);
49 return E_DB_FAIL;
50 }
51
52 return FillMetadata(resultSet, ptr);
53 }
54
QueryRingtoneRdb(string & whereClause,vector<string> & whereArgs,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet)55 int32_t RingtoneScannerDb::QueryRingtoneRdb(string &whereClause, vector<string> &whereArgs,
56 const vector<string> &columns, shared_ptr<NativeRdb::ResultSet> &resultSet)
57 {
58 string tableName = RINGTONE_TABLE;
59 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
60 if (rawRdb == nullptr) {
61 RINGTONE_ERR_LOG("get raw rdb failed");
62 return E_RDB;
63 }
64
65 AbsRdbPredicates absRdbPredicates(tableName);
66 absRdbPredicates.SetWhereClause(whereClause);
67 absRdbPredicates.SetWhereArgs(whereArgs);
68 resultSet = rawRdb->Query(absRdbPredicates, columns);
69 if (resultSet == nullptr) {
70 RINGTONE_ERR_LOG("return nullptr when query rdb");
71 return E_RDB;
72 }
73
74 return E_OK;
75 }
76
UpdateRingtoneRdb(ValuesBucket & values,string & whereClause,vector<string> & whereArgs)77 int32_t RingtoneScannerDb::UpdateRingtoneRdb(ValuesBucket &values, string &whereClause, vector<string> &whereArgs)
78 {
79 string tableName = RINGTONE_TABLE;
80 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
81 if (rawRdb == nullptr) {
82 RINGTONE_ERR_LOG("get raw rdb failed");
83 return E_RDB;
84 }
85 int32_t updateCount = 0;
86 int32_t result = rawRdb->Update(updateCount, tableName, values, whereClause, whereArgs);
87 if (result != NativeRdb::E_OK) {
88 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
89 return E_DB_FAIL;
90 }
91 return updateCount;
92 }
93
FillMetadata(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<RingtoneMetadata> & ptr)94 int32_t RingtoneScannerDb::FillMetadata(const shared_ptr<NativeRdb::ResultSet> &resultSet,
95 unique_ptr<RingtoneMetadata> &ptr)
96 {
97 std::vector<std::string> columnNames;
98 int32_t err = resultSet->GetAllColumnNames(columnNames);
99 if (err != NativeRdb::E_OK) {
100 RINGTONE_ERR_LOG("failed to get all column names");
101 return E_RDB;
102 }
103
104 for (const auto &col : columnNames) {
105 ExtractMetaFromColumn(resultSet, ptr, col);
106 }
107
108 return E_OK;
109 }
110
ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<RingtoneMetadata> & metadata,const std::string & col)111 void RingtoneScannerDb::ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> &resultSet,
112 unique_ptr<RingtoneMetadata> &metadata, const std::string &col)
113 {
114 RingtoneResultSetDataType dataType = RingtoneResultSetDataType::DATA_TYPE_NULL;
115 RingtoneMetadata::RingtoneMetadataFnPtr requestFunc = nullptr;
116 auto itr = metadata->memberFuncMap_.find(col);
117 if (itr != metadata->memberFuncMap_.end()) {
118 dataType = itr->second.first;
119 requestFunc = itr->second.second;
120 } else {
121 RINGTONE_ERR_LOG("invalid column name %{private}s", col.c_str());
122 return;
123 }
124
125 std::variant<int32_t, std::string, int64_t, double> data =
126 ResultSetUtils::GetValFromColumn<const shared_ptr<NativeRdb::ResultSet>>(col, resultSet, dataType);
127
128 // Use the function pointer from map and pass data to fn ptr
129 if (requestFunc != nullptr) {
130 (metadata.get()->*requestFunc)(data);
131 }
132 }
133
GetFileSet(RingtoneDataCommand & cmd,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet)134 int32_t RingtoneScannerDb::GetFileSet(RingtoneDataCommand &cmd, const vector<string> &columns,
135 shared_ptr<NativeRdb::ResultSet> &resultSet)
136 {
137 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
138 if (rawRdb == nullptr) {
139 RINGTONE_ERR_LOG("get raw rdb failed");
140 return E_RDB;
141 }
142 resultSet = rawRdb->Query(*cmd.GetAbsRdbPredicates(), columns);
143 if (resultSet == nullptr) {
144 RINGTONE_ERR_LOG("return nullptr when query rdb");
145 return E_RDB;
146 }
147
148 int32_t rowCount = 0;
149 int32_t ret = resultSet->GetRowCount(rowCount);
150 if (ret != NativeRdb::E_OK) {
151 RINGTONE_ERR_LOG("failed to get row count");
152 return E_RDB;
153 }
154 if (rowCount == 0) {
155 return E_OK;
156 }
157
158 ret = resultSet->GoToFirstRow();
159 if (ret != NativeRdb::E_OK) {
160 RINGTONE_ERR_LOG("failed to go to first row");
161 return E_RDB;
162 }
163 return E_OK;
164 }
165
InsertDateAdded(const RingtoneMetadata & metadata,ValuesBucket & outValues)166 static void InsertDateAdded(const RingtoneMetadata &metadata, ValuesBucket &outValues)
167 {
168 int64_t dateAdded = metadata.GetDateAdded();
169 if (dateAdded == 0) {
170 int64_t dateTaken = metadata.GetDateTaken();
171 if (dateTaken == 0) {
172 int64_t dateModified = metadata.GetDateModified();
173 if (dateModified == 0) {
174 dateAdded = RingtoneFileUtils::UTCTimeMilliSeconds();
175 RINGTONE_WARN_LOG("Invalid dateAdded time, use current time instead: %{public}" PRId64, dateAdded);
176 } else {
177 dateAdded = dateModified;
178 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateModified instead: %{public}" PRId64, dateAdded);
179 }
180 } else {
181 dateAdded = dateTaken * MSEC_TO_SEC;
182 RINGTONE_WARN_LOG("Invalid dateAdded time, use dateTaken instead: %{public}" PRId64, dateAdded);
183 }
184 }
185 outValues.PutLong(RINGTONE_COLUMN_DATE_ADDED, dateAdded);
186 }
187
SetValuesFromMetaData(const RingtoneMetadata & metadata,ValuesBucket & values,bool isInsert)188 static void SetValuesFromMetaData(const RingtoneMetadata &metadata, ValuesBucket &values, bool isInsert)
189 {
190 values.PutString(RINGTONE_COLUMN_DATA, metadata.GetData());
191 values.PutLong(RINGTONE_COLUMN_SIZE, metadata.GetSize());
192 values.PutString(RINGTONE_COLUMN_DISPLAY_NAME, metadata.GetDisplayName());
193 values.PutString(RINGTONE_COLUMN_TITLE, metadata.GetTitle());
194 values.PutInt(RINGTONE_COLUMN_MEDIA_TYPE, metadata.GetMediaType());
195 values.PutInt(RINGTONE_COLUMN_TONE_TYPE, metadata.GetToneType());
196 values.PutString(RINGTONE_COLUMN_MIME_TYPE, metadata.GetMimeType());
197 values.PutInt(RINGTONE_COLUMN_SOURCE_TYPE, metadata.GetSourceType());
198 values.PutLong(RINGTONE_COLUMN_DATE_MODIFIED, metadata.GetDateModified());
199 values.PutLong(RINGTONE_COLUMN_DATE_TAKEN, metadata.GetDateTaken());
200 values.PutInt(RINGTONE_COLUMN_DURATION, metadata.GetDuration());
201 values.PutInt(RINGTONE_COLUMN_SHOT_TONE_TYPE, metadata.GetShotToneType());
202 values.PutInt(RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE, metadata.GetShotToneSourceType());
203 values.PutInt(RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE, metadata.GetNotificationToneType());
204 values.PutInt(RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE, metadata.GetNotificationToneSourceType());
205 values.PutInt(RINGTONE_COLUMN_RING_TONE_TYPE, metadata.GetRingToneType());
206 values.PutInt(RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE, metadata.GetRingToneSourceType());
207 values.PutInt(RINGTONE_COLUMN_ALARM_TONE_TYPE, metadata.GetAlarmToneType());
208 values.PutInt(RINGTONE_COLUMN_ALARM_TONE_SOURCE_TYPE, metadata.GetAlarmToneSourceType());
209
210 if (isInsert) {
211 InsertDateAdded(metadata, values);
212 return;
213 }
214 }
215
UpdateMetadata(const RingtoneMetadata & metadata,string & tableName)216 int32_t RingtoneScannerDb::UpdateMetadata(const RingtoneMetadata &metadata, string &tableName)
217 {
218 int32_t updateCount = 0;
219 ValuesBucket values;
220 string whereClause = RINGTONE_COLUMN_TONE_ID + " = ?";
221 vector<string> whereArgs = { to_string(metadata.GetToneId()) };
222
223 SetValuesFromMetaData(metadata, values, false);
224
225 tableName = RINGTONE_TABLE;
226 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
227 if (rawRdb == nullptr) {
228 RINGTONE_ERR_LOG("get raw rdb failed");
229 return E_RDB;
230 }
231 int32_t result = rawRdb->Update(updateCount, tableName, values, whereClause, whereArgs);
232 if (result != NativeRdb::E_OK || updateCount <= 0) {
233 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
234 return E_DB_FAIL;
235 }
236 return updateCount;
237 }
238
InsertMetadata(const RingtoneMetadata & metadata,string & tableName)239 int32_t RingtoneScannerDb::InsertMetadata(const RingtoneMetadata &metadata, string &tableName)
240 {
241 ValuesBucket values;
242 SetValuesFromMetaData(metadata, values, true);
243
244 int64_t rowNum = 0;
245 tableName = RINGTONE_TABLE;
246 if (!InsertData(values, tableName, rowNum)) {
247 return E_DB_FAIL;
248 }
249 return static_cast<int32_t>(rowNum);
250 }
251
InsertData(const ValuesBucket values,const string & tableName,int64_t & rowNum)252 bool RingtoneScannerDb::InsertData(const ValuesBucket values, const string &tableName, int64_t &rowNum)
253 {
254 auto rawRdb = RingtoneRdbStore::GetInstance()->GetRaw();
255 if (rawRdb == nullptr) {
256 RINGTONE_ERR_LOG("get raw rdb failed");
257 return E_RDB;
258 }
259 int32_t result = rawRdb->Insert(rowNum, tableName, values);
260 if (rowNum <= 0) {
261 RINGTONE_ERR_LOG("Ringtone library Insert functionality is failed, rowNum %{public}ld", (long) rowNum);
262 return false;
263 }
264
265 if (result != NativeRdb::E_OK) {
266 RINGTONE_ERR_LOG("Ringtone library Insert functionality is failed, return %{public}d", result);
267 return false;
268 }
269
270 return true;
271 }
272 } // namespace Media
273 } // namespace OHOS
274