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
16 #include "ringtone_rdb_callbacks.h"
17
18 #include <sys/stat.h>
19
20 #include "rdb_sql_utils.h"
21 #include "ringtone_errno.h"
22 #include "ringtone_log.h"
23 #include "ringtone_db_const.h"
24 #include "ringtone_file_utils.h"
25 #include "ringtone_mimetype_utils.h"
26 #include "ringtone_utils.h"
27 #include "result_set_utils.h"
28 #include "preferences_helper.h"
29 #include "dfx_const.h"
30
31 namespace OHOS {
32 namespace Media {
33 using namespace std;
34
35 const string DEFAULT_MIME_TYPE = "application/octet-stream";
36 static const char RINGTONE_PARAMETER_SCANNER_COMPLETED_KEY[] = "ringtone.scanner.completed";
37 static const int RINGTONE_PARAMETER_SCANNER_COMPLETED_FALSE = 0;
38
39 const std::string CREATE_RINGTONE_TABLE = "CREATE TABLE IF NOT EXISTS " + RINGTONE_TABLE + "(" +
40 RINGTONE_COLUMN_TONE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
41 RINGTONE_COLUMN_DATA + " TEXT , " +
42 RINGTONE_COLUMN_SIZE + " BIGINT DEFAULT 0, " +
43 RINGTONE_COLUMN_DISPLAY_NAME + " TEXT , " +
44 RINGTONE_COLUMN_TITLE + " TEXT , " +
45 RINGTONE_COLUMN_MEDIA_TYPE + " INT DEFAULT 0, " +
46 RINGTONE_COLUMN_TONE_TYPE + " INT DEFAULT 0, " +
47 RINGTONE_COLUMN_MIME_TYPE + " TEXT , " +
48 RINGTONE_COLUMN_SOURCE_TYPE + " INT DEFAULT 0, " +
49 RINGTONE_COLUMN_DATE_ADDED + " BIGINT DEFAULT 0, " +
50 RINGTONE_COLUMN_DATE_MODIFIED + " BIGINT DEFAULT 0, " +
51 RINGTONE_COLUMN_DATE_TAKEN + " BIGINT DEFAULT 0, " +
52 RINGTONE_COLUMN_DURATION + " INT DEFAULT 0, " +
53 RINGTONE_COLUMN_SHOT_TONE_TYPE + " INT DEFAULT 0, " +
54 RINGTONE_COLUMN_SHOT_TONE_SOURCE_TYPE + " INT DEFAULT 0, " +
55 RINGTONE_COLUMN_NOTIFICATION_TONE_TYPE + " INT DEFAULT 0, " +
56 RINGTONE_COLUMN_NOTIFICATION_TONE_SOURCE_TYPE + " INT DEFAULT 0, " +
57 RINGTONE_COLUMN_RING_TONE_TYPE + " INT DEFAULT 0, " +
58 RINGTONE_COLUMN_RING_TONE_SOURCE_TYPE + " INT DEFAULT 0, " +
59 RINGTONE_COLUMN_ALARM_TONE_TYPE + " INT DEFAULT 0, " +
60 RINGTONE_COLUMN_ALARM_TONE_SOURCE_TYPE + " INT DEFAULT 0, " +
61 RINGTONE_COLUMN_DISPLAY_LANGUAGE_TYPE + " TEXT , " +
62 RINGTONE_COLUMN_SCANNER_FLAG + " INT DEFAULT 0 " + ")";
63
64 const std::string CREATE_SIMCARD_SETTING_TABLE = "CREATE TABLE IF NOT EXISTS " + SIMCARD_SETTING_TABLE + "(" +
65 SIMCARD_SETTING_COLUMN_MODE + " INTEGER ," +
66 SIMCARD_SETTING_COLUMN_RINGTONE_TYPE + " INTEGER ," +
67 SIMCARD_SETTING_COLUMN_TONE_FILE + " TEXT ," +
68 SIMCARD_SETTING_COLUMN_VIBRATE_FILE + " TEXT ," +
69 SIMCARD_SETTING_COLUMN_VIBRATE_MODE + " INTEGER ," +
70 SIMCARD_SETTING_COLUMN_RING_MODE + " INTEGER ," +
71 " PRIMARY KEY (" + SIMCARD_SETTING_COLUMN_MODE + ", " + SIMCARD_SETTING_COLUMN_RINGTONE_TYPE + "))";
72
73 const std::string INIT_SIMCARD_SETTING_TABLE = "INSERT OR IGNORE INTO " + SIMCARD_SETTING_TABLE + " (" +
74 SIMCARD_SETTING_COLUMN_MODE + ", " +
75 SIMCARD_SETTING_COLUMN_RINGTONE_TYPE + ") VALUES (1, 0), (1, 1), (1, 2), (1, 3), \
76 (2, 0), (2, 1), (2, 2), (2, 3), \
77 (3, 0), (3, 1), (3, 2), (3, 3);";
78
79 const std::string CREATE_VIBRATE_TABLE = "CREATE TABLE IF NOT EXISTS " + VIBRATE_TABLE + "(" +
80 VIBRATE_COLUMN_VIBRATE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
81 VIBRATE_COLUMN_DATA + " TEXT , " +
82 VIBRATE_COLUMN_SIZE + " BIGINT DEFAULT 0, " +
83 VIBRATE_COLUMN_DISPLAY_NAME + " TEXT , " +
84 VIBRATE_COLUMN_TITLE + " TEXT , " +
85 VIBRATE_COLUMN_DISPLAY_LANGUAGE + " TEXT , " +
86 VIBRATE_COLUMN_VIBRATE_TYPE + " INT DEFAULT 0, " +
87 VIBRATE_COLUMN_SOURCE_TYPE + " INT DEFAULT 0, " +
88 VIBRATE_COLUMN_DATE_ADDED + " BIGINT DEFAULT 0, " +
89 VIBRATE_COLUMN_DATE_MODIFIED + " BIGINT DEFAULT 0, " +
90 VIBRATE_COLUMN_DATE_TAKEN + " BIGINT DEFAULT 0, " +
91 VIBRATE_COLUMN_PLAY_MODE + " INT DEFAULT 0, " +
92 VIBRATE_COLUMN_SCANNER_FLAG + " INT DEFAULT 0 " + ")";
93
94 const std::string CREATE_PRELOAD_CONF_TABLE = "CREATE TABLE IF NOT EXISTS " + PRELOAD_CONFIG_TABLE + "(" +
95 PRELOAD_CONFIG_COLUMN_RING_TONE_TYPE + " INTEGER PRIMARY KEY," +
96 PRELOAD_CONFIG_COLUMN_TONE_ID + " INTEGER ," +
97 PRELOAD_CONFIG_COLUMN_DISPLAY_NAME + " TEXT " + ")";
98
99 const std::string INIT_PRELOAD_CONF_TABLE = "INSERT OR IGNORE INTO " + PRELOAD_CONFIG_TABLE + " (" +
100 PRELOAD_CONFIG_COLUMN_RING_TONE_TYPE + ") VALUES (1), (2), (3), (4), (5), (6);";
101
102 static const vector<string> g_initSqls = {
103 CREATE_RINGTONE_TABLE,
104 CREATE_VIBRATE_TABLE,
105 CREATE_SIMCARD_SETTING_TABLE,
106 INIT_SIMCARD_SETTING_TABLE,
107 CREATE_PRELOAD_CONF_TABLE,
108 INIT_PRELOAD_CONF_TABLE,
109 };
110
RingtoneDataCallBack(void)111 RingtoneDataCallBack::RingtoneDataCallBack(void)
112 {
113 }
114
~RingtoneDataCallBack(void)115 RingtoneDataCallBack::~RingtoneDataCallBack(void)
116 {
117 }
118
InitSql(NativeRdb::RdbStore & store)119 int32_t RingtoneDataCallBack::InitSql(NativeRdb::RdbStore &store)
120 {
121 for (const string &sqlStr : g_initSqls) {
122 if (store.ExecuteSql(sqlStr) != NativeRdb::E_OK) {
123 RINGTONE_ERR_LOG("Failed to execute sql");
124 return NativeRdb::E_ERROR;
125 }
126 }
127 return NativeRdb::E_OK;
128 }
129
OnCreate(NativeRdb::RdbStore & store)130 int32_t RingtoneDataCallBack::OnCreate(NativeRdb::RdbStore &store)
131 {
132 if (InitSql(store) != NativeRdb::E_OK) {
133 RINGTONE_DEBUG_LOG("Failed to init sql");
134 return NativeRdb::E_ERROR;
135 }
136
137 RingtoneFileUtils::CreateRingtoneDir();
138 return NativeRdb::E_OK;
139 }
140
ExecSqls(const vector<string> & sqls,NativeRdb::RdbStore & store)141 static void ExecSqls(const vector<string> &sqls, NativeRdb::RdbStore &store)
142 {
143 int32_t err = NativeRdb::E_OK;
144 for (const auto &sql : sqls) {
145 err = store.ExecuteSql(sql);
146 if (err != NativeRdb::E_OK) {
147 RINGTONE_ERR_LOG("Failed to exec: %{private}s", sql.c_str());
148 continue;
149 }
150 }
151 }
152
AddDisplayLanguageColumn(NativeRdb::RdbStore & store)153 static void AddDisplayLanguageColumn(NativeRdb::RdbStore &store)
154 {
155 const vector<string> sqls = {
156 "ALTER TABLE " + RINGTONE_TABLE + " ADD COLUMN " + RINGTONE_COLUMN_DISPLAY_LANGUAGE_TYPE + " TEXT",
157 };
158 RINGTONE_INFO_LOG("Add display language column");
159 ExecSqls(sqls, store);
160 }
161
AddScannerFlagColumn(NativeRdb::RdbStore & store)162 static void AddScannerFlagColumn(NativeRdb::RdbStore &store)
163 {
164 const vector<string> sqls = {
165 "ALTER TABLE " + RINGTONE_TABLE + " ADD COLUMN " + RINGTONE_COLUMN_SCANNER_FLAG + " INT DEFAULT 0",
166 "ALTER TABLE " + VIBRATE_TABLE + " ADD COLUMN " + VIBRATE_COLUMN_SCANNER_FLAG + " INT DEFAULT 0",
167 };
168 RINGTONE_INFO_LOG("Add scanner flag column");
169 ExecSqls(sqls, store);
170 }
171
AddVibrateTable(NativeRdb::RdbStore & store)172 static void AddVibrateTable(NativeRdb::RdbStore &store)
173 {
174 const vector<string> sqls = {
175 CREATE_VIBRATE_TABLE,
176 CREATE_SIMCARD_SETTING_TABLE,
177 INIT_SIMCARD_SETTING_TABLE,
178 };
179 int32_t errCode;
180 shared_ptr<NativePreferences::Preferences> prefs =
181 NativePreferences::PreferencesHelper::GetPreferences(COMMON_XML_EL1, errCode);
182 if (!prefs) {
183 RINGTONE_ERR_LOG("AddVibrateTable: update faild errCode=%{public}d", errCode);
184 } else {
185 prefs->PutInt(RINGTONE_PARAMETER_SCANNER_COMPLETED_KEY, RINGTONE_PARAMETER_SCANNER_COMPLETED_FALSE);
186 prefs->FlushSync();
187 }
188
189 RINGTONE_INFO_LOG("Add vibrate table");
190 ExecSqls(sqls, store);
191 }
192
UpdateMimeType(NativeRdb::RdbStore & store)193 static void UpdateMimeType(NativeRdb::RdbStore &store)
194 {
195 RINGTONE_INFO_LOG("Update MimeType Begin");
196 RingtoneMimeTypeUtils::InitMimeTypeMap();
197 const string sql = "SELECT * FROM " + RINGTONE_TABLE;
198 auto resultSet = store.QuerySql(sql);
199 if (resultSet == nullptr) {
200 RINGTONE_ERR_LOG("error query sql %{public}s", sql.c_str());
201 return;
202 }
203 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
204 std::string mimeType = GetStringVal(RINGTONE_COLUMN_MIME_TYPE, resultSet);
205 if (mimeType != DEFAULT_MIME_TYPE) {
206 continue;
207 }
208 string displayName = GetStringVal(RINGTONE_COLUMN_DISPLAY_NAME, resultSet);
209 int32_t toneid = GetInt32Val(RINGTONE_COLUMN_TONE_ID, resultSet);
210 std::string extension = RingtoneFileUtils::GetFileExtension(displayName);
211 mimeType = RingtoneMimeTypeUtils::GetMimeTypeFromExtension(extension);
212 int32_t mime = RingtoneMimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
213 RINGTONE_INFO_LOG("extension: %{public}s, mimeType: %{public}s, toneid: %{public}d mime: %{public}d",
214 extension.c_str(), mimeType.c_str(), toneid, mime);
215
216 NativeRdb::ValuesBucket values;
217 values.PutString(RINGTONE_COLUMN_MIME_TYPE, mimeType);
218 values.PutInt(RINGTONE_COLUMN_MEDIA_TYPE, mime);
219 NativeRdb::AbsRdbPredicates absRdbPredicates(RINGTONE_TABLE);
220 absRdbPredicates.EqualTo(RINGTONE_COLUMN_TONE_ID, toneid);
221 int32_t changedRows;
222 int32_t result = store.Update(changedRows, values, absRdbPredicates);
223 if (result != E_OK || changedRows <= 0) {
224 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, changedRows);
225 }
226 }
227 resultSet->Close();
228 }
229
UpdateMediaType(NativeRdb::RdbStore & store)230 static void UpdateMediaType(NativeRdb::RdbStore &store)
231 {
232 RINGTONE_INFO_LOG("Update MediaType Begin");
233 RingtoneMimeTypeUtils::InitMimeTypeMap();
234 const string sql = "SELECT * FROM " + RINGTONE_TABLE + " WHERE " + RINGTONE_COLUMN_MEDIA_TYPE + " = 0";
235 auto resultSet = store.QuerySql(sql);
236 if (resultSet == nullptr) {
237 RINGTONE_ERR_LOG("error query sql %{public}s", sql.c_str());
238 return;
239 }
240 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
241 string displayName = GetStringVal(RINGTONE_COLUMN_DISPLAY_NAME, resultSet);
242 int32_t toneid = GetInt32Val(RINGTONE_COLUMN_TONE_ID, resultSet);
243 string extension = RingtoneFileUtils::GetFileExtension(displayName);
244 string mimeType = RingtoneMimeTypeUtils::GetMimeTypeFromExtension(extension);
245 int32_t mediaType = RingtoneMimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
246
247 NativeRdb::ValuesBucket values;
248 values.PutInt(RINGTONE_COLUMN_MEDIA_TYPE, mediaType);
249 NativeRdb::AbsRdbPredicates absRdbPredicates(RINGTONE_TABLE);
250 absRdbPredicates.EqualTo(RINGTONE_COLUMN_TONE_ID, toneid);
251 int32_t changedRows;
252 int32_t result = store.Update(changedRows, values, absRdbPredicates);
253 if (result != E_OK || changedRows <= 0) {
254 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, changedRows);
255 }
256 }
257 resultSet->Close();
258 RINGTONE_INFO_LOG("Update MediaType End");
259 }
260
AddPreloadConfTable(NativeRdb::RdbStore & store)261 static void AddPreloadConfTable(NativeRdb::RdbStore &store)
262 {
263 const vector<string> sqls = {
264 CREATE_PRELOAD_CONF_TABLE,
265 INIT_PRELOAD_CONF_TABLE
266 };
267 RINGTONE_INFO_LOG("Add preload config table");
268 ExecSqls(sqls, store);
269 }
270
UpdateDefaultSystemTone(NativeRdb::RdbStore & store)271 static void UpdateDefaultSystemTone(NativeRdb::RdbStore &store)
272 {
273 RINGTONE_INFO_LOG("setting system tone begin");
274 auto infos = RingtoneUtils::GetDefaultSystemtoneInfo();
275 for (auto info : infos) {
276 const string querySql = "SELECT tone_id FROM ToneFiles WHERE display_name = "s + "\"" + info.second + "\"";
277 auto resultSet = store.QuerySql(querySql);
278 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
279 RINGTONE_ERR_LOG("Update operation failed. no resultSet");
280 continue;
281 }
282
283 int32_t tone_id = GetInt32Val("tone_id", resultSet);
284 NativeRdb::ValuesBucket values;
285 values.PutString(PRELOAD_CONFIG_COLUMN_DISPLAY_NAME, info.second);
286 values.PutInt(PRELOAD_CONFIG_COLUMN_TONE_ID, tone_id);
287 NativeRdb::AbsRdbPredicates absRdbPredicates(PRELOAD_CONFIG_TABLE);
288 absRdbPredicates.EqualTo(PRELOAD_CONFIG_COLUMN_RING_TONE_TYPE, std::to_string(info.first));
289 int32_t changedRows = 0;
290 int32_t result = store.Update(changedRows, values, absRdbPredicates);
291 if (result != E_OK || changedRows <= 0) {
292 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, changedRows);
293 }
294 }
295 }
296
CheckAndGetDataUri(const string & displayName,const string & dataUri,int32_t toneType,string & newDataUri)297 static bool CheckAndGetDataUri(const string &displayName, const string &dataUri,
298 int32_t toneType, string &newDataUri)
299 {
300 if (displayName.empty() || dataUri.empty()) {
301 return true;
302 }
303 string ringDirName;
304 if (toneType == TONE_TYPE_ALARM) {
305 ringDirName = "alarms";
306 } else if (toneType == TONE_TYPE_RINGTONE) {
307 ringDirName = "ringtones";
308 } else if (toneType == TONE_TYPE_NOTIFICATION) {
309 ringDirName = "notifications";
310 } else if (toneType == TONE_TYPE_CONTACTS) {
311 ringDirName = "contacts";
312 } else {
313 RINGTONE_ERR_LOG("error tone type, displayName:%{public}s", displayName.c_str());
314 return true;
315 }
316 auto lastPos = dataUri.find_last_of(RINGTONE_SLASH_CHAR);
317 if (lastPos == std::string::npos) {
318 return true;
319 }
320 string fileName = dataUri.substr(lastPos + 1);
321 string filePath = dataUri.substr(0, lastPos);
322 lastPos = filePath.find_last_of(RINGTONE_SLASH_CHAR);
323 if (lastPos == std::string::npos) {
324 return true;
325 }
326 string dirName = filePath.substr(lastPos + 1);
327 if (dirName == ringDirName && fileName == displayName) {
328 return true;
329 }
330 if (dataUri.find(RINGTONE_CUSTOMIZED_BASE_PATH) != std::string::npos) {
331 newDataUri = RINGTONE_CUSTOMIZED_BASE_PATH + "/Ringtone/" + ringDirName + "/" + displayName;
332 if (RingtoneFileUtils::IsFileExists(newDataUri)) {
333 return false;
334 }
335 }
336 return true;
337 }
338
UpdateDataUri(NativeRdb::RdbStore & store)339 static void UpdateDataUri(NativeRdb::RdbStore &store)
340 {
341 RINGTONE_INFO_LOG("Update Data Uri Begin");
342 const string querySql = "SELECT " + RINGTONE_COLUMN_DISPLAY_NAME + " , " + RINGTONE_COLUMN_DATA +
343 " , " + RINGTONE_COLUMN_TONE_ID + " , " + RINGTONE_COLUMN_TONE_TYPE + " FROM " + RINGTONE_TABLE +
344 " WHERE " + RINGTONE_COLUMN_SOURCE_TYPE + " = 2";
345 auto resultSet = store.QuerySql(querySql);
346 CHECK_AND_RETURN_LOG(resultSet != nullptr, "error query sql %{public}s", querySql.c_str());
347 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
348 string displayName = GetStringVal(RINGTONE_COLUMN_DISPLAY_NAME, resultSet);
349 string dataUri = GetStringVal(RINGTONE_COLUMN_DATA, resultSet);
350 int32_t toneid = GetInt32Val(RINGTONE_COLUMN_TONE_ID, resultSet);
351 int32_t toneType = GetInt32Val(RINGTONE_COLUMN_TONE_TYPE, resultSet);
352 string newDataUri = "";
353 if (CheckAndGetDataUri(displayName, dataUri, toneType, newDataUri)) {
354 RINGTONE_INFO_LOG("check data path ok. toneid %{public}d", toneid);
355 continue;
356 }
357 if (newDataUri.empty()) {
358 RINGTONE_ERR_LOG("new data path err. toneid %{public}d", toneid);
359 continue;
360 }
361 RINGTONE_INFO_LOG("need update uri toneid:%{public}d, displayName:%{public}s", toneid, displayName.c_str());
362 NativeRdb::ValuesBucket values;
363 values.PutString(RINGTONE_COLUMN_DATA, newDataUri);
364 NativeRdb::AbsRdbPredicates absRdbPredicates(RINGTONE_TABLE);
365 absRdbPredicates.EqualTo(RINGTONE_COLUMN_TONE_ID, toneid);
366 int32_t changedRows;
367 int32_t result = store.Update(changedRows, values, absRdbPredicates);
368 if (result != E_OK || changedRows <= 0) {
369 RINGTONE_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, changedRows);
370 }
371 }
372 resultSet->Close();
373 RINGTONE_INFO_LOG("Update Data Uri End");
374 }
375
UpgradeExtension(NativeRdb::RdbStore & store,int32_t oldVersion)376 static void UpgradeExtension(NativeRdb::RdbStore &store, int32_t oldVersion)
377 {
378 if (oldVersion < VERSION_ADD_DISPLAY_LANGUAGE_COLUMN) {
379 AddDisplayLanguageColumn(store);
380 }
381 if (oldVersion < VERSION_ADD_VIBRATE_TABLE) {
382 AddVibrateTable(store);
383 }
384 if (oldVersion < VERSION_UPDATE_MIME_TYPE) {
385 UpdateMimeType(store);
386 }
387 if (oldVersion < VERSION_ADD_PRELOAD_CONF_TABLE) {
388 AddPreloadConfTable(store);
389 UpdateDefaultSystemTone(store);
390 }
391 if (oldVersion < VERSION_UPDATE_WATCH_MIME_TYPE) {
392 UpdateMimeType(store);
393 }
394 if (oldVersion < VERSION_ADD_SCANNER_FLAG) {
395 AddScannerFlagColumn(store);
396 }
397 if (oldVersion < VERSION_UPDATE_MEDIA_TYPE_VIDEO) {
398 UpdateMediaType(store);
399 }
400 if (oldVersion < VERSION_UPDATE_DATA_URI) {
401 UpdateDataUri(store);
402 }
403 }
404
OnUpgrade(NativeRdb::RdbStore & store,int32_t oldVersion,int32_t newVersion)405 int32_t RingtoneDataCallBack::OnUpgrade(NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)
406 {
407 RINGTONE_INFO_LOG("OnUpgrade old:%d, new:%d", oldVersion, newVersion);
408 UpgradeExtension(store, oldVersion);
409 return NativeRdb::E_OK;
410 }
411 } // namespace Media
412 } // namespace OHOS
413