• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "media_scanner_client.h"
17 
18 using namespace OHOS::AppExecFwk;
19 using namespace OHOS::AAFwk;
20 using namespace std;
21 
22 namespace OHOS {
23 namespace Media {
CreateScannerHelper()24 std::shared_ptr<IMediaScannerClient> MediaScannerHelperFactory::CreateScannerHelper()
25 {
26     return OHOS::Media::MediaScannerClient::GetMediaScannerInstance();
27 }
28 
29 std::mutex MediaScannerClient::mutex_;
30 std::shared_ptr<MediaScannerClient> MediaScannerClient::msInstance_ = nullptr;
31 
GetMediaScannerInstance()32 std::shared_ptr<MediaScannerClient> MediaScannerClient::GetMediaScannerInstance()
33 {
34     if (msInstance_ == nullptr) {
35         std::lock_guard<std::mutex> lock(mutex_);
36         if (msInstance_ == nullptr) {
37             msInstance_ = std::make_shared<MediaScannerClient>();
38         }
39     }
40 
41     CHECK_AND_RETURN_RET_LOG(msInstance_ != nullptr, nullptr, "Failed to create new media scanner client");
42 
43     return msInstance_;
44 }
45 
~MediaScannerClient()46 MediaScannerClient::~MediaScannerClient()
47 {
48     connectionState_ = ConnectionState::CONN_NONE;
49     abilityMgrProxy_ = nullptr;
50     connection_ = nullptr;
51     scanList_.clear();
52 }
53 
54 
ConnectAbility()55 int32_t MediaScannerClient::ConnectAbility()
56 {
57     std::lock_guard<std::mutex> lock(mutex_);
58     if (!IsScannerServiceConnected()) {
59         // Obtain ability manager service for connecting to ability
60         auto abilityMgr = DelayedSingleton<SysMrgClient>::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
61         CHECK_AND_RETURN_RET_LOG(abilityMgr != nullptr, CONN_ERROR, "Ability Mgr instance not available");
62 
63         abilityMgrProxy_ = iface_cast<IAbilityManager>(abilityMgr);
64         CHECK_AND_RETURN_RET_LOG(abilityMgrProxy_ != nullptr, CONN_ERROR, "Ability Mgr proxy is null");
65 
66         // Create callback stub object and pass to fwk connect request.
67         connection_ = new (std::nothrow) MediaScannerConnectCallbackStub();
68         CHECK_AND_RETURN_RET_LOG(connection_ != nullptr, CONN_ERROR, "connect cb object create failed");
69 
70         Want want;
71         want.SetElementName(SCANNER_BUNDLE_NAME, SCANNER_ABILITY_NAME);
72 
73         // Connect to the service ability. Dest ability name mentioned in want param
74         SetConnectionState(ConnectionState::CONN_IN_PROGRESS);
75         int32_t ret = abilityMgrProxy_->ConnectAbility(want, connection_, nullptr);
76         if (ret != 0) {
77             MEDIA_ERR_LOG("MediaScannerClient:: Connect ability failed %{public}d", ret);
78             SetConnectionState(ConnectionState::CONN_ERROR);
79             return CONN_ERROR;
80         }
81     }
82 
83     return CONN_SUCCESS;
84 }
85 
DisconnectAbility()86 void MediaScannerClient::DisconnectAbility()
87 {
88     CHECK_AND_RETURN_LOG(connection_ != nullptr && abilityMgrProxy_ != nullptr, "Connection unavailable");
89 
90     int32_t ret = abilityMgrProxy_->DisconnectAbility(connection_);
91     if (ret != 0) {
92         MEDIA_ERR_LOG("MediaScannerClient:: Disconnect ability failed %{public}d", ret);
93         return;
94     }
95 
96     connectionState_ = ConnectionState::CONN_NONE;
97     abilityMgrProxy_ = nullptr;
98     connection_ = nullptr;
99     scanList_.clear();
100 }
101 
Release()102 void MediaScannerClient::Release()
103 {
104     // If already disconnected, return from here
105     std::lock_guard<std::mutex> lock(mutex_);
106     if (!IsScannerServiceConnected()) {
107         MEDIA_ERR_LOG("Scanner Service is not connected");
108         return;
109     }
110 
111     CHECK_AND_RETURN_LOG(abilityProxy_ != nullptr, "Ability service proxy unavailable");
112 
113     if (abilityProxy_->IsScannerRunning()) {
114         MEDIA_ERR_LOG("scanner is running. Cannot release ability now");
115         return;
116     }
117 
118     // Scanner is not running. Release ability
119     DisconnectAbility();
120 }
121 
ScanDir(string & scanDirPath,const shared_ptr<IMediaScannerAppCallback> & scanDircb)122 ScanState MediaScannerClient::ScanDir(string &scanDirPath, const shared_ptr<IMediaScannerAppCallback> &scanDircb)
123 {
124     return ScanInternal(scanDirPath, scanDircb, ScanType::SCAN_DIR);
125 }
126 
ScanFile(string & scanFilePath,const shared_ptr<IMediaScannerAppCallback> & scanFileCb)127 ScanState MediaScannerClient::ScanFile(string &scanFilePath, const shared_ptr<IMediaScannerAppCallback> &scanFileCb)
128 {
129     return ScanInternal(scanFilePath, scanFileCb, ScanType::SCAN_FILE);
130 }
131 
ScanInternal(string & path,const shared_ptr<IMediaScannerAppCallback> & appCb,ScanType scanType)132 ScanState MediaScannerClient::ScanInternal(string &path, const shared_ptr<IMediaScannerAppCallback> &appCb,
133     ScanType scanType)
134 {
135     auto connectResult = ConnectAbility();
136     CHECK_AND_RETURN_RET_LOG(connectResult == CONN_SUCCESS, SCAN_ERROR, "Service error %{public}d", connectResult);
137 
138     auto callbackStub = new(std::nothrow) MediaScannerOperationCallbackStub();
139     CHECK_AND_RETURN_RET_LOG(callbackStub != nullptr, SCAN_MEM_ALLOC_FAIL, "ScannerOperCallback creation failed");
140 
141     callbackStub->SetApplicationCallback(appCb);
142 
143     auto callbackRemoteObj = callbackStub->AsObject();
144     CHECK_AND_RETURN_RET_LOG(callbackRemoteObj != nullptr, SCAN_MEM_ALLOC_FAIL, "callback remote obj is null");
145 
146     // If service is not connected, add the request into queue. Queue will be processed OnAbilityConnected callback
147     if (GetConnectionState() == ConnectionState::CONN_IN_PROGRESS) {
148         ScanRequest scanRequest;
149         scanRequest.scanType = scanType;
150         scanRequest.path = path;
151         scanRequest.serviceCb = callbackRemoteObj;
152         scanRequest.appCallback = appCb;
153 
154         // Add request to the queue with locked scope
155         if (UpdateScanRequestQueue(scanRequest)) {
156             return SCAN_SUCCESS;
157         }
158     }
159 
160     CHECK_AND_RETURN_RET_LOG(abilityProxy_ != nullptr, SCAN_ERROR, "Ability service proxy unavailable for scanning");
161 
162     if (scanType == ScanType::SCAN_FILE) {
163         int32_t ret = abilityProxy_->ScanFileService(path, callbackRemoteObj);
164         CHECK_AND_RETURN_RET_LOG(ret == 0, static_cast<ScanState>(ret), "Scan file failed [%{public}d]", ret);
165     } else if (scanType == ScanType::SCAN_DIR) {
166         int32_t ret = abilityProxy_->ScanDirService(path, callbackRemoteObj);
167         CHECK_AND_RETURN_RET_LOG(ret == 0, static_cast<ScanState>(ret), "Scan dir failed [%{public}d]", ret);
168     }
169 
170     return SCAN_SUCCESS;
171 }
172 
IsScannerServiceConnected()173 bool MediaScannerClient::IsScannerServiceConnected()
174 {
175     ConnectionState connState = GetConnectionState();
176     if (connState == ConnectionState::CONN_SUCCESS || connState == ConnectionState::CONN_IN_PROGRESS) {
177         return true;
178     }
179 
180     return false;
181 }
182 
SetConnectionState(ConnectionState connState)183 void MediaScannerClient::SetConnectionState(ConnectionState connState)
184 {
185     connectionState_ = connState;
186 }
187 
GetConnectionState()188 ConnectionState MediaScannerClient::GetConnectionState()
189 {
190     return connectionState_;
191 }
192 
EmptyScanRequestQueue(bool isConnected)193 void MediaScannerClient::EmptyScanRequestQueue(bool isConnected)
194 {
195     for (auto &scanRequest : scanList_) {
196         if (!isConnected) {
197             MEDIA_ERR_LOG("Remote object unavailable. Notify registered clients");
198             CHECK_AND_RETURN_LOG(scanRequest.appCallback != nullptr, "Invalid app callback object");
199             scanRequest.appCallback->OnScanFinished(SCAN_ERROR, "", scanRequest.path);
200             continue;
201         }
202 
203         CHECK_AND_RETURN_LOG(abilityProxy_ != nullptr, "Ability service unavailable");
204         auto ret(0);
205         switch (scanRequest.scanType) {
206             case SCAN_FILE:
207                 ret = abilityProxy_->ScanFileService(scanRequest.path, scanRequest.serviceCb);
208                 if (ret != SCAN_SUCCESS) {
209                     MEDIA_ERR_LOG("Scan file operation failed %{public}d", ret);
210                     scanRequest.appCallback->OnScanFinished(ret, "", scanRequest.path);
211                 }
212                 break;
213             case SCAN_DIR:
214                 ret = abilityProxy_->ScanDirService(scanRequest.path, scanRequest.serviceCb);
215                 if (ret != SCAN_SUCCESS) {
216                     MEDIA_ERR_LOG("Scan dir operation failed %{public}d", ret);
217                     scanRequest.appCallback->OnScanFinished(ret, "", scanRequest.path);
218                 }
219                 break;
220             default:
221                 break;
222         }
223     }
224 
225     scanList_.clear();
226 }
227 
UpdateScanRequestQueue(ScanRequest & scanRequest)228 bool MediaScannerClient::UpdateScanRequestQueue(ScanRequest &scanRequest)
229 {
230     std::lock_guard<std::mutex> lock(mutex_);
231     if (GetConnectionState() == ConnectionState::CONN_IN_PROGRESS) {
232         scanList_.emplace_back(scanRequest);
233         return true;
234     }
235 
236     return false;
237 }
238 
OnConnectAbility(const sptr<IRemoteObject> & remoteObject,int32_t result)239 void MediaScannerClient::OnConnectAbility(const sptr<IRemoteObject> &remoteObject, int32_t result)
240 {
241     sptr<IMediaScannerAbility> scannerAbilityProxy = iface_cast<IMediaScannerAbility>(remoteObject);
242 
243     std::lock_guard<std::mutex> lock(mutex_);
244     if (result == 0 && scannerAbilityProxy != nullptr) {
245         SetConnectionState(ConnectionState::CONN_SUCCESS);
246         abilityProxy_ = scannerAbilityProxy;
247         MediaScannerClient::EmptyScanRequestQueue(true);
248     } else {
249         SetConnectionState(ConnectionState::CONN_ERROR);
250         abilityProxy_ = nullptr;
251         MediaScannerClient::EmptyScanRequestQueue(false);
252     }
253 }
254 
OnDisconnectAbility()255 void MediaScannerClient::OnDisconnectAbility()
256 {
257     abilityProxy_ = nullptr;
258 
259     std::lock_guard<std::mutex> lock(mutex_);
260     SetConnectionState(ConnectionState::CONN_NONE);
261 
262     // Clear all pending requests. Since service is disconnected, we cannot process any requests
263     if (!scanList_.empty()) {
264         MediaScannerClient::EmptyScanRequestQueue(false);
265     }
266 }
267 
268 // Connect callback impl
MediaScannerConnectCallbackStub()269 MediaScannerConnectCallbackStub::MediaScannerConnectCallbackStub()
270 {
271     scannerClientInstance_ = MediaScannerClient::GetMediaScannerInstance();
272 }
273 
~MediaScannerConnectCallbackStub()274 MediaScannerConnectCallbackStub::~MediaScannerConnectCallbackStub()
275 {
276     scannerClientInstance_ = nullptr;
277 }
278 
OnAbilityConnectDone(const OHOS::AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t result)279 void MediaScannerConnectCallbackStub::OnAbilityConnectDone(const OHOS::AppExecFwk::ElementName &element,
280     const sptr<IRemoteObject> &remoteObject, int32_t result)
281 {
282     CHECK_AND_RETURN_LOG(scannerClientInstance_ != nullptr, "Scanner instance is down in OnAbilityConnectDone");
283     scannerClientInstance_->OnConnectAbility(remoteObject, result);
284 }
285 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int32_t result)286 void MediaScannerConnectCallbackStub::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t result)
287 {
288     CHECK_AND_RETURN_LOG(scannerClientInstance_ != nullptr, "Scanner instance is down in OnAbilityDisconnectDone");
289     scannerClientInstance_->OnDisconnectAbility();
290 }
291 } // namespace Media
292 } // namespace OHOS
293