1 /*
2  * Copyright (C) 2022 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 "media_scanner_manager.h"
19 
20 #include "directory_ex.h"
21 
22 #include "media_log.h"
23 #include "medialibrary_errno.h"
24 #include "media_scanner_db.h"
25 
26 namespace OHOS {
27 namespace Media {
28 std::shared_ptr<MediaScannerManager> MediaScannerManager::instance_ = nullptr;
29 std::mutex MediaScannerManager::instanceMutex_;
30 
GetInstance()31 std::shared_ptr<MediaScannerManager> MediaScannerManager::GetInstance()
32 {
33     if (instance_ == nullptr) {
34         std::lock_guard<std::mutex> guard(instanceMutex_);
35 
36         if (instance_ != nullptr) {
37             return instance_;
38         }
39 
40         instance_ = std::shared_ptr<MediaScannerManager>(new (std::nothrow) MediaScannerManager());
41     }
42 
43     return instance_;
44 }
45 
ScanFile(const std::string & path,const std::shared_ptr<IMediaScannerCallback> & callback,MediaLibraryApi api)46 int32_t MediaScannerManager::ScanFile(const std::string &path, const std::shared_ptr<IMediaScannerCallback> &callback,
47     MediaLibraryApi api)
48 {
49     MEDIA_DEBUG_LOG("scan file %{private}s, api%{public}d", path.c_str(), static_cast<int>(api));
50 
51     string realPath;
52     if (!PathToRealPath(path, realPath)) {
53         MEDIA_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
54         return E_INVALID_PATH;
55     }
56 
57     if (!ScannerUtils::IsRegularFile(realPath)) {
58         MEDIA_ERR_LOG("the path %{private}s is not a regular file", realPath.c_str());
59         return E_INVALID_PATH;
60     }
61 
62     std::unique_ptr<MediaScannerObj> scanner =
63         std::make_unique<MediaScannerObj>(realPath, callback, MediaScannerObj::FILE, api);
64     executor_.Commit(move(scanner));
65 
66     return E_OK;
67 }
68 
ScanFileSync(const std::string & path,const std::shared_ptr<IMediaScannerCallback> & callback,MediaLibraryApi api,bool isForceScan,int32_t fileId)69 int32_t MediaScannerManager::ScanFileSync(const std::string &path,
70     const std::shared_ptr<IMediaScannerCallback> &callback, MediaLibraryApi api, bool isForceScan, int32_t fileId)
71 {
72     MEDIA_DEBUG_LOG("scan file %{private}s, api%{public}d", path.c_str(), static_cast<int>(api));
73 
74     string realPath;
75     if (!PathToRealPath(path, realPath)) {
76         MEDIA_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
77         return E_INVALID_PATH;
78     }
79 
80     if (!ScannerUtils::IsRegularFile(realPath)) {
81         MEDIA_ERR_LOG("the path %{private}s is not a regular file", realPath.c_str());
82         return E_INVALID_PATH;
83     }
84 
85     MediaScannerObj scanner = MediaScannerObj(realPath, callback, MediaScannerObj::FILE, api);
86     if (isForceScan) {
87         scanner.SetForceScan(true);
88     }
89     scanner.SetFileId(fileId);
90     scanner.Scan();
91 
92     return E_OK;
93 }
94 
ScanFileSyncWithoutAlbumUpdate(const std::string & path,const std::shared_ptr<IMediaScannerCallback> & callback,MediaLibraryApi api,bool isForceScan,int32_t fileId)95 int32_t MediaScannerManager::ScanFileSyncWithoutAlbumUpdate(const std::string &path,
96     const std::shared_ptr<IMediaScannerCallback> &callback, MediaLibraryApi api, bool isForceScan, int32_t fileId)
97 {
98     MEDIA_DEBUG_LOG("scan file %{private}s, api%{public}d", path.c_str(), static_cast<int>(api));
99 
100     string realPath;
101     if (!PathToRealPath(path, realPath)) {
102         MEDIA_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
103         return E_INVALID_PATH;
104     }
105 
106     if (!ScannerUtils::IsRegularFile(realPath)) {
107         MEDIA_ERR_LOG("the path %{private}s is not a regular file", realPath.c_str());
108         return E_INVALID_PATH;
109     }
110 
111     MediaScannerObj scanner = MediaScannerObj(realPath, callback, MediaScannerObj::FILE, api);
112     if (isForceScan) {
113         scanner.SetForceScan(true);
114     }
115     scanner.SetFileId(fileId);
116     scanner.SetIsSkipAlbumUpdate(true);
117     scanner.Scan();
118 
119     return E_OK;
120 }
121 
ScanDir(const std::string & path,const std::shared_ptr<IMediaScannerCallback> & callback)122 int32_t MediaScannerManager::ScanDir(const std::string &path, const std::shared_ptr<IMediaScannerCallback> &callback)
123 {
124     MEDIA_DEBUG_LOG("scan dir %{private}s", path.c_str());
125 
126     string realPath;
127     if (!PathToRealPath(path, realPath)) {
128         MEDIA_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
129         return E_INVALID_PATH;
130     }
131 
132     if (!ScannerUtils::IsDirectory(realPath)) {
133         MEDIA_ERR_LOG("the path %{private}s is not a directory", realPath.c_str());
134         return E_INVALID_PATH;
135     }
136 
137     std::unique_ptr<MediaScannerObj> scanner = std::make_unique<MediaScannerObj>(realPath, callback,
138         MediaScannerObj::DIRECTORY);
139     executor_.Commit(move(scanner));
140 
141     return E_OK;
142 }
143 
ScanDirSync(const std::string & path,const std::shared_ptr<IMediaScannerCallback> & callback)144 int32_t MediaScannerManager::ScanDirSync(const std::string &path,
145     const std::shared_ptr<IMediaScannerCallback> &callback)
146 {
147     MEDIA_DEBUG_LOG("scan dir %{private}s", path.c_str());
148 
149     string realPath;
150     if (!PathToRealPath(path, realPath)) {
151         MEDIA_ERR_LOG("failed to get real path %{private}s, errno %{public}d", path.c_str(), errno);
152         return E_INVALID_PATH;
153     }
154 
155     if (!ScannerUtils::IsDirectory(realPath)) {
156         MEDIA_ERR_LOG("the path %{private}s is not a directory", realPath.c_str());
157         return E_INVALID_PATH;
158     }
159 
160     MediaScannerObj scanner = MediaScannerObj(realPath, callback, MediaScannerObj::DIRECTORY);
161     scanner.Scan();
162 
163     return E_OK;
164 }
165 
Start()166 void MediaScannerManager::Start()
167 {
168     executor_.Start();
169 
170     std::unique_ptr<MediaScannerObj> scanner = std::make_unique<MediaScannerObj>(MediaScannerObj::START);
171     executor_.Commit(move(scanner));
172 }
173 
Stop()174 void MediaScannerManager::Stop()
175 {
176     /* stop all working threads */
177     this->executor_.Stop();
178 
179     MediaScannerDb::GetDatabaseInstance()->DeleteError(ROOT_MEDIA_DIR);
180 }
181 
ScanError()182 void MediaScannerManager::ScanError()
183 {
184     std::unique_ptr<MediaScannerObj> scanner = std::make_unique<MediaScannerObj>(MediaScannerObj::ERROR);
185     executor_.Commit(move(scanner));
186 }
187 
ErrorRecord(const std::string & path)188 void MediaScannerManager::ErrorRecord(const std::string &path)
189 {
190     std::unique_ptr<MediaScannerObj> scanner = std::make_unique<MediaScannerObj>(MediaScannerObj::SET_ERROR);
191     scanner->SetErrorPath(path);
192     executor_.Commit(move(scanner));
193 }
194 } // namespace Media
195 } // namespace OHOS