• 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 = 1; 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     }
254     SCAN_HILOGI("ConvertSaneDescriptor end");
255 }
256 
SaneGetParameters(const std::string & scannerId,SaneParameters & spm,int32_t & status)257 ErrCode SaneServerManager::SaneGetParameters(const std::string& scannerId, SaneParameters& spm, int32_t& status)
258 {
259     SCAN_HILOGI("SaneGetParameters start");
260     if (!CheckPermission()) {
261         SCAN_HILOGE("no permission to access sane_service");
262         return SANE_STATUS_NO_PERMISSION;
263     }
264     SANE_Handle handle = GetScanHandle(scannerId);
265     if (handle == nullptr) {
266         SCAN_HILOGE("handle is a nullptr");
267         status = SANE_STATUS_INVAL;
268         return ERR_OK;
269     }
270     SANE_Parameters params;
271     SANE_Status saneStatus = sane_get_parameters(handle, &params);
272     if (saneStatus != ::SANE_STATUS_GOOD) {
273         status = static_cast<int32_t>(saneStatus);
274         SCAN_HILOGE("sane_get_parameters error, ret = [%{public}d]", status);
275         return ERR_OK;
276     }
277     spm.format_ = static_cast<SaneFrame>(params.format);
278     spm.lastFrame_ = params.last_frame;
279     spm.bytesPerLine_ = params.bytes_per_line;
280     spm.pixelsPerLine_ = params.pixels_per_line;
281     spm.lines_ = params.lines;
282     spm.depth_ = params.depth;
283     status = SANE_STATUS_GOOD;
284     SCAN_HILOGI("SaneGetParameters end");
285     return ERR_OK;
286 }
287 
SaneGetDevices(std::vector<SaneDevice> & deviceInfos,int32_t & status)288 ErrCode SaneServerManager::SaneGetDevices(std::vector<SaneDevice>& deviceInfos, int32_t& status)
289 {
290     SCAN_HILOGI("SaneGetDevices start");
291     if (!CheckPermission()) {
292         SCAN_HILOGE("no permission to access sane_service");
293         return SANE_STATUS_NO_PERMISSION;
294     }
295     const SANE_Device **deviceList = nullptr;
296     SANE_Status saneStatus = sane_get_devices(&deviceList, SANE_FALSE);
297     if (saneStatus != ::SANE_STATUS_GOOD) {
298         status = static_cast<int32_t>(saneStatus);
299         SCAN_HILOGE("sane_get_devices error, ret = [%{public}d]", status);
300         return ERR_OK;
301     }
302     for (int32_t i = 0; deviceList[i] != nullptr; i++) {
303         SaneDevice device;
304         if (deviceList[i]->name != nullptr) {
305             device.name_ = std::string(deviceList[i]->name);
306         }
307         if (deviceList[i]->vendor != nullptr) {
308             device.vendor_ = std::string(deviceList[i]->vendor);
309         }
310         if (deviceList[i]->model != nullptr) {
311             device.model_ = std::string(deviceList[i]->model);
312         }
313         if (deviceList[i]->type != nullptr) {
314             device.type_ = std::string(deviceList[i]->type);
315         }
316         device.Dump();
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("valueType = [%{public}d], option = [%{public}d], action = [%{public}u]",
414         valueType, option, action);
415     SANE_Status saneStatus = ::SANE_STATUS_GOOD;
416     if (valueType == SCAN_VALUE_STR) {
417         std::string value = controlParam.valueStr_;
418         saneStatus = sane_control_option(handle, option, action, const_cast<char*>(&value.front()), &info);
419         SCAN_HILOGD("SetControlOption, value = [%{public}s]", value.c_str());
420     } else {
421         int32_t value = controlParam.valueNumber_;
422         saneStatus = sane_control_option(handle, option, action, &value, &info);
423         SCAN_HILOGD("SetControlOption, value = [%{public}d]", value);
424     }
425     if (saneStatus != ::SANE_STATUS_GOOD) {
426         SCAN_HILOGE("Set sane_control_option error, ret = [%{public}u]", saneStatus);
427         return static_cast<SaneStatus>(saneStatus);
428     }
429     return SANE_STATUS_GOOD;
430 }
431 
SaneRead(const std::string & scannerId,const int32_t buflen,SanePictureData & pictureData,int32_t & status)432 ErrCode SaneServerManager::SaneRead(const std::string& scannerId,
433     const int32_t buflen, SanePictureData& pictureData, int32_t& status)
434 {
435     SCAN_HILOGI("SaneRead start");
436     if (!CheckPermission()) {
437         SCAN_HILOGE("no permission to access sane_service");
438         return SANE_STATUS_NO_PERMISSION;
439     }
440     if (buflen < 0 || buflen > MAX_BUFLEN) {
441         SCAN_HILOGE("invalid buflen, buflen = %{public}d", buflen);
442         status = SANE_STATUS_INVAL;
443         return ERR_OK;
444     }
445     SANE_Handle handle = GetScanHandle(scannerId);
446     if (handle == nullptr) {
447         SCAN_HILOGE("handle is a nullptr");
448         status = SANE_STATUS_INVAL;
449         return ERR_OK;
450     }
451     constexpr int32_t zero = 0;
452     SANE_Int curReadSize = zero;
453     std::vector<SANE_Byte> valueBuffer(buflen);
454     SANE_Status saneStatus = ::SANE_STATUS_GOOD;
455     do {
456         saneStatus = sane_read(handle, valueBuffer.data(), buflen, &curReadSize);
457     } while (saneStatus == ::SANE_STATUS_GOOD && curReadSize == zero);
458     status = static_cast<int32_t>(saneStatus);
459     if (saneStatus != ::SANE_STATUS_GOOD && saneStatus != ::SANE_STATUS_EOF) {
460         SCAN_HILOGE("sane_read error, ret = [%{public}d]", status);
461         pictureData.ret_ = SANE_READ_FAIL;
462         return ERR_OK;
463     }
464     if (curReadSize > 0) {
465         valueBuffer.resize(curReadSize);
466     }
467     pictureData.dataBuffer_ = std::move(valueBuffer);
468     pictureData.ret_ = SANE_READ_OK;
469     SCAN_HILOGI("SaneRead end");
470     return ERR_OK;
471 }
472 
UnloadSystemAbility()473 ErrCode SaneServerManager::UnloadSystemAbility()
474 {
475     SCAN_HILOGI("UnloadSystemAbility start");
476     if (!CheckPermission()) {
477         SCAN_HILOGE("no permission to access sane_service");
478         return SANE_STATUS_NO_PERMISSION;
479     }
480     std::lock_guard<std::mutex> autoLock(scannerHandleListlock_);
481     for (const auto& scanner : scannerHandleList_) {
482         sane_cancel(scanner.second);
483         sane_close(scanner.second);
484     }
485     scannerHandleList_.clear();
486     sane_exit();
487     const std::string dataTmpDir = "/data/service/el2/public/print_service/sane/tmp";
488     std::vector<std::string> files;
489     GetDirFiles(dataTmpDir, files);
490     for (const auto& file : files) {
491         if (!RemoveFile(file)) {
492             SCAN_HILOGW("RemoveFile failed");
493         }
494     }
495     auto task = [this] () {
496         auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
497         if (samgrProxy == nullptr) {
498             SCAN_HILOGE("get samgr failed");
499             return;
500         }
501         int32_t ret = samgrProxy->UnloadSystemAbility(SANE_SERVICE_ID);
502         if (ret != ERR_OK) {
503             SCAN_HILOGE("unload sane_service failed");
504             return;
505         }
506         SCAN_HILOGI("unload sane_service successfull.");
507     };
508     std::thread unloadThead(task);
509     unloadThead.detach();
510     return ERR_OK;
511 }
512 }
513 }