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_manager.h"
19 
20 #include "directory_ex.h"
21 #include "ringtone_log.h"
22 #include "ringtone_scanner_utils.h"
23 
24 namespace OHOS {
25 namespace Media {
26 std::shared_ptr<RingtoneScannerManager> RingtoneScannerManager::instance_ = nullptr;
27 std::mutex RingtoneScannerManager::instanceMutex_;
28 
GetInstance()29 std::shared_ptr<RingtoneScannerManager> RingtoneScannerManager::GetInstance()
30 {
31     if (instance_ == nullptr) {
32         std::lock_guard<std::mutex> guard(instanceMutex_);
33 
34         if (instance_ != nullptr) {
35             return instance_;
36         }
37 
38         instance_ = std::make_shared<RingtoneScannerManager>();
39     }
40 
41     return instance_;
42 }
43 
ScanFile(const std::string & path,const std::shared_ptr<IRingtoneScannerCallback> & callback)44 int32_t RingtoneScannerManager::ScanFile(const std::string &path,
45     const std::shared_ptr<IRingtoneScannerCallback> &callback)
46 {
47     RINGTONE_DEBUG_LOG("scan file %{private}s", path.c_str());
48 
49     std::string realPath;
50     if (!PathToRealPath(path, realPath)) {
51         RINGTONE_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
52         return E_INVALID_PATH;
53     }
54 
55     if (!RingtoneScannerUtils::IsRegularFile(realPath)) {
56         RINGTONE_ERR_LOG("the path %{private}s is not a regular file", realPath.c_str());
57         return E_INVALID_PATH;
58     }
59 
60     std::unique_ptr<RingtoneScannerObj> scanner =
61         std::make_unique<RingtoneScannerObj>(realPath, callback, RingtoneScannerObj::FILE);
62     executor_.Commit(move(scanner));
63 
64     return E_OK;
65 }
66 
ScanFileSync(const std::string & path,const std::shared_ptr<IRingtoneScannerCallback> & callback,bool isForceScan)67 int32_t RingtoneScannerManager::ScanFileSync(const std::string &path,
68     const std::shared_ptr<IRingtoneScannerCallback> &callback, bool isForceScan)
69 {
70     RINGTONE_DEBUG_LOG("scan file %{private}s", path.c_str());
71 
72     std::string realPath;
73     if (!PathToRealPath(path, realPath)) {
74         RINGTONE_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
75         return E_INVALID_PATH;
76     }
77 
78     if (!RingtoneScannerUtils::IsRegularFile(realPath)) {
79         RINGTONE_ERR_LOG("the path %{private}s is not a regular file", realPath.c_str());
80         return E_INVALID_PATH;
81     }
82 
83     RingtoneScannerObj scanner = RingtoneScannerObj(realPath, callback, RingtoneScannerObj::FILE);
84     if (isForceScan) {
85         scanner.SetForceScan(true);
86     }
87     scanner.Scan();
88 
89     return E_OK;
90 }
91 
ScanDir(const std::string & path,const std::shared_ptr<IRingtoneScannerCallback> & callback)92 int32_t RingtoneScannerManager::ScanDir(const std::string &path,
93     const std::shared_ptr<IRingtoneScannerCallback> &callback)
94 {
95     RINGTONE_DEBUG_LOG("scan dir %{private}s", path.c_str());
96 
97     std::string realPath;
98     if (!PathToRealPath(path, realPath)) {
99         RINGTONE_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
100         return E_INVALID_PATH;
101     }
102 
103     if (!RingtoneScannerUtils::IsDirectory(realPath)) {
104         RINGTONE_ERR_LOG("the path %{private}s is not a directory", realPath.c_str());
105         return E_INVALID_PATH;
106     }
107 
108     std::unique_ptr<RingtoneScannerObj> scanner = std::make_unique<RingtoneScannerObj>(realPath, callback,
109         RingtoneScannerObj::DIRECTORY);
110     executor_.Commit(move(scanner));
111 
112     return E_OK;
113 }
114 
ScanDirSync(const std::string & path,const std::shared_ptr<IRingtoneScannerCallback> & callback)115 int32_t RingtoneScannerManager::ScanDirSync(const std::string &path,
116     const std::shared_ptr<IRingtoneScannerCallback> &callback)
117 {
118     RINGTONE_DEBUG_LOG("scan dir %{private}s", path.c_str());
119 
120     std::string realPath;
121     if (!PathToRealPath(path, realPath)) {
122         RINGTONE_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
123         return E_INVALID_PATH;
124     }
125 
126     if (!RingtoneScannerUtils::IsDirectory(realPath)) {
127         RINGTONE_ERR_LOG("the path %{private}s is not a directory", realPath.c_str());
128         return E_INVALID_PATH;
129     }
130 
131     RingtoneScannerObj scanner = RingtoneScannerObj(realPath, callback, RingtoneScannerObj::DIRECTORY);
132     scanner.Scan();
133 
134     return E_OK;
135 }
136 
Start(bool isSync)137 void RingtoneScannerManager::Start(bool isSync)
138 {
139     if (isSync) {
140         RINGTONE_DEBUG_LOG("scan start, isSync = %{public}d", isSync);
141         RingtoneScannerObj scanner = RingtoneScannerObj(RingtoneScannerObj::START);
142         scanner.Scan();
143         RINGTONE_DEBUG_LOG("scan finished");
144     } else {
145         RINGTONE_DEBUG_LOG("scan start, isSync = %{public}d", isSync);
146         executor_.Start();
147         std::shared_ptr<RingtoneScannerObj> scanner = std::make_shared<RingtoneScannerObj>(RingtoneScannerObj::START);
148         executor_.Commit(scanner);
149         scanner->WaitFor();
150         RINGTONE_DEBUG_LOG("scan finished");
151     }
152 }
153 
Stop()154 void RingtoneScannerManager::Stop()
155 {
156     /* stop all working threads */
157     this->executor_.Stop();
158 }
159 } // namespace Media
160 } // namespace OHOS
161