• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ipc_skeleton.h>
17 #include <system_ability_definition.h>
18 #include <iservice_registry.h>
19 #include <thread>
20 #include "accesstoken_kit.h"
21 #include "directory_ex.h"
22 #include "sane/sane.h"
23 #include "sane/saneopts.h"
24 #include "sane_service_ability.h"
25 #include "sane_device.h"
26 
27 namespace OHOS {
28 namespace Scan {
29 
30 constexpr int32_t SANE_SERVICE_ID = 3709;
31 
32 REGISTER_SYSTEM_ABILITY_BY_ID(SaneServerManager, SANE_SERVICE_ID, true);
33 
SaneServerManager(int32_t saId,bool runOnCreate)34 SaneServerManager::SaneServerManager(int32_t saId, bool runOnCreate) : SystemAbility(SANE_SERVICE_ID, true)
35 {
36     SCAN_HILOGI("SaneServerManager init");
37 }
38 
OnStart()39 void SaneServerManager::OnStart()
40 {
41     SCAN_HILOGI("SaneServerManager::OnStart()");
42     if (!Publish(this)) {
43         SCAN_HILOGE("SaneServerManager::OnStart() failed");
44         return;
45     }
46     SCAN_HILOGI("SaneServerManager start success");
47 }
48 
GetScanHandle(const std::string & scannerId)49 SANE_Handle SaneServerManager::GetScanHandle(const std::string& scannerId)
50 {
51     auto it = scannerHandleList_.find(scannerId);
52     if (it == scannerHandleList_.end()) {
53         SCAN_HILOGE("ScannerId is not openned!");
54         return nullptr;
55     }
56     return it->second;
57 }
58 
CheckPermission()59 bool SaneServerManager::CheckPermission()
60 {
61     using namespace Security::AccessToken;
62     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
63     TypeATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
64     if (tokenType != TOKEN_NATIVE) {
65         SCAN_HILOGE("invalid tokenType, type = [%{public}u]", tokenType);
66         return false;
67     }
68     static const std::string PERMISSION_NAME_PRINT = "ohos.permission.PRINT";
69     int result = AccessTokenKit::VerifyAccessToken(tokenId, PERMISSION_NAME_PRINT);
70     if (result != PERMISSION_GRANTED) {
71         SCAN_HILOGE("Current tokenId permission is denied.");
72         return false;
73     }
74     return true;
75 }
76 
SaneInit(int32_t & status)77 ErrCode SaneServerManager::SaneInit(int32_t& status)
78 {
79     SCAN_HILOGI("SaneInit start");
80     if (!CheckPermission()) {
81         SCAN_HILOGE("no permission to access sane_service");
82         return SANE_STATUS_NO_PERMISSION;
83     }
84     int32_t scanVersion = 0;
85     SANE_Status saneStatus = sane_init(&scanVersion, nullptr);
86     status = static_cast<int32_t>(saneStatus);
87     SCAN_HILOGI("sane_init successfully, version [%{public}d]", scanVersion);
88     return ERR_OK;
89 }
90 
SaneExit()91 ErrCode SaneServerManager::SaneExit()
92 {
93     SCAN_HILOGI("SaneExit start");
94     if (!CheckPermission()) {
95         SCAN_HILOGE("no permission to access sane_service");
96         return SANE_STATUS_NO_PERMISSION;
97     }
98     sane_exit();
99     SCAN_HILOGI("SaneExit end");
100     return ERR_OK;
101 }
102 
SaneOpen(const std::string & scannerId,int32_t & status)103 ErrCode SaneServerManager::SaneOpen(const std::string& scannerId, int32_t& status)
104 {
105     SCAN_HILOGI("SaneOpen start");
106     if (!CheckPermission()) {
107         SCAN_HILOGE("no permission to access sane_service");
108         return SANE_STATUS_NO_PERMISSION;
109     }
110     std::lock_guard<std::mutex> autoLock(scannerHandleListlock_);
111     if (scannerHandleList_.find(scannerId) != scannerHandleList_.end()) {
112         status = SANE_STATUS_GOOD;
113         return ERR_OK;
114     }
115     SANE_Handle handle = nullptr;
116     SANE_Status saneStatus = sane_open(scannerId.c_str(), &handle);
117     if (saneStatus != ::SANE_STATUS_GOOD) {
118         status = static_cast<int32_t>(saneStatus);
119         SCAN_HILOGE("sane_open error, ret = [%{public}d]", status);
120         return ERR_OK;
121     }
122     if (handle == nullptr) {
123         SCAN_HILOGE("handle is a nullptr.");
124         status = SANE_STATUS_INVAL;
125         return ERR_OK;
126     }
127     scannerHandleList_.insert({scannerId, handle});
128     SCAN_HILOGI("sane_open end, ret = [%{public}d]", status);
129     return ERR_OK;
130 }
131 
SaneClose(const std::string & scannerId)132 ErrCode SaneServerManager::SaneClose(const std::string& scannerId)
133 {
134     SCAN_HILOGI("SaneClose start");
135     if (!CheckPermission()) {
136         SCAN_HILOGE("no permission to access sane_service");
137         return SANE_STATUS_NO_PERMISSION;
138     }
139     std::lock_guard<std::mutex> autoLock(scannerHandleListlock_);
140     auto it = scannerHandleList_.find(scannerId);
141     if (it != scannerHandleList_.end()) {
142         sane_close(it->second);
143         scannerHandleList_.erase(it);
144     }
145     SCAN_HILOGI("SaneClose end");
146     return ERR_OK;
147 }
148 
SaneStart(const std::string & scannerId,int32_t & status)149 ErrCode SaneServerManager::SaneStart(const std::string& scannerId, int32_t& status)
150 {
151     SCAN_HILOGI("SaneStart start");
152     if (!CheckPermission()) {
153         SCAN_HILOGE("no permission to access sane_service");
154         return SANE_STATUS_NO_PERMISSION;
155     }
156     SANE_Handle handle = GetScanHandle(scannerId);
157     if (handle == nullptr) {
158         SCAN_HILOGE("handle is a nullptr");
159         status = SANE_STATUS_INVAL;
160         return ERR_OK;
161     }
162     SANE_Status saneStatus = sane_start(handle);
163     status = static_cast<int32_t>(saneStatus);
164     SCAN_HILOGI("sane_start end, ret = [%{public}d]", status);
165     return ERR_OK;
166 }
167 
SaneCancel(const std::string & scannerId)168 ErrCode SaneServerManager::SaneCancel(const std::string& scannerId)
169 {
170     SCAN_HILOGI("SaneCancel start");
171     if (!CheckPermission()) {
172         SCAN_HILOGE("no permission to access sane_service");
173         return SANE_STATUS_NO_PERMISSION;
174     }
175     SANE_Handle handle = GetScanHandle(scannerId);
176     if (handle == nullptr) {
177         SCAN_HILOGE("handle is a nullptr");
178         return ERR_OK;
179     }
180     sane_cancel(handle);
181     SCAN_HILOGI("sane_cancel end");
182     return ERR_OK;
183 }
184 
SaneGetOptionDescriptor(const std::string & scannerId,int32_t saneOption,SaneOptionDescriptor & saneOptDes,int32_t & status)185 ErrCode SaneServerManager::SaneGetOptionDescriptor(const std::string& scannerId, int32_t saneOption,
186     SaneOptionDescriptor& saneOptDes, int32_t& status)
187 {
188     SCAN_HILOGI("SaneGetOptionDescriptor start");
189     if (!CheckPermission()) {
190         SCAN_HILOGE("no permission to access sane_service");
191         return SANE_STATUS_NO_PERMISSION;
192     }
193     SANE_Handle handle = GetScanHandle(scannerId);
194     if (handle == nullptr) {
195         SCAN_HILOGE("handle is a nullptr");
196         status = SANE_STATUS_INVAL;
197         return ERR_OK;
198     }
199     SCAN_HILOGD("saneOption %{public}d", saneOption);
200     const SANE_Option_Descriptor* saneDesc = sane_get_option_descriptor(handle, saneOption);
201     if (saneDesc == nullptr) {
202         SCAN_HILOGE("saneDesc is a nullptr");
203         status = SANE_STATUS_INVAL;
204         return ERR_OK;
205     }
206     ConvertSaneDescriptor(saneDesc, saneOptDes);
207     saneOptDes.Dump();
208     SCAN_HILOGI("SaneGetOptionDescriptor end");
209     status = SANE_STATUS_GOOD;
210     return ERR_OK;
211 }
212 
ConvertSaneDescriptor(const SANE_Option_Descriptor * saneDesc,SaneOptionDescriptor & saneOptDes)213 void SaneServerManager::ConvertSaneDescriptor(const SANE_Option_Descriptor* saneDesc,
214     SaneOptionDescriptor& saneOptDes)
215 {
216     SCAN_HILOGI("ConvertSaneDescriptor start");
217     if (saneDesc == nullptr) {
218         SCAN_HILOGE("saneDesc is a nullptr");
219         return;
220     }
221     if (saneDesc->name != nullptr) {
222         saneOptDes.optionName_ = std::string(saneDesc->name);
223     }
224     if (saneDesc->title != nullptr) {
225         saneOptDes.optionTitle_ = std::string(saneDesc->title);
226     }
227     if (saneDesc->desc != nullptr) {
228         saneOptDes.optionDesc_ = std::string(saneDesc->desc);
229     }
230     saneOptDes.optionType_ = static_cast<int32_t>(saneDesc->type);
231     saneOptDes.optionUnit_ = static_cast<int32_t>(saneDesc->unit);
232     saneOptDes.optionSize_ = saneDesc->size;
233     saneOptDes.optionCap_ = saneDesc->cap;
234     saneOptDes.optionConstraintType_ = static_cast<int32_t>(saneDesc->constraint_type);
235     if (saneDesc->constraint_type == ::SANE_CONSTRAINT_RANGE && saneDesc->constraint.range != nullptr) {
236         saneOptDes.minValue_ = saneDesc->constraint.range->min;
237         saneOptDes.maxValue_ = saneDesc->constraint.range->max;
238         saneOptDes.quantValue_ = saneDesc->constraint.range->quant;
239     } else if (saneDesc->constraint_type == ::SANE_CONSTRAINT_WORD_LIST
240         && saneDesc->constraint.word_list != nullptr) {
241         saneOptDes.optionConstraintNumber_.clear();
242         int32_t sizeNumber = saneDesc->constraint.word_list[0];
243         for (int32_t i = 0; i < sizeNumber; i++) {
244             SCAN_HILOGD("SANE_CONSTRAINT_WORD_LIST: %{public}d", saneDesc->constraint.word_list[i]);
245             saneOptDes.optionConstraintNumber_.push_back(saneDesc->constraint.word_list[i]);
246         }
247     } else if (saneDesc->constraint_type == ::SANE_CONSTRAINT_STRING_LIST
248         && saneDesc->constraint.string_list != nullptr) {
249         for (int32_t i = 0; saneDesc->constraint.string_list[i] != nullptr; i++) {
250             SCAN_HILOGD("SANE_CONSTRAINT_STRING_LIST: %{public}s", saneDesc->constraint.string_list[i]);
251             saneOptDes.optionConstraintString_.push_back(std::string(saneDesc->constraint.string_list[i]));
252         }
253         saneOptDes.optionConstraintString_.push_back("null");
254     }
255     SCAN_HILOGI("ConvertSaneDescriptor end");
256 }
257 
SaneGetParameters(const std::string & scannerId,SaneParameters & spm,int32_t & status)258 ErrCode SaneServerManager::SaneGetParameters(const std::string& scannerId, SaneParameters& spm, int32_t& status)
259 {
260     SCAN_HILOGI("SaneGetParameters start");
261     if (!CheckPermission()) {
262         SCAN_HILOGE("no permission to access sane_service");
263         return SANE_STATUS_NO_PERMISSION;
264     }
265     SANE_Handle handle = GetScanHandle(scannerId);
266     if (handle == nullptr) {
267         SCAN_HILOGE("handle is a nullptr");
268         status = SANE_STATUS_INVAL;
269         return ERR_OK;
270     }
271     SANE_Parameters params;
272     SANE_Status saneStatus = sane_get_parameters(handle, &params);
273     if (saneStatus != ::SANE_STATUS_GOOD) {
274         status = static_cast<int32_t>(saneStatus);
275         SCAN_HILOGE("sane_get_parameters error, ret = [%{public}d]", status);
276         return ERR_OK;
277     }
278     spm.format_ = static_cast<SaneFrame>(params.format);
279     spm.lastFrame_ = params.last_frame;
280     spm.bytesPerLine_ = params.bytes_per_line;
281     spm.pixelsPerLine_ = params.pixels_per_line;
282     spm.lines_ = params.lines;
283     spm.depth_ = params.depth;
284     status = SANE_STATUS_GOOD;
285     SCAN_HILOGI("SaneGetParameters end");
286     return ERR_OK;
287 }
288 
SaneGetDevices(std::vector<SaneDevice> & deviceInfos,int32_t & status)289 ErrCode SaneServerManager::SaneGetDevices(std::vector<SaneDevice>& deviceInfos, int32_t& status)
290 {
291     SCAN_HILOGI("SaneGetDevices start");
292     if (!CheckPermission()) {
293         SCAN_HILOGE("no permission to access sane_service");
294         return SANE_STATUS_NO_PERMISSION;
295     }
296     const SANE_Device **deviceList = nullptr;
297     SANE_Status saneStatus = sane_get_devices(&deviceList, SANE_FALSE);
298     if (saneStatus != ::SANE_STATUS_GOOD) {
299         status = static_cast<int32_t>(saneStatus);
300         SCAN_HILOGE("sane_get_devices error, ret = [%{public}d]", status);
301         return ERR_OK;
302     }
303     for (int32_t i = 0; deviceList[i] != nullptr; i++) {
304         SaneDevice device;
305         if (deviceList[i]->name != nullptr) {
306             device.name_ = std::string(deviceList[i]->name);
307         }
308         if (deviceList[i]->vendor != nullptr) {
309             device.vendor_ = std::string(deviceList[i]->vendor);
310         }
311         if (deviceList[i]->model != nullptr) {
312             device.model_ = std::string(deviceList[i]->model);
313         }
314         if (deviceList[i]->type != nullptr) {
315             device.type_ = std::string(deviceList[i]->type);
316         }
317         deviceInfos.push_back(device);
318     }
319     status = SANE_STATUS_GOOD;
320     SCAN_HILOGI("SaneGetDevices end");
321     return ERR_OK;
322 }
323 
SaneControlOption(const std::string & scannerId,const SaneControlParam & controlParam,SaneOutParam & outParam,int32_t & status)324 ErrCode SaneServerManager::SaneControlOption(const std::string& scannerId, const SaneControlParam& controlParam,
325     SaneOutParam& outParam, int32_t& status)
326 {
327     SCAN_HILOGI("SaneControlOption start");
328     if (!CheckPermission()) {
329         SCAN_HILOGE("no permission to access sane_service");
330         return SANE_STATUS_NO_PERMISSION;
331     }
332     SANE_Handle handle = GetScanHandle(scannerId);
333     if (handle == nullptr) {
334         SCAN_HILOGE("handle is a nullptr");
335         status = SANE_STATUS_INVAL;
336         return ERR_OK;
337     }
338     SANE_Int option = controlParam.option_;
339     SANE_Action action = static_cast<SANE_Action>(controlParam.action_);
340     if (controlParam.action_ == SANE_ACTION_SET_AUTO) {
341         SANE_Status saneStatus = sane_control_option(handle, option, action, nullptr, nullptr);
342         if (saneStatus != ::SANE_STATUS_GOOD) {
343             status = static_cast<int32_t>(saneStatus);
344             SCAN_HILOGE("sane_control_option error, ret = [%{public}d]", status);
345             return ERR_OK;
346         }
347     } else if (controlParam.action_ == SANE_ACTION_GET_VALUE) {
348         SaneStatus saneStatus = GetControlOption(handle, controlParam, outParam);
349         if (saneStatus != SANE_STATUS_GOOD) {
350             status = static_cast<int32_t>(saneStatus);
351             SCAN_HILOGE("Get sane_control_option error, ret = [%{public}d]", status);
352             return ERR_OK;
353         }
354     } else if (controlParam.action_ == SANE_ACTION_SET_VALUE) {
355         SaneStatus saneStatus = SetControlOption(handle, controlParam, outParam);
356         if (saneStatus != SANE_STATUS_GOOD) {
357             status = static_cast<int32_t>(saneStatus);
358             SCAN_HILOGE("Set sane_control_option error, ret = [%{public}d]", status);
359             return ERR_OK;
360         }
361     } else {
362         status = SANE_STATUS_INVAL;
363         SCAN_HILOGE("action is invalid, action = [%{public}u]", controlParam.action_);
364         return ERR_OK;
365     }
366     SCAN_HILOGI("SaneControlOption end");
367     return ERR_OK;
368 }
369 
GetControlOption(SANE_Handle & handle,const SaneControlParam & controlParam,SaneOutParam & outParam)370 SaneStatus SaneServerManager::GetControlOption(SANE_Handle& handle,
371     const SaneControlParam& controlParam, SaneOutParam& outParam)
372 {
373     if (handle == nullptr) {
374         SCAN_HILOGE("handle is a nullptr");
375         return SANE_STATUS_INVAL;
376     }
377     SANE_Int option = controlParam.option_;
378     int32_t valueType = controlParam.valueType_;
379     SANE_Status saneStatus = ::SANE_STATUS_GOOD;
380     SCAN_HILOGD("valueSize_ = [%{public}d], valueType = [%{public}u]", controlParam.valueSize_, valueType);
381     if (valueType == SCAN_VALUE_NUM) {
382         int32_t value = 0;
383         saneStatus = sane_control_option(handle, option, ::SANE_ACTION_GET_VALUE, &value, nullptr);
384         outParam.valueNumber_ = value;
385     } else if (valueType == SCAN_VALUE_STR) {
386         std::string value;
387         value.resize(controlParam.valueSize_ + 1);
388         saneStatus = sane_control_option(handle, option, ::SANE_ACTION_GET_VALUE, &value.front(), nullptr);
389         outParam.valueStr_ = value;
390     } else if (valueType == SCAN_VALUE_BOOL) {
391         int32_t value = 0;
392         saneStatus = sane_control_option(handle, option, ::SANE_ACTION_GET_VALUE, &value, nullptr);
393         outParam.valueBool_ = value > 0 ? true : false;
394     }
395     if (saneStatus != ::SANE_STATUS_GOOD) {
396         SCAN_HILOGE("Get sane_control_option error, ret = [%{public}u]", saneStatus);
397         return static_cast<SaneStatus>(saneStatus);
398     }
399     return SANE_STATUS_GOOD;
400 }
401 
SetControlOption(SANE_Handle & handle,const SaneControlParam & controlParam,SaneOutParam & outParam)402 SaneStatus SaneServerManager::SetControlOption(SANE_Handle& handle,
403     const SaneControlParam& controlParam, SaneOutParam& outParam)
404 {
405     if (handle == nullptr) {
406         SCAN_HILOGE("handle is a nullptr");
407         return SANE_STATUS_INVAL;
408     }
409     SANE_Int option = controlParam.option_;
410     SANE_Action action = static_cast<SANE_Action>(controlParam.action_);
411     SANE_Int& info = outParam.info_;
412     int32_t valueType = controlParam.valueType_;
413     SCAN_HILOGD("SetControlOption, valueType = [%{public}d]", valueType);
414     SANE_Status saneStatus = ::SANE_STATUS_GOOD;
415     if (valueType == SCAN_VALUE_NUM) {
416         int32_t value = controlParam.valueNumber_;
417         saneStatus = sane_control_option(handle, option, action, &value, &info);
418     } else if (valueType == SCAN_VALUE_STR) {
419         std::string value = controlParam.valueStr_;
420         saneStatus = sane_control_option(handle, option, action, const_cast<char*>(&value.front()), &info);
421     }
422     if (saneStatus != ::SANE_STATUS_GOOD) {
423         SCAN_HILOGE("Set sane_control_option error, ret = [%{public}u]", saneStatus);
424         return static_cast<SaneStatus>(saneStatus);
425     }
426     return SANE_STATUS_GOOD;
427 }
428 
SaneRead(const std::string & scannerId,const int32_t buflen,SanePictureData & pictureData,int32_t & status)429 ErrCode SaneServerManager::SaneRead(const std::string& scannerId,
430     const int32_t buflen, SanePictureData& pictureData, int32_t& status)
431 {
432     SCAN_HILOGI("SaneRead start");
433     if (!CheckPermission()) {
434         SCAN_HILOGE("no permission to access sane_service");
435         return SANE_STATUS_NO_PERMISSION;
436     }
437     if (buflen < 0 || buflen > MAX_BUFLEN) {
438         SCAN_HILOGE("invalid buflen, buflen = %{public}d", buflen);
439         status = SANE_STATUS_INVAL;
440         return ERR_OK;
441     }
442     SANE_Handle handle = GetScanHandle(scannerId);
443     if (handle == nullptr) {
444         SCAN_HILOGE("handle is a nullptr");
445         status = SANE_STATUS_INVAL;
446         return ERR_OK;
447     }
448     constexpr int32_t zero = 0;
449     SANE_Int curReadSize = zero;
450     std::vector<SANE_Byte> valueBuffer(buflen);
451     SANE_Status saneStatus = ::SANE_STATUS_GOOD;
452     do {
453         saneStatus = sane_read(handle, valueBuffer.data(), buflen, &curReadSize);
454     } while (saneStatus == ::SANE_STATUS_GOOD && curReadSize == zero);
455     status = static_cast<int32_t>(saneStatus);
456     if (saneStatus != ::SANE_STATUS_GOOD && saneStatus != ::SANE_STATUS_EOF) {
457         SCAN_HILOGE("sane_read error, ret = [%{public}d]", status);
458         pictureData.ret_ = SANE_READ_FAIL;
459         return ERR_OK;
460     }
461     if (curReadSize > 0) {
462         valueBuffer.resize(curReadSize);
463     }
464     pictureData.dataBuffer_ = std::move(valueBuffer);
465     pictureData.ret_ = SANE_READ_OK;
466     SCAN_HILOGI("SaneRead end");
467     return ERR_OK;
468 }
469 
UnloadSystemAbility()470 ErrCode SaneServerManager::UnloadSystemAbility()
471 {
472     SCAN_HILOGI("UnloadSystemAbility start");
473     if (!CheckPermission()) {
474         SCAN_HILOGE("no permission to access sane_service");
475         return SANE_STATUS_NO_PERMISSION;
476     }
477     std::lock_guard<std::mutex> autoLock(scannerHandleListlock_);
478     for (const auto& scanner : scannerHandleList_) {
479         sane_cancel(scanner.second);
480         sane_close(scanner.second);
481     }
482     scannerHandleList_.clear();
483     sane_exit();
484     const std::string dataTmpDir = "/data/service/el2/public/print_service/sane/tmp";
485     std::vector<std::string> files;
486     GetDirFiles(dataTmpDir, files);
487     for (const auto& file : files) {
488         if (!RemoveFile(file)) {
489             SCAN_HILOGW("RemoveFile failed");
490         }
491     }
492     auto task = [this] () {
493         auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
494         if (samgrProxy == nullptr) {
495             SCAN_HILOGE("get samgr failed");
496             return;
497         }
498         int32_t ret = samgrProxy->UnloadSystemAbility(SANE_SERVICE_ID);
499         if (ret != ERR_OK) {
500             SCAN_HILOGE("unload sane_service failed");
501             return;
502         }
503         SCAN_HILOGI("unload sane_service successfull.");
504     };
505     std::thread unloadThead(task);
506     unloadThead.detach();
507     return ERR_OK;
508 }
509 }
510 }