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