1 /*
2 * Copyright (c) 2025 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 "iservice_registry.h"
17 #include "system_ability_definition.h"
18 #include "sane_service_load_callback.h"
19 #include "sane_manager_client.h"
20
21 namespace OHOS::Scan {
22 constexpr int32_t SANE_SERVICE_ID = 3709;
23 constexpr int32_t LOAD_SA_TIMEOUT_MS = 15000;
24 std::mutex SaneManagerClient::instanceLock_;
25 std::shared_mutex SaneManagerClient::serviceLock_;
26 sptr<SaneManagerClient> SaneManagerClient::instance_;
27
SaneManagerClient()28 SaneManagerClient::SaneManagerClient() : proxy_(nullptr)
29 {
30 deathRecipient_ = new SaneSaDeathRecipient();
31 }
~SaneManagerClient()32 SaneManagerClient::~SaneManagerClient()
33 {
34 proxy_ = nullptr;
35 deathRecipient_ = nullptr;
36 }
37
GetInstance()38 sptr<SaneManagerClient> SaneManagerClient::GetInstance()
39 {
40 if (instance_ == nullptr) {
41 std::lock_guard<std::mutex> autoLock(instanceLock_);
42 if (instance_ == nullptr) {
43 instance_ = new SaneManagerClient;
44 }
45 }
46 return instance_;
47 }
48
GetSaneServiceProxy()49 sptr<ISaneBackends> SaneManagerClient::GetSaneServiceProxy()
50 {
51 {
52 std::unique_lock<std::shared_mutex> lock(serviceLock_);
53 if (proxy_ != nullptr) {
54 SCAN_HILOGD("already get proxy_");
55 return proxy_;
56 }
57 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
58 if (samgrProxy == nullptr) {
59 SCAN_HILOGE("samgrProxy is a nullptr");
60 return nullptr;
61 }
62 auto object = samgrProxy->CheckSystemAbility(SANE_SERVICE_ID);
63 if (object != nullptr) {
64 object->AddDeathRecipient(deathRecipient_);
65 proxy_ = iface_cast<ISaneBackends>(object);
66 return proxy_;
67 }
68 }
69 if (LoadSaneService()) {
70 std::unique_lock<std::shared_mutex> lock(serviceLock_);
71 return proxy_;
72 }
73 return nullptr;
74 }
75
LoadSaneService()76 bool SaneManagerClient::LoadSaneService()
77 {
78 std::unique_lock<std::shared_mutex> lock(serviceLock_);
79 sptr<SaneServiceLoadCallback> lockCallback = new SaneServiceLoadCallback();
80 if (lockCallback == nullptr) {
81 SCAN_HILOGE("lockCallback is a nullptr");
82 return false;
83 }
84 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
85 if (samgrProxy == nullptr) {
86 SCAN_HILOGE("get samgr failed");
87 return false;
88 }
89 int32_t ret = samgrProxy->LoadSystemAbility(SANE_SERVICE_ID, lockCallback);
90 if (ret != ERR_OK) {
91 SCAN_HILOGE("LoadSystemAbility failed");
92 return false;
93 }
94 auto waitStatus = syncCon_.wait_for(lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS),
95 [this]() { return proxy_ != nullptr; });
96 if (!waitStatus) {
97 return false;
98 }
99 return true;
100 }
101
LoadSystemAbilitysuccess(const sptr<IRemoteObject> & remoteObject)102 void SaneManagerClient::LoadSystemAbilitysuccess(const sptr<IRemoteObject> &remoteObject)
103 {
104 std::unique_lock<std::shared_mutex> lock(serviceLock_);
105 SCAN_HILOGI("sane_service LoadSystemAbilitysuccess");
106 if (remoteObject != nullptr) {
107 remoteObject->AddDeathRecipient(deathRecipient_);
108 proxy_ = iface_cast<ISaneBackends>(remoteObject);
109 syncCon_.notify_one();
110 }
111 }
112
LoadSystemAbilityFail()113 void SaneManagerClient::LoadSystemAbilityFail()
114 {
115 std::unique_lock<std::shared_mutex> lock(serviceLock_);
116 SCAN_HILOGI("sane_service LoadSystemAbilityFail");
117 proxy_ = nullptr;
118 }
119
OnRemoteSaDied(const wptr<IRemoteObject> & object)120 void SaneManagerClient::OnRemoteSaDied(const wptr<IRemoteObject>& object)
121 {
122 std::unique_lock<std::shared_mutex> lock(serviceLock_);
123 proxy_ = nullptr;
124 }
125
SaneInit()126 SaneStatus SaneManagerClient::SaneInit()
127 {
128 SCAN_HILOGI("SaneManagerClient SaneInit start.");
129 if (proxy_ == nullptr) {
130 SCAN_HILOGW("do GetSaneServiceProxy");
131 proxy_ = GetSaneServiceProxy();
132 }
133 std::shared_lock<std::shared_mutex> lock(serviceLock_);
134 if (proxy_ == nullptr) {
135 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
136 return SANE_STATUS_SERVER_FAILURE;
137 }
138 int32_t saneStatus = SANE_STATUS_GOOD;
139 int32_t ret = proxy_->SaneInit(saneStatus);
140 if (ret != ERR_NONE) {
141 SCAN_HILOGE("proxy_->SaneInit error exit, ret = [%{public}d]", ret);
142 return SANE_STATUS_RPC_FAILURE;
143 }
144 SCAN_HILOGI("SaneManagerClient SaneInit end, saneStatus = [%{public}d].", saneStatus);
145 return static_cast<SaneStatus>(saneStatus);
146 }
147
SaneExit()148 SaneStatus SaneManagerClient::SaneExit()
149 {
150 SCAN_HILOGI("SaneManagerClient SaneExit start.");
151 if (proxy_ == nullptr) {
152 SCAN_HILOGW("do GetSaneServiceProxy");
153 proxy_ = GetSaneServiceProxy();
154 }
155 std::shared_lock<std::shared_mutex> lock(serviceLock_);
156 if (proxy_ == nullptr) {
157 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
158 return SANE_STATUS_SERVER_FAILURE;
159 }
160 int32_t ret = proxy_->SaneExit();
161 if (ret != ERR_NONE) {
162 SCAN_HILOGE("proxy_->SaneExit error exit, ret = [%{public}d]", ret);
163 return SANE_STATUS_RPC_FAILURE;
164 }
165 SCAN_HILOGI("SaneManagerClient SaneExit end.");
166 return SANE_STATUS_GOOD;
167 }
168
SaneOpen(const std::string & scannerId)169 SaneStatus SaneManagerClient::SaneOpen(const std::string& scannerId)
170 {
171 SCAN_HILOGI("SaneManagerClient SaneOpen start.");
172 if (proxy_ == nullptr) {
173 SCAN_HILOGW("do GetSaneServiceProxy");
174 proxy_ = GetSaneServiceProxy();
175 }
176 std::shared_lock<std::shared_mutex> lock(serviceLock_);
177 if (proxy_ == nullptr) {
178 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
179 return SANE_STATUS_SERVER_FAILURE;
180 }
181 int32_t saneStatus = SANE_STATUS_GOOD;
182 int32_t ret = proxy_->SaneOpen(scannerId, saneStatus);
183 if (ret != ERR_NONE) {
184 SCAN_HILOGE("proxy_->SaneOpen error exit, ret = [%{public}d]", ret);
185 return SANE_STATUS_RPC_FAILURE;
186 }
187 SCAN_HILOGI("SaneManagerClient SaneOpen end, saneStatus = [%{public}d].", saneStatus);
188 return static_cast<SaneStatus>(saneStatus);
189 }
190
SaneClose(const std::string & scannerId)191 SaneStatus SaneManagerClient::SaneClose(const std::string& scannerId)
192 {
193 SCAN_HILOGI("SaneManagerClient SaneClose start.");
194 if (proxy_ == nullptr) {
195 SCAN_HILOGW("do GetSaneServiceProxy");
196 proxy_ = GetSaneServiceProxy();
197 }
198 std::shared_lock<std::shared_mutex> lock(serviceLock_);
199 if (proxy_ == nullptr) {
200 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
201 return SANE_STATUS_SERVER_FAILURE;
202 }
203 int32_t ret = proxy_->SaneClose(scannerId);
204 if (ret != ERR_NONE) {
205 SCAN_HILOGE("proxy_->SaneClose error exit, ret = [%{public}d]", ret);
206 return SANE_STATUS_RPC_FAILURE;
207 }
208 SCAN_HILOGI("SaneManagerClient SaneClose end.");
209 return SANE_STATUS_GOOD;
210 }
211
SaneStart(const std::string & scannerId)212 SaneStatus SaneManagerClient::SaneStart(const std::string& scannerId)
213 {
214 SCAN_HILOGI("SaneManagerClient SaneStart start.");
215 if (proxy_ == nullptr) {
216 SCAN_HILOGW("do GetSaneServiceProxy");
217 proxy_ = GetSaneServiceProxy();
218 }
219 std::shared_lock<std::shared_mutex> lock(serviceLock_);
220 if (proxy_ == nullptr) {
221 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
222 return SANE_STATUS_SERVER_FAILURE;
223 }
224 int32_t saneStatus = SANE_STATUS_GOOD;
225 int32_t ret = proxy_->SaneStart(scannerId, saneStatus);
226 if (ret != ERR_NONE) {
227 SCAN_HILOGE("proxy_->SaneStart error exit, ret = [%{public}d]", ret);
228 return SANE_STATUS_RPC_FAILURE;
229 }
230 SCAN_HILOGI("SaneManagerClient SaneStart end, saneStatus = [%{public}d].", saneStatus);
231 return static_cast<SaneStatus>(saneStatus);
232 }
233
SaneCancel(const std::string & scannerId)234 SaneStatus SaneManagerClient::SaneCancel(const std::string& scannerId)
235 {
236 SCAN_HILOGI("SaneManagerClient SaneCancel start.");
237 if (proxy_ == nullptr) {
238 SCAN_HILOGW("do GetSaneServiceProxy");
239 proxy_ = GetSaneServiceProxy();
240 }
241 std::shared_lock<std::shared_mutex> lock(serviceLock_);
242 if (proxy_ == nullptr) {
243 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
244 return SANE_STATUS_SERVER_FAILURE;
245 }
246 int32_t ret = proxy_->SaneCancel(scannerId);
247 if (ret != ERR_NONE) {
248 SCAN_HILOGE("proxy_->SaneCancel error exit, ret = [%{public}d]", ret);
249 return SANE_STATUS_RPC_FAILURE;
250 }
251 SCAN_HILOGI("SaneManagerClient SaneCancel end.");
252 return SANE_STATUS_GOOD;
253 }
254
SaneGetOptionDescriptor(const std::string & scannerId,const int32_t & option,SaneOptionDescriptor & desc)255 SaneStatus SaneManagerClient::SaneGetOptionDescriptor(const std::string& scannerId, const int32_t& option,
256 SaneOptionDescriptor& desc)
257 {
258 SCAN_HILOGI("SaneManagerClient SaneGetOptionDescriptor start.");
259 if (proxy_ == nullptr) {
260 SCAN_HILOGW("do GetSaneServiceProxy");
261 proxy_ = GetSaneServiceProxy();
262 }
263 std::shared_lock<std::shared_mutex> lock(serviceLock_);
264 if (proxy_ == nullptr) {
265 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
266 return SANE_STATUS_SERVER_FAILURE;
267 }
268 int32_t saneStatus = SANE_STATUS_GOOD;
269 int32_t ret = proxy_->SaneGetOptionDescriptor(scannerId, option, desc, saneStatus);
270 if (ret != ERR_NONE) {
271 SCAN_HILOGE("proxy_->SaneGetOptionDescriptor error exit, ret = [%{public}d]", ret);
272 return SANE_STATUS_RPC_FAILURE;
273 }
274 SCAN_HILOGI("SaneManagerClient SaneGetOptionDescriptor end, saneStatus = [%{public}d].", saneStatus);
275 return static_cast<SaneStatus>(saneStatus);
276 }
277
SaneGetParameters(const std::string & scannerId,SaneParameters & params)278 SaneStatus SaneManagerClient::SaneGetParameters(const std::string& scannerId, SaneParameters& params)
279 {
280 SCAN_HILOGI("SaneManagerClient SaneGetParameters start.");
281 if (proxy_ == nullptr) {
282 SCAN_HILOGW("do GetSaneServiceProxy");
283 proxy_ = GetSaneServiceProxy();
284 }
285 std::shared_lock<std::shared_mutex> lock(serviceLock_);
286 if (proxy_ == nullptr) {
287 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
288 return SANE_STATUS_SERVER_FAILURE;
289 }
290 int32_t saneStatus = SANE_STATUS_GOOD;
291 int32_t ret = proxy_->SaneGetParameters(scannerId, params, saneStatus);
292 if (ret != ERR_NONE) {
293 SCAN_HILOGE("proxy_->SaneGetParameters error exit, ret = [%{public}d]", ret);
294 return SANE_STATUS_RPC_FAILURE;
295 }
296 SCAN_HILOGI("SaneManagerClient SaneGetParameters end, saneStatus = [%{public}d].", saneStatus);
297 return static_cast<SaneStatus>(saneStatus);
298 }
299
SaneGetDevices(std::vector<SaneDevice> & deviceInfos)300 SaneStatus SaneManagerClient::SaneGetDevices(std::vector<SaneDevice>& deviceInfos)
301 {
302 SCAN_HILOGI("SaneManagerClient SaneGetDevices start.");
303 if (proxy_ == nullptr) {
304 SCAN_HILOGW("do GetSaneServiceProxy");
305 proxy_ = GetSaneServiceProxy();
306 }
307 std::shared_lock<std::shared_mutex> lock(serviceLock_);
308 if (proxy_ == nullptr) {
309 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
310 return SANE_STATUS_SERVER_FAILURE;
311 }
312 int32_t saneStatus = SANE_STATUS_GOOD;
313 int32_t ret = proxy_->SaneGetDevices(deviceInfos, saneStatus);
314 if (ret != ERR_NONE) {
315 SCAN_HILOGE("proxy_->SaneGetDevices error exit, ret = [%{public}d]", ret);
316 return SANE_STATUS_RPC_FAILURE;
317 }
318 SCAN_HILOGI("SaneManagerClient SaneGetDevices end, saneStatus = [%{public}d].", saneStatus);
319 return static_cast<SaneStatus>(saneStatus);
320 }
321
SaneControlOption(const std::string & scannerId,SaneControlParam & controlParam,SaneOutParam & outParam)322 SaneStatus SaneManagerClient::SaneControlOption(const std::string& scannerId, SaneControlParam& controlParam,
323 SaneOutParam& outParam)
324 {
325 SCAN_HILOGI("SaneManagerClient SaneControlOption start.");
326 if (proxy_ == nullptr) {
327 SCAN_HILOGW("do GetSaneServiceProxy");
328 proxy_ = GetSaneServiceProxy();
329 }
330 std::shared_lock<std::shared_mutex> lock(serviceLock_);
331 if (proxy_ == nullptr) {
332 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
333 return SANE_STATUS_SERVER_FAILURE;
334 }
335 int32_t saneStatus = SANE_STATUS_GOOD;
336 int32_t ret = proxy_->SaneControlOption(scannerId, controlParam, outParam, saneStatus);
337 if (ret != ERR_NONE) {
338 SCAN_HILOGE("proxy_->SaneControlOption error exit, ret = [%{public}d]", ret);
339 return SANE_STATUS_RPC_FAILURE;
340 }
341 SCAN_HILOGI("SaneManagerClient SaneControlOption end, saneStatus = [%{public}d].", saneStatus);
342 return static_cast<SaneStatus>(saneStatus);
343 }
344
SaneRead(const std::string & scannerId,const int32_t buflen,SanePictureData & pictureData)345 SaneStatus SaneManagerClient::SaneRead(const std::string& scannerId, const int32_t buflen,
346 SanePictureData& pictureData)
347 {
348 SCAN_HILOGI("SaneManagerClient SaneRead start.");
349 if (proxy_ == nullptr) {
350 SCAN_HILOGW("do GetSaneServiceProxy");
351 proxy_ = GetSaneServiceProxy();
352 }
353 std::shared_lock<std::shared_mutex> lock(serviceLock_);
354 if (proxy_ == nullptr) {
355 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
356 return SANE_STATUS_SERVER_FAILURE;
357 }
358 int32_t saneStatus = SANE_STATUS_GOOD;
359 int32_t ret = proxy_->SaneRead(scannerId, buflen, pictureData, saneStatus);
360 if (ret != ERR_NONE) {
361 SCAN_HILOGE("proxy_->SaneRead error exit, ret = [%{public}d]", ret);
362 return SANE_STATUS_RPC_FAILURE;
363 }
364 SCAN_HILOGI("SaneManagerClient SaneRead end, saneStatus = [%{public}d].", saneStatus);
365 return static_cast<SaneStatus>(saneStatus);
366 }
367
UnloadSystemAbility()368 SaneStatus SaneManagerClient::UnloadSystemAbility()
369 {
370 SCAN_HILOGI("SaneManagerClient UnloadSystemAbility start.");
371 if (proxy_ == nullptr) {
372 SCAN_HILOGW("do GetSaneServiceProxy");
373 proxy_ = GetSaneServiceProxy();
374 }
375 std::shared_lock<std::shared_mutex> lock(serviceLock_);
376 if (proxy_ == nullptr) {
377 SCAN_HILOGE("On quit because redoing GetSaneServiceProxy failed..");
378 return SANE_STATUS_SERVER_FAILURE;
379 }
380 int32_t ret = proxy_->UnloadSystemAbility();
381 if (ret != ERR_NONE) {
382 SCAN_HILOGE("proxy_->UnloadSystemAbility error exit, ret = [%{public}d]", ret);
383 return SANE_STATUS_RPC_FAILURE;
384 }
385 SCAN_HILOGI("SaneManagerClient UnloadSystemAbility end.");
386 return SANE_STATUS_GOOD;
387 }
388 } // namespace OHOS::Scan