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 #define MLOG_TAG "Scanner"
17
18 #include "ringtone_scanner.h"
19
20 #include "directory_ex.h"
21 #include "ringtone_default_setting.h"
22 #include "ringtone_file_utils.h"
23 #include "ringtone_log.h"
24 #include "ringtone_mimetype_utils.h"
25 #include "ringtone_rdbstore.h"
26 #include "ringtone_scanner_utils.h"
27
28 namespace OHOS {
29 namespace Media {
30 using namespace std;
31 using namespace OHOS::AppExecFwk;
32 using namespace OHOS::DataShare;
33 static const int32_t SCANNER_WAIT_FOR_TIMEOUT = 10000; // ms
34 static const std::string PATH_PLAY_MODE_SYNC = "/synchronized";
35 static const std::string PATH_PLAY_MODE_CLASSIC = "/non-synchronized";
36 static const std::string PATH_VIBRATE_TYPE_STANDARD = "/standard";
37 static const std::string PATH_VIBRATE_TYPE_GENTLE = "/gentle";
38 static const std::string ALARMS_TYPE = "alarms";
39 static const std::string RINGTONES_TYPE = "ringtones";
40 static const std::string NOTIFICATIONS_TYPE = "notifications";
41 #ifndef OHOS_LOCAL_DEBUG_DISABLE
42 // liuxk just for debug
43 static const std::string LOCAL_DIR = "/data/storage/el2/base/preload_data";
44 #endif
45 static std::unordered_map<std::string, std::pair<int32_t, int32_t>> g_typeMap = {
46 #ifndef OHOS_LOCAL_DEBUG_DISABLE
47 // liuxk just for debug
48 {LOCAL_DIR + "/alarms", {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_ALARM}},
49 {LOCAL_DIR + "/ringtones", {SOURCE_TYPE_PRESET, TONE_TYPE_RINGTONE}},
50 {LOCAL_DIR + "/notifications", {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_NOTIFICATION}},
51 {LOCAL_DIR + "/contacts", {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_CONTACTS}},
52 #endif
53 // customized tones map
54 {RINGTONE_CUSTOMIZED_ALARM_PATH, {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_ALARM}},
55 {RINGTONE_CUSTOMIZED_RINGTONE_PATH, {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_RINGTONE}},
56 {RINGTONE_CUSTOMIZED_NOTIFICATIONS_PATH, {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_NOTIFICATION}},
57 {RINGTONE_CUSTOMIZED_CONTACTS_PATH, {SOURCE_TYPE_CUSTOMISED, TONE_TYPE_CONTACTS}},
58 // customized tones map
59 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/alarms", {SOURCE_TYPE_PRESET, TONE_TYPE_ALARM}},
60 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/ringtones", {SOURCE_TYPE_PRESET, TONE_TYPE_RINGTONE}},
61 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/notifications", {SOURCE_TYPE_PRESET, TONE_TYPE_NOTIFICATION}},
62 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/alarms", {SOURCE_TYPE_PRESET, TONE_TYPE_ALARM}},
63 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/ringtones", {SOURCE_TYPE_PRESET, TONE_TYPE_RINGTONE}},
64 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/notifications", {SOURCE_TYPE_PRESET, TONE_TYPE_NOTIFICATION}},
65 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/alarms", {SOURCE_TYPE_PRESET, TONE_TYPE_ALARM}},
66 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/ringtones", {SOURCE_TYPE_PRESET, TONE_TYPE_RINGTONE}},
67 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/notifications", {SOURCE_TYPE_PRESET, TONE_TYPE_NOTIFICATION}},
68 };
69 // vibrate type map
70 static std::unordered_map<std::string, std::pair<int32_t, int32_t>> g_vibrateTypeMap = {
71 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_STANDARD, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_STANDARD}},
72 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_GENTLE, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_GENTLE}},
73 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_STANDARD, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_STANDARD}},
74 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_GENTLE, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_GENTLE}},
75 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_STANDARD, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_STANDARD}},
76 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_GENTLE, {SOURCE_TYPE_PRESET, VIBRATE_TYPE_GENTLE}},
77 };
78
79 static std::unordered_map<std::string, std::pair<int32_t, int32_t>> g_vibratePlayModeMap = {
80 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_SYNC,
81 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
82 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_CLASSIC,
83 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
84 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_SYNC,
85 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
86 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_CLASSIC,
87 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
88 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_SYNC,
89 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
90 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_CLASSIC,
91 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
92 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_SYNC,
93 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
94 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_CLASSIC,
95 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
96 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_SYNC,
97 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
98 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_STANDARD + PATH_PLAY_MODE_CLASSIC,
99 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
100 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_SYNC,
101 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_SYNC}},
102 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + PATH_VIBRATE_TYPE_GENTLE + PATH_PLAY_MODE_CLASSIC,
103 {SOURCE_TYPE_PRESET, VIBRATE_PLAYMODE_CLASSIC}},
104 };
105
106 static const std::vector<std::string> g_preloadDirs = {
107 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/alarms"},
108 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/ringtones"},
109 {ROOT_TONE_PRELOAD_PATH_NOAH_PATH + "/notifications"},
110 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/alarms"},
111 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/ringtones"},
112 {ROOT_TONE_PRELOAD_PATH_CHINA_PATH + "/notifications"},
113 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/alarms"},
114 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/ringtones"},
115 {ROOT_TONE_PRELOAD_PATH_OVERSEA_PATH + "/notifications"},
116 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + "/standard"},
117 {ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH + "/gentle"},
118 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + "/standard"},
119 {ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH + "/gentle"},
120 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + "/standard"},
121 {ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH + "/gentle"},
122 };
123
RingtoneScannerObj(const std::string & path,const std::shared_ptr<IRingtoneScannerCallback> & callback,RingtoneScannerObj::ScanType type)124 RingtoneScannerObj::RingtoneScannerObj(const std::string &path,
125 const std::shared_ptr<IRingtoneScannerCallback> &callback,
126 RingtoneScannerObj::ScanType type) : type_(type), callback_(callback)
127 {
128 if (type_ == DIRECTORY) {
129 dir_ = path;
130 } else if (type_ == FILE) {
131 path_ = path;
132 }
133 // when path is /Photo, it means update or clone scene
134 stopFlag_ = make_shared<bool>(false);
135 }
136
RingtoneScannerObj(RingtoneScannerObj::ScanType type)137 RingtoneScannerObj::RingtoneScannerObj(RingtoneScannerObj::ScanType type) : type_(type)
138 {
139 stopFlag_ = make_shared<bool>(false);
140 }
141
SetStopFlag(std::shared_ptr<bool> & flag)142 void RingtoneScannerObj::SetStopFlag(std::shared_ptr<bool> &flag)
143 {
144 stopFlag_ = flag;
145 }
146
ScanFile()147 int32_t RingtoneScannerObj::ScanFile()
148 {
149 RINGTONE_DEBUG_LOG("scan file %{private}s", path_.c_str());
150
151 int32_t ret = ScanFileInternal();
152 if (ret != E_OK) {
153 RINGTONE_ERR_LOG("ScanFileInternal err %{public}d", ret);
154 }
155
156 (void)InvokeCallback(ret);
157
158 return ret;
159 }
160
InvokeCallback(int32_t err)161 int32_t RingtoneScannerObj::InvokeCallback(int32_t err)
162 {
163 if (callback_ == nullptr) {
164 return E_OK;
165 }
166
167 return callback_->OnScanFinished(err, uri_, path_);
168 }
169
Scan()170 void RingtoneScannerObj::Scan()
171 {
172 switch (type_) {
173 case FILE:
174 ScanFile();
175 break;
176 case DIRECTORY:
177 ScanDir();
178 break;
179 case START:
180 BootScan();
181 break;
182 default:
183 break;
184 }
185 }
186
BootScan()187 int32_t RingtoneScannerObj::BootScan()
188 {
189 int64_t scanStart = RingtoneFileUtils::UTCTimeMilliSeconds();
190 for (auto &dir : g_preloadDirs) {
191 RINGTONE_INFO_LOG("start to scan realpath %{private}s", dir.c_str());
192 string realPath;
193 if (!PathToRealPath(dir, realPath)) {
194 RINGTONE_ERR_LOG("failed to get realpath %{private}s, errno %{public}d", dir.c_str(), errno);
195 continue;
196 }
197
198 RINGTONE_INFO_LOG("start to scan realpath %{private}s", dir.c_str());
199 callback_ = make_shared<ScanErrCallback>(dir);
200
201 if (RingtoneScannerUtils::IsDirectory(realPath)) {
202 dir_ = move(realPath);
203 (void)ScanDir();
204 } else if (RingtoneScannerUtils::IsRegularFile(realPath)) {
205 path_ = move(realPath);
206 (void)ScanFile();
207 }
208 }
209
210 // reset ringtone default settings
211 auto rdbStore = RingtoneRdbStore::GetInstance();
212 if (rdbStore != nullptr) {
213 auto rawRdb = rdbStore->GetRaw();
214 if (rawRdb != nullptr) {
215 RingtoneDefaultSetting::GetObj(rawRdb)->Update();
216 }
217 }
218
219 int64_t scanEnd = RingtoneFileUtils::UTCTimeMilliSeconds();
220 RINGTONE_INFO_LOG("total preload tone files count:%{public}d, scanned: %{public}d, costed-time:%{public}"
221 PRId64 " ms", tonesScannedCount_, tonesScannedCount_, scanEnd - scanStart);
222 unique_lock<mutex> lock(scannerLock_);
223 scannerCv_.notify_one();
224 bool res = true;
225 res = RingtoneScannerDb::DeleteNotExist();
226 if (!res) {
227 RINGTONE_ERR_LOG("DeleteNotExist operation failed, res: %{public}d", res);
228 }
229 res = RingtoneScannerDb::UpdateScannerFlag();
230 if (!res) {
231 RINGTONE_ERR_LOG("UpdateScannerFlag operation failed, res: %{public}d", res);
232 }
233 return E_OK;
234 }
235
WaitFor()236 void RingtoneScannerObj::WaitFor()
237 {
238 unique_lock<mutex> lock(scannerLock_);
239 scannerCv_.wait_for(lock, chrono::milliseconds(SCANNER_WAIT_FOR_TIMEOUT));
240 }
241
ScanDir()242 int32_t RingtoneScannerObj::ScanDir()
243 {
244 RINGTONE_INFO_LOG("scan dir %{private}s", dir_.c_str());
245
246 int32_t ret = ScanDirInternal();
247 if (ret != E_OK) {
248 RINGTONE_ERR_LOG("ScanDirInternal err %{public}d", ret);
249 }
250
251 (void)InvokeCallback(ret);
252
253 return ret;
254 }
255
ScanDirInternal()256 int32_t RingtoneScannerObj::ScanDirInternal()
257 {
258 if (RingtoneScannerUtils::IsDirHiddenRecursive(dir_)) {
259 RINGTONE_ERR_LOG("the dir %{private}s is hidden", dir_.c_str());
260 return E_DIR_HIDDEN;
261 }
262
263 /* no further operation when stopped */
264 auto err = WalkFileTree(dir_);
265 if (err != E_OK) {
266 RINGTONE_ERR_LOG("walk file tree err %{public}d", err);
267 return err;
268 }
269 err = CommitTransaction();
270 if (err != E_OK) {
271 RINGTONE_ERR_LOG("commit transaction err %{public}d", err);
272 return err;
273 }
274
275 err = CommitVibrateTransaction();
276 if (err != E_OK) {
277 RINGTONE_ERR_LOG("commit vibrate transaction err %{public}d", err);
278 return err;
279 }
280 err = CleanupDirectory();
281 if (err != E_OK) {
282 RINGTONE_ERR_LOG("clean up dir err %{public}d", err);
283 return err;
284 }
285
286 return E_OK;
287 }
288
CleanupDirectory()289 int32_t RingtoneScannerObj::CleanupDirectory()
290 {
291 return E_OK;
292 }
293
CommitTransaction()294 int32_t RingtoneScannerObj::CommitTransaction()
295 {
296 unique_ptr<RingtoneMetadata> data;
297 string tableName = RINGTONE_TABLE;
298
299 // will begin a transaction in later pr
300 for (uint32_t i = 0; i < dataBuffer_.size(); i++) {
301 data = move(dataBuffer_[i]);
302 if (data->GetToneId() != FILE_ID_DEFAULT) {
303 RingtoneScannerDb::UpdateMetadata(*data, tableName);
304 } else {
305 RingtoneScannerDb::InsertMetadata(*data, tableName);
306 }
307 }
308
309 if (dataBuffer_.size() > 0) {
310 tonesScannedCount_ += dataBuffer_.size();
311 }
312 dataBuffer_.clear();
313
314 return E_OK;
315 }
316
CommitVibrateTransaction()317 int32_t RingtoneScannerObj::CommitVibrateTransaction()
318 {
319 unique_ptr<VibrateMetadata> vibrateData;
320 string vibrateTableName = VIBRATE_TABLE;
321
322 for (uint32_t i = 0; i < vibrateDataBuffer_.size(); i++) {
323 vibrateData = move(vibrateDataBuffer_[i]);
324 if (vibrateData->GetVibrateId() != FILE_ID_DEFAULT) {
325 RingtoneScannerDb::UpdateVibrateMetadata(*vibrateData, vibrateTableName);
326 } else {
327 RingtoneScannerDb::InsertVibrateMetadata(*vibrateData, vibrateTableName);
328 }
329 }
330
331 if (vibrateDataBuffer_.size() > 0) {
332 tonesScannedCount_ += vibrateDataBuffer_.size();
333 }
334 vibrateDataBuffer_.clear();
335
336 return E_OK;
337 }
338
WalkFileTree(const string & path)339 int32_t RingtoneScannerObj::WalkFileTree(const string &path)
340 {
341 int err = E_OK;
342 DIR *dirPath = nullptr;
343 struct dirent *ent = nullptr;
344 size_t len = path.length();
345 struct stat statInfo;
346 if (len >= FILENAME_MAX - 1) {
347 return ERR_INCORRECT_PATH;
348 }
349 auto fName = (char *)calloc(FILENAME_MAX, sizeof(char));
350 if (fName == nullptr) {
351 return E_NO_MEMORY;
352 }
353 if (strcpy_s(fName, FILENAME_MAX, path.c_str()) != ERR_SUCCESS) {
354 free(fName);
355 return E_ERR;
356 }
357 fName[len++] = '/';
358 if ((dirPath = opendir(path.c_str())) == nullptr) {
359 free(fName);
360 return E_PERMISSION_DENIED;
361 }
362 while ((ent = readdir(dirPath)) != nullptr) {
363 if (*stopFlag_) {
364 err = E_STOP;
365 break;
366 }
367 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
368 continue;
369 }
370 if (strncpy_s(fName + len, FILENAME_MAX - len, ent->d_name, FILENAME_MAX - len)) {
371 continue;
372 }
373 if (lstat(fName, &statInfo) == -1) {
374 continue;
375 }
376 string currentPath = fName;
377 if (S_ISDIR(statInfo.st_mode)) {
378 if (RingtoneScannerUtils::IsDirHidden(currentPath)) {
379 continue;
380 }
381 (void)WalkFileTree(currentPath);
382 } else {
383 (void)ScanFileInTraversal(currentPath);
384 }
385 }
386 closedir(dirPath);
387 free(fName);
388 return err;
389 }
390
ScanFileInTraversal(const string & path)391 int32_t RingtoneScannerObj::ScanFileInTraversal(const string &path)
392 {
393 path_ = path;
394 if (RingtoneScannerUtils::IsFileHidden(path_)) {
395 RINGTONE_ERR_LOG("the file is hidden");
396 return E_FILE_HIDDEN;
397 }
398
399 bool flag = (path_.find(ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH) != std::string::npos) ? true : false;
400 flag |= (path_.find(ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH) != std::string::npos);
401 flag |= (path_.find(ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH) != std::string::npos);
402 std::string extension = RingtoneScannerUtils::GetFileExtension(path_);
403
404 if (flag) {
405 if (extension.compare("json") == 0) {
406 isVibrateFile_ = true;
407 return ScanVibrateFile();
408 }
409 return E_OK;
410 }
411
412 int32_t err = GetFileMetadata();
413 if (err != E_OK) {
414 if (err != E_SCANNED) {
415 RINGTONE_ERR_LOG("failed to get file metadata");
416 }
417 return err;
418 }
419
420 err = BuildFileInfo();
421 if (err != E_OK) {
422 RINGTONE_ERR_LOG("failed to get other file metadata");
423 return err;
424 }
425
426 return E_OK;
427 }
428
GetFileMetadata()429 int32_t RingtoneScannerObj::GetFileMetadata()
430 {
431 if (path_.empty()) {
432 return E_INVALID_ARGUMENTS;
433 }
434 struct stat statInfo = { 0 };
435 if (stat(path_.c_str(), &statInfo) != 0) {
436 RINGTONE_ERR_LOG("stat syscall err %{public}d", errno);
437 return E_SYSCALL;
438 }
439
440 int errCode = 0;
441 if (isVibrateFile_) {
442 errCode = BuildVibrateData(statInfo);
443 if (errCode != E_OK) {
444 return errCode;
445 }
446 } else {
447 errCode = BuildData(statInfo);
448 if (errCode != E_OK) {
449 return errCode;
450 }
451 }
452
453 return E_OK;
454 }
455
BuildFileInfo()456 int32_t RingtoneScannerObj::BuildFileInfo()
457 {
458 auto err = GetMediaInfo();
459 if (err != E_OK) {
460 RINGTONE_ERR_LOG("failed to get media info");
461 }
462
463 err = AddToTransaction();
464 if (err != E_OK) {
465 RINGTONE_ERR_LOG("failed to add to transaction err %{public}d", err);
466 return err;
467 }
468
469 return E_OK;
470 }
471
AddToTransaction()472 int32_t RingtoneScannerObj::AddToTransaction()
473 {
474 if (isVibrateFile_) {
475 vibrateDataBuffer_.emplace_back(move(vibrateData_));
476 if (vibrateDataBuffer_.size() >= MAX_BATCH_SIZE) {
477 return CommitVibrateTransaction();
478 }
479 } else {
480 dataBuffer_.emplace_back(move(data_));
481 if (dataBuffer_.size() >= MAX_BATCH_SIZE) {
482 return CommitTransaction();
483 }
484 }
485
486 return E_OK;
487 }
488
GetMediaInfo()489 int32_t RingtoneScannerObj::GetMediaInfo()
490 {
491 #ifdef ENABLE_METADATA_EXTRACTOR
492 auto pos = data_->GetMimeType().find_first_of("/");
493 std::string mimePrefix = data_->GetMimeType().substr(0, pos) + "/*";
494 if (find(EXTRACTOR_SUPPORTED_MIME.begin(), EXTRACTOR_SUPPORTED_MIME.end(), mimePrefix) !=
495 EXTRACTOR_SUPPORTED_MIME.end()) {
496 return RingtoneMetadataExtractor::Extract(data_);
497 }
498 #endif // ENABLE_METADATA_EXTRACTOR
499 return E_OK;
500 }
501
BuildData(const struct stat & statInfo)502 int32_t RingtoneScannerObj::BuildData(const struct stat &statInfo)
503 {
504 data_ = make_unique<RingtoneMetadata>();
505 if (data_ == nullptr) {
506 RINGTONE_ERR_LOG("failed to make unique ptr for metadata");
507 return E_DATA;
508 }
509
510 if (S_ISDIR(statInfo.st_mode)) {
511 return E_INVALID_ARGUMENTS;
512 }
513
514 int32_t err = RingtoneScannerDb::GetFileBasicInfo(path_, data_);
515 if (err != E_OK) {
516 RINGTONE_ERR_LOG("failed to get file basic info");
517 return err;
518 }
519
520 for (const auto& pair : g_typeMap) {
521 if (path_.find(pair.first) == 0) {
522 data_->SetSourceType(pair.second.first);
523 data_->SetToneType(pair.second.second);
524 }
525 }
526
527 // file path
528 data_->SetData(path_);
529 auto dispName = RingtoneScannerUtils::GetFileNameFromUri(path_);
530 data_->SetDisplayName(dispName);
531 if (data_->GetTitle() == TITLE_DEFAULT) {
532 data_->SetTitle(RingtoneScannerUtils::GetFileTitle(data_->GetDisplayName()));
533 }
534
535 // statinfo
536 data_->SetSize(statInfo.st_size);
537 data_->SetDateModified(static_cast<int64_t>(RingtoneFileUtils::Timespec2Millisecond(statInfo.st_mtim)));
538
539 // extension and type
540 std::string extension = RingtoneScannerUtils::GetFileExtension(path_);
541 std::string mimeType = RingtoneMimeTypeUtils::GetMimeTypeFromExtension(extension);
542 data_->SetMimeType(mimeType);
543 int32_t mime = RingtoneMimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
544 data_->SetMediaType(mime);
545
546 return E_OK;
547 }
548
BuildVibrateData(const struct stat & statInfo)549 int32_t RingtoneScannerObj::BuildVibrateData(const struct stat &statInfo)
550 {
551 vibrateData_ = make_unique<VibrateMetadata>();
552 if (vibrateData_ == nullptr) {
553 RINGTONE_ERR_LOG("failed to make unique ptr for metadata");
554 return E_DATA;
555 }
556
557 if (S_ISDIR(statInfo.st_mode)) {
558 return E_INVALID_ARGUMENTS;
559 }
560
561 int32_t err = RingtoneScannerDb::GetVibrateFileBasicInfo(path_, vibrateData_);
562 if (err != E_OK) {
563 RINGTONE_ERR_LOG("failed to get file basic info");
564 return err;
565 }
566
567 for (const auto &pair : g_vibrateTypeMap) {
568 if (path_.find(pair.first) == 0) {
569 vibrateData_->SetSourceType(pair.second.first);
570 vibrateData_->SetVibrateType(pair.second.second);
571 int32_t ntype = 0;
572 if (pair.second.second == VIBRATE_TYPE_STANDARD) {
573 ntype = (path_.find(ALARMS_TYPE) != string::npos) ? VIBRATE_TYPE_SALARM : VIBRATE_TYPE_STANDARD;
574 ntype = (path_.find(RINGTONES_TYPE) != string::npos) ? VIBRATE_TYPE_SRINGTONE : ntype;
575 ntype = (path_.find(NOTIFICATIONS_TYPE) != string::npos) ? \
576 VIBRATE_TYPE_SNOTIFICATION : ntype;
577 vibrateData_->SetVibrateType(ntype);
578 } else {
579 ntype = (path_.find(ALARMS_TYPE) != string::npos) ? VIBRATE_TYPE_GALARM : VIBRATE_TYPE_GENTLE;
580 ntype = (path_.find(RINGTONES_TYPE) != string::npos) ? VIBRATE_TYPE_GRINGTONE : ntype;
581 ntype = (path_.find(NOTIFICATIONS_TYPE) != string::npos) ? \
582 VIBRATE_TYPE_GNOTIFICATION : ntype;
583 vibrateData_->SetVibrateType(ntype);
584 }
585 }
586 }
587
588 for (const auto &pair : g_vibratePlayModeMap) {
589 if (path_.find(pair.first) == 0) {
590 vibrateData_->SetPlayMode(pair.second.second);
591 }
592 }
593
594 // file path
595 vibrateData_->SetData(path_);
596 auto dispName = RingtoneScannerUtils::GetFileNameFromUri(path_);
597 vibrateData_->SetDisplayName(dispName);
598 if (vibrateData_->GetTitle() == TITLE_DEFAULT) {
599 vibrateData_->SetTitle(RingtoneScannerUtils::GetFileTitle(vibrateData_->GetDisplayName()));
600 }
601
602 // statinfo
603 vibrateData_->SetSize(statInfo.st_size);
604 vibrateData_->SetDateModified(static_cast<int64_t>(RingtoneFileUtils::Timespec2Millisecond(statInfo.st_mtim)));
605
606 return E_OK;
607 }
608
ScanFileInternal()609 int32_t RingtoneScannerObj::ScanFileInternal()
610 {
611 if (RingtoneScannerUtils::IsFileHidden(path_)) {
612 RINGTONE_ERR_LOG("the file is hidden");
613 return E_FILE_HIDDEN;
614 }
615
616 bool flag = (path_.find(ROOT_VIBRATE_PRELOAD_PATH_NOAH_PATH) != std::string::npos) ? true : false;
617 flag |= (path_.find(ROOT_VIBRATE_PRELOAD_PATH_CHINA_PATH) != std::string::npos);
618 flag |= (path_.find(ROOT_VIBRATE_PRELOAD_PATH_OVERSEA_PATH) != std::string::npos);
619 std::string extension = RingtoneScannerUtils::GetFileExtension(path_);
620
621 if (flag) {
622 if (extension.compare("json") == 0) {
623 isVibrateFile_ = true;
624 return ScanVibrateFile();
625 }
626 return E_INVALID_PATH;
627 }
628
629 int32_t err = GetFileMetadata();
630 if (err != E_OK) {
631 if (err != E_SCANNED) {
632 RINGTONE_ERR_LOG("failed to get file metadata");
633 }
634 return err;
635 }
636 err = GetMediaInfo();
637 if (err != E_OK) {
638 RINGTONE_ERR_LOG("failed to get ringtone info");
639 }
640
641 err = Commit();
642 if (err != E_OK) {
643 RINGTONE_ERR_LOG("failed to commit err %{public}d", err);
644 return err;
645 }
646
647 return E_OK;
648 }
649
ScanVibrateFile()650 int32_t RingtoneScannerObj::ScanVibrateFile()
651 {
652 int32_t err = GetFileMetadata();
653 if (err != E_OK) {
654 if (err != E_SCANNED) {
655 RINGTONE_ERR_LOG("failed to get vibrate file metadata");
656 }
657 isVibrateFile_ = false;
658 return err;
659 }
660
661 if (type_ == FILE) {
662 err = Commit();
663 if (err != E_OK) {
664 RINGTONE_ERR_LOG("failed to commit err %{public}d", err);
665 isVibrateFile_ = false;
666 return err;
667 }
668 } else {
669 err = AddToTransaction();
670 if (err != E_OK) {
671 RINGTONE_ERR_LOG("failed to add to transaction err %{public}d", err);
672 isVibrateFile_ = false;
673 return err;
674 }
675 }
676
677 isVibrateFile_ = false;
678 return E_OK;
679 }
680
Commit()681 int32_t RingtoneScannerObj::Commit()
682 {
683 std::string tab = RINGTONE_TABLE;
684
685 if (isVibrateFile_) {
686 tab = VIBRATE_TABLE;
687
688 if (vibrateData_->GetVibrateId() != FILE_ID_DEFAULT) {
689 uri_ = RingtoneScannerDb::UpdateVibrateMetadata(*vibrateData_, tab);
690 } else {
691 uri_ = RingtoneScannerDb::InsertVibrateMetadata(*vibrateData_, tab);
692 }
693 } else {
694 if (data_->GetToneId() != FILE_ID_DEFAULT) {
695 uri_ = RingtoneScannerDb::UpdateMetadata(*data_, tab);
696 } else {
697 uri_ = RingtoneScannerDb::InsertMetadata(*data_, tab);
698 }
699 }
700
701 return E_OK;
702 }
703 } // namespace Media
704 } // namespace OHOS
705