• 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 
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