• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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