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