1/*
2 * Copyright (c) 2024 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 "ohprint.h"
17
18#include <algorithm>
19#include <map>
20#include <memory>
21#include <mutex>
22#include <vector>
23
24#include "ability_context.h"
25#include "iprint_adapter.h"
26#include "print_attributes.h"
27#include "print_manager_client.h"
28#include "print_constant.h"
29#include "print_log.h"
30#include "ability_manager_client.h"
31#include "print_util.h"
32#include "print_callback.h"
33#include "print_converter.h"
34#include "print_helper.h"
35#include "refbase.h"
36#include "ui_extension_context.h"
37
38using namespace OHOS::Print;
39
40static Print_PrinterDiscoveryCallback printerDiscoverCallback = nullptr;
41static Print_PrinterChangeCallback printerInfoCallback = nullptr;
42
43static bool NativePrinterDiscoverFunction(uint32_t event, const PrinterInfo &info)
44{
45    PRINT_HILOGD("NativePrinterDiscoverFunction event: %{public}d, printerId: [%{public}s]",
46        event, info.GetPrinterId().c_str());
47    if (printerDiscoverCallback == nullptr) {
48        PRINT_HILOGW("printerDiscoverCallback is null");
49        return false;
50    }
51    Print_PrinterInfo *nativePrinterInfo = ConvertToNativePrinterInfo(info);
52    if (nativePrinterInfo == nullptr) {
53        PRINT_HILOGW("nativePrinterInfo is null.");
54        return false;
55    }
56    printerDiscoverCallback(static_cast<Print_DiscoveryEvent>(event), nativePrinterInfo);
57    OH_Print_ReleasePrinterInfo(nativePrinterInfo);
58    return true;
59}
60
61static bool NativePrinterInfoFunction(uint32_t event, const PrinterInfo &info)
62{
63    PRINT_HILOGD("NativePrinterInfoFunction event: [%{public}d, printerId: [%{public}s]",
64        event, info.GetPrinterId().c_str());
65    if (printerInfoCallback == nullptr) {
66        PRINT_HILOGW("printerInfoCallback is null");
67        return false;
68    }
69    Print_PrinterInfo *nativePrinterInfo = ConvertToNativePrinterInfo(info);
70    if (nativePrinterInfo == nullptr) {
71        PRINT_HILOGW("nativePrinterInfo is null.");
72        return false;
73    }
74    printerInfoCallback(static_cast<Print_PrinterEvent>(event), nativePrinterInfo);
75    OH_Print_ReleasePrinterInfo(nativePrinterInfo);
76    nativePrinterInfo = nullptr;
77    return true;
78}
79
80static OHOS::Ace::UIContent *GetUIContent(void *context)
81{
82    if (context == nullptr) {
83        PRINT_HILOGE("input context is null.");
84        return nullptr;
85    }
86
87    auto weakContext = static_cast<std::weak_ptr<OHOS::AbilityRuntime::Context>*>(context);
88    if (weakContext == nullptr) {
89        PRINT_HILOGE("cast context to weak is null.");
90        return nullptr;
91    }
92    auto sharedContext = weakContext->lock();
93    auto abilityContext =
94        OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(sharedContext);
95    if (abilityContext != nullptr) {
96        PRINT_HILOGD("get ability ui content.");
97        return abilityContext->GetUIContent();
98    }
99    auto uiExtensionContext =
100        OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::UIExtensionContext>(sharedContext);
101    if (uiExtensionContext != nullptr) {
102        PRINT_HILOGD("get ui extension ui content.");
103        return uiExtensionContext->GetUIContent();
104    }
105    PRINT_HILOGE("get ui content failed.");
106    return nullptr;
107}
108
109static Print_PrintAttributes *NewPrintAttributes(void)
110{
111    auto attributes = new (std::nothrow) Print_PrintAttributes;
112    if (attributes == nullptr) {
113        PRINT_HILOGE("OH_Print new attributes failed.");
114        return nullptr;
115    }
116    if (memset_s(attributes, sizeof(Print_PrintAttributes), 0, sizeof(Print_PrintAttributes)) != 0) {
117        PRINT_HILOGE("OH_Print attributes memset failed.");
118        delete attributes;
119        return nullptr;
120    }
121    return attributes;
122}
123
124static void ReleasePrintAttributes(Print_PrintAttributes *attr)
125{
126    if (attr == nullptr) {
127        PRINT_HILOGE("OH_Print release attr is null.");
128        return;
129    }
130    if (attr->pageRange.pagesArray != nullptr) {
131        delete [] attr->pageRange.pagesArray;
132        attr->pageRange.pagesArray = nullptr;
133    }
134    delete attr;
135}
136
137// 初始化
138Print_ErrorCode OH_Print_Init()
139{
140    int32_t ret = PrintManagerClient::GetInstance()->Init();
141    PRINT_HILOGI("OH_Print_Init ret = [%{public}d]", ret);
142    return ConvertToNativeErrorCode(ret);
143}
144
145// 反初始化
146Print_ErrorCode OH_Print_Release()
147{
148    int32_t ret = PrintManagerClient::GetInstance()->Release();
149    PRINT_HILOGI("OH_Print_Release ret = [%{public}d]", ret);
150    return ConvertToNativeErrorCode(ret);
151}
152
153Print_ErrorCode OH_Print_StartPrinterDiscovery(Print_PrinterDiscoveryCallback callback)
154{
155    printerDiscoverCallback = callback;
156    std::vector<PrintExtensionInfo> extensionInfos;
157    int32_t ret = PrintManagerClient::GetInstance()->QueryAllExtension(extensionInfos);
158    PRINT_HILOGI("QueryAllExtension ret = [%{public}d]", ret);
159    if (ret == PRINT_ERROR_NONE) {
160        std::vector<std::string> extensionIds;
161        for (auto &extensionInfo : extensionInfos) {
162            extensionIds.emplace_back(extensionInfo.GetExtensionId());
163        }
164        PRINT_HILOGI("extensionIds size = [%{public}zu]", extensionIds.size());
165        PrintManagerClient::GetInstance()->SetNativePrinterChangeCallback(
166            PRINTER_DISCOVER_EVENT_TYPE, NativePrinterDiscoverFunction);
167        ret = PrintManagerClient::GetInstance()->StartDiscoverPrinter(extensionIds);
168        PRINT_HILOGI("StartDiscoverPrinter ret = [%{public}d]", ret);
169    }
170    return ConvertToNativeErrorCode(ret);
171}
172
173Print_ErrorCode OH_Print_StopPrinterDiscovery()
174{
175    PrintManagerClient::GetInstance()->SetNativePrinterChangeCallback(PRINTER_DISCOVER_EVENT_TYPE, nullptr);
176    printerDiscoverCallback = nullptr;
177    int32_t ret = PrintManagerClient::GetInstance()->StopDiscoverPrinter();
178    PRINT_HILOGI("StopDiscoverPrinter ret = [%{public}d]", ret);
179    return ConvertToNativeErrorCode(ret);
180}
181
182Print_ErrorCode OH_Print_ConnectPrinter(const char *printerId)
183{
184    if (printerId == nullptr) {
185        PRINT_HILOGW("printerId is null.");
186        return PRINT_ERROR_INVALID_PRINTER;
187    }
188    std::string nativePrinterId = printerId;
189    int32_t ret = PrintManagerClient::GetInstance()->ConnectPrinter(nativePrinterId);
190    PRINT_HILOGI("ConnectPrinter ret = [%{public}d]", ret);
191    return ConvertToNativeErrorCode(ret);
192}
193
194Print_ErrorCode OH_Print_StartPrintJob(const Print_PrintJob *printJob)
195{
196    if (printJob == nullptr) {
197        PRINT_HILOGI("printJob is null.");
198        return PRINT_ERROR_INVALID_PRINT_JOB;
199    }
200    PrintJob curPrintJob;
201    int32_t ret = ConvertNativeJobToPrintJob(*printJob, curPrintJob);
202    if (ret != 0) {
203        PRINT_HILOGW("ConvertNativeJobToPrintJob fail.");
204        return PRINT_ERROR_INVALID_PRINT_JOB;
205    }
206    ret = PrintManagerClient::GetInstance()->StartNativePrintJob(curPrintJob);
207    PRINT_HILOGI("StartNativePrintJob ret = [%{public}d]", ret);
208    return ConvertToNativeErrorCode(ret);
209}
210
211Print_ErrorCode OH_Print_RegisterPrinterChangeListener(Print_PrinterChangeCallback callback)
212{
213    printerInfoCallback = callback;
214    PrintManagerClient::GetInstance()->SetNativePrinterChangeCallback(
215        PRINTER_CHANGE_EVENT_TYPE, NativePrinterInfoFunction);
216    return PRINT_ERROR_NONE;
217}
218
219void OH_Print_UnregisterPrinterChangeListener()
220{
221    PrintManagerClient::GetInstance()->SetNativePrinterChangeCallback(PRINTER_CHANGE_EVENT_TYPE, nullptr);
222    printerInfoCallback = nullptr;
223}
224
225Print_ErrorCode OH_Print_QueryPrinterList(Print_StringList *printerIdList)
226{
227    if (printerIdList == nullptr) {
228        PRINT_HILOGW("printerIdList is null.");
229        return PRINT_ERROR_INVALID_PARAMETER;
230    }
231    std::vector<std::string> printerNameList;
232    int32_t ret = PrintManagerClient::GetInstance()->QueryAddedPrinter(printerNameList);
233    size_t count = printerNameList.size();
234    PRINT_HILOGI("OH_Print_QueryPrinterList ret = %{public}d, count = %{public}zu.", ret, count);
235    if (ret != 0 || count == 0) {
236        return PRINT_ERROR_INVALID_PRINTER;
237    }
238    printerIdList->list = new (std::nothrow) char *[count];
239    if (printerIdList->list == nullptr) {
240        PRINT_HILOGW("printerIdList->list is null");
241        return PRINT_ERROR_GENERIC_FAILURE;
242    }
243    if (memset_s(printerIdList->list, count * sizeof(char *), 0, count * sizeof(char *)) != 0) {
244        delete[] printerIdList->list;
245        printerIdList->list = nullptr;
246        PRINT_HILOGW("memset_s fail");
247        return PRINT_ERROR_GENERIC_FAILURE;
248    }
249    for (size_t i = 0; i < count; ++i) {
250        printerIdList->list[i] = CopyString(printerNameList[i]);
251    }
252    printerIdList->count = count;
253    return PRINT_ERROR_NONE;
254}
255
256void OH_Print_ReleasePrinterList(Print_StringList *printerIdList)
257{
258    if (printerIdList == nullptr) {
259        PRINT_HILOGW("printerIdList is null.");
260        return;
261    }
262    if (printerIdList->list != nullptr) {
263        for (uint32_t i = 0; i < printerIdList->count; i++) {
264            SAFE_DELETE_ARRAY(printerIdList->list[i]);
265        }
266        SAFE_DELETE_ARRAY(printerIdList->list);
267    }
268    printerIdList->count = 0;
269}
270
271Print_ErrorCode OH_Print_QueryPrinterInfo(const char *printerId, Print_PrinterInfo **printerInfo)
272{
273    if (printerId == nullptr || printerInfo == nullptr) {
274        PRINT_HILOGW("Invalid parameter.");
275        return PRINT_ERROR_INVALID_PARAMETER;
276    }
277    std::string id(printerId);
278    PrinterInfo info;
279    int32_t ret = PrintManagerClient::GetInstance()->QueryPrinterInfoByPrinterId(id, info);
280    PRINT_HILOGI("QueryPrinterInfoByPrinterId ret = %{public}d", ret);
281    if (info.GetPrinterId() != id || info.GetPrinterName().empty()) {
282        PRINT_HILOGI("QueryPrinterInfoByPrinterId invalid printer");
283        return PRINT_ERROR_INVALID_PRINTER;
284    }
285    Print_PrinterInfo *nativePrinterInfo = ConvertToNativePrinterInfo(info);
286    if (nativePrinterInfo != nullptr) {
287        if (ret != 0) {
288            nativePrinterInfo->printerState = PRINTER_UNAVAILABLE;
289        }
290        *printerInfo = nativePrinterInfo;
291    }
292    return ConvertToNativeErrorCode(ret);
293}
294
295void OH_Print_ReleasePrinterInfo(Print_PrinterInfo *printerInfo)
296{
297    if (printerInfo == nullptr) {
298        PRINT_HILOGW("printerInfo is null.");
299        return;
300    }
301    ReleasePrinterInfo(*printerInfo);
302    delete printerInfo;
303    printerInfo = nullptr;
304}
305
306Print_ErrorCode OH_Print_LaunchPrinterManager()
307{
308    PRINT_HILOGW("Ability context is needed to start ability");
309    return PRINT_ERROR_GENERIC_FAILURE;
310}
311
312Print_ErrorCode OH_Print_QueryPrinterProperties(
313    const char *printerId, const Print_StringList *propertyKeyList, Print_PropertyList *propertyList)
314{
315    if (printerId == nullptr || propertyKeyList == nullptr || propertyKeyList->list == nullptr ||
316        propertyList == nullptr) {
317        PRINT_HILOGW("OH_Print_QueryPrinterProperties invalid parameter.");
318        return PRINT_ERROR_INVALID_PRINTER;
319    }
320    std::vector<std::string> keyList;
321    for (uint32_t i = 0; i < propertyKeyList->count; i++) {
322        if (propertyKeyList->list[i] == nullptr) {
323            continue;
324        }
325        std::string key(propertyKeyList->list[i]);
326        if (key.empty()) {
327            continue;
328        }
329        keyList.emplace_back(key);
330    }
331    if (keyList.size() == 0) {
332        PRINT_HILOGW("empty keyList");
333        return PRINT_ERROR_INVALID_PARAMETER;
334    }
335    std::vector<std::string> valueList;
336    int32_t ret = PrintManagerClient::GetInstance()->QueryPrinterProperties(printerId, keyList, valueList);
337    PRINT_HILOGI("QueryPrinterProperties ret = %{public}d", ret);
338    if (ret != 0) {
339        PRINT_HILOGW("QueryPrinterProperties fail");
340        return PRINT_ERROR_INVALID_PRINTER;
341    }
342    return ConvertStringVectorToPropertyList(valueList, propertyList);
343}
344
345void OH_Print_ReleasePrinterProperties(Print_PropertyList *propertyList)
346{
347    if (propertyList == nullptr) {
348        PRINT_HILOGW("propertyList is null");
349        return;
350    }
351    if (propertyList->list != nullptr) {
352        for (uint32_t i = 0; i < propertyList->count; ++i) {
353            SAFE_DELETE_ARRAY(propertyList->list[i].key);
354            SAFE_DELETE_ARRAY(propertyList->list[i].value);
355        }
356        SAFE_DELETE_ARRAY(propertyList->list);
357    }
358    propertyList->count = 0;
359}
360
361Print_ErrorCode OH_Print_UpdatePrinterProperties(const char *printerId, const Print_PropertyList *propertyList)
362{
363    if (printerId == nullptr || propertyList->list == nullptr || propertyList->count <= 0) {
364        PRINT_HILOGW("OH_Print_UpdatePrinterProperties invalid parameter.");
365        return PRINT_ERROR_INVALID_PRINTER;
366    }
367    nlohmann::json settingJson;
368    for (uint32_t i = 0; i < propertyList->count; i++) {
369        settingJson[propertyList->list[i].key] = propertyList->list[i].value;
370    }
371    PRINT_HILOGW("OH_Print_UpdatePrinterProperties setting : %{public}s.", settingJson.dump().c_str());
372    int32_t ret = PrintManagerClient::GetInstance()->SetPrinterPreference(printerId, settingJson.dump());
373    if (ret != 0) {
374        PRINT_HILOGW("SetPrinterPreference fail");
375        return PRINT_ERROR_INVALID_PRINTER;
376    }
377    return PRINT_ERROR_NONE;
378}
379
380Print_ErrorCode OH_Print_RestorePrinterProperties(const char *printerId, const Print_StringList *propertyKeyList)
381{
382    return PRINT_ERROR_NONE;
383}
384
385namespace {
386class PrintDocumentAdapterWrapper : public PrintDocumentAdapter {
387public:
388    explicit PrintDocumentAdapterWrapper(Print_PrintDocCallback PrintCallback);
389    void onStartLayoutWrite(const std::string &jobId,
390                            const PrintAttributes &oldAttrs,
391                            const PrintAttributes &newAttrs,
392                            uint32_t fd,
393                            std::function<void(std::string, uint32_t)> writeResultCallback) override;
394    void onJobStateChanged(const std::string &jobId, uint32_t state) override;
395    void OnWriteResultCallback(const std::string &jobId, uint32_t code);
396    static void WriteResultCallback(const char *jobId, uint32_t code);
397
398private:
399    Print_PrintAttributes *BuildPrintAttributes(const PrintAttributes &attrs);
400
401    Print_PrintDocCallback printCb_;
402    std::function<void(std::string, uint32_t)> writeResultCb_;
403    static std::mutex printDocMutex_;
404    static std::map<std::string, PrintDocumentAdapterWrapper*> printDocAdapterMap_;
405};
406
407std::mutex PrintDocumentAdapterWrapper::printDocMutex_;
408std::map<std::string, PrintDocumentAdapterWrapper*> PrintDocumentAdapterWrapper::printDocAdapterMap_;
409
410PrintDocumentAdapterWrapper::PrintDocumentAdapterWrapper(Print_PrintDocCallback PrintCallback)
411{
412    printCb_ = PrintCallback;
413}
414
415void PrintDocumentAdapterWrapper::onStartLayoutWrite(const std::string &jobId,
416                                                     const PrintAttributes &oldAttrs,
417                                                     const PrintAttributes &newAttrs,
418                                                     uint32_t fd,
419                                                     std::function<void(std::string, uint32_t)> writeResultCallback)
420{
421    if (printCb_.startLayoutWriteCb == nullptr) {
422        PRINT_HILOGE("OH_Print start layout callback is null.");
423        return;
424    }
425    {
426        std::lock_guard<std::mutex> lock(printDocMutex_);
427        if (printDocAdapterMap_.find(jobId) == printDocAdapterMap_.end()) {
428            printDocAdapterMap_.insert({ jobId, this });
429        }
430    }
431    writeResultCb_ = writeResultCallback;
432    auto oldAttrsPtr = BuildPrintAttributes(oldAttrs);
433    auto newAttrsPtr = BuildPrintAttributes(newAttrs);
434    printCb_.startLayoutWriteCb(jobId.c_str(),
435                                fd,
436                                oldAttrsPtr,
437                                newAttrsPtr,
438                                PrintDocumentAdapterWrapper::WriteResultCallback);
439    ReleasePrintAttributes(oldAttrsPtr);
440    ReleasePrintAttributes(newAttrsPtr);
441    oldAttrsPtr = nullptr;
442    newAttrsPtr = nullptr;
443}
444
445void PrintDocumentAdapterWrapper::onJobStateChanged(const std::string &jobId, uint32_t state)
446{
447    if (printCb_.jobStateChangedCb == nullptr) {
448        PRINT_HILOGE("OH_Print job state callback is null.");
449        return;
450    }
451    if (state == PRINT_DOC_ADAPTER_PREVIEW_ABILITY_DESTROY_FOR_CANCELED
452        || state == PRINT_DOC_ADAPTER_PREVIEW_ABILITY_DESTROY_FOR_STARTED) {
453        std::lock_guard<std::mutex> lock(printDocMutex_);
454        printDocAdapterMap_.erase(jobId);
455    }
456    printCb_.jobStateChangedCb(jobId.c_str(), state);
457}
458
459void PrintDocumentAdapterWrapper::WriteResultCallback(const char *jobId, uint32_t code)
460{
461    if (jobId == nullptr) {
462        PRINT_HILOGE("OH_Print write result callback param is null.");
463        return;
464    }
465    std::string jobIdStr = jobId;
466    PrintDocumentAdapterWrapper* wrapper = nullptr;
467    {
468        std::lock_guard<std::mutex> lock(printDocMutex_);
469        auto iter = printDocAdapterMap_.find(jobId);
470        if (iter != printDocAdapterMap_.end()) {
471            wrapper = iter->second;
472        }
473    }
474    if (wrapper == nullptr) {
475        PRINT_HILOGE("OH_Print get wrapper failed.");
476        return;
477    }
478    wrapper->OnWriteResultCallback(jobIdStr, code);
479}
480
481void PrintDocumentAdapterWrapper::OnWriteResultCallback(const std::string &jobId, uint32_t code)
482{
483    if (writeResultCb_ == nullptr) {
484        PRINT_HILOGE("OH_Print write callback is null.");
485        return;
486    }
487    writeResultCb_(jobId, code);
488}
489
490Print_PrintAttributes *PrintDocumentAdapterWrapper::BuildPrintAttributes(const PrintAttributes &attrs)
491{
492    auto attributesRaw = NewPrintAttributes();
493    if (attributesRaw == nullptr) {
494        PRINT_HILOGE("OH_Print attribute raw is null.");
495        return nullptr;
496    }
497    std::unique_ptr<Print_PrintAttributes> attributes(attributesRaw);
498    attributes->copyNumber = attrs.GetCopyNumber();
499    Print_Range printRange;
500    PrintRange range;
501    attrs.GetPageRange(range);
502    printRange.startPage = range.GetStartPage();
503    printRange.endPage = range.GetEndPage();
504    std::vector<uint32_t> pages;
505    range.GetPages(pages);
506    auto pageArray = new (std::nothrow) uint32_t[pages.size()];
507    if (pageArray == nullptr) {
508        PRINT_HILOGE("OH_Print pages array is null.");
509        return nullptr;
510    }
511    std::copy(pages.begin(), pages.end(), pageArray);
512    printRange.pagesArray = pageArray;
513    printRange.pagesArrayLen = pages.size();
514    attributes->pageRange = printRange;
515    attributes->isSequential = attrs.GetIsSequential();
516    Print_PageSize printPageSize;
517    PrintPageSize pageSize;
518    attrs.GetPageSize(pageSize);
519    printPageSize.width = pageSize.GetWidth();
520    printPageSize.height = pageSize.GetHeight();
521    attributes->pageSize = printPageSize;
522    attributes->isLandscape = attrs.GetIsLandscape();
523    attributes->colorMode = attrs.GetColorMode();
524    attributes->duplexMode = attrs.GetDuplexMode();
525    Print_Margin printMargin;
526    PrintMargin margin;
527    attrs.GetMargin(margin);
528    printMargin.topMargin = margin.GetTop();
529    printMargin.bottomMargin = margin.GetBottom();
530    printMargin.leftMargin = margin.GetLeft();
531    printMargin.rightMargin = margin.GetRight();
532    attributes->pageMargin = printMargin;
533    return attributes.release();
534}
535}
536
537Print_ErrorCode OH_Print_StartPrintByNative(const char *printJobName,
538                                            Print_PrintDocCallback printDocCallback,
539                                            void *context)
540{
541    if (printJobName == nullptr) {
542        PRINT_HILOGE("OH_Print start print native print job name is null.");
543        return PRINT_ERROR_INVALID_PARAMETER;
544    }
545
546    auto uiContent = GetUIContent(context);
547    if (uiContent == nullptr) {
548        PRINT_HILOGE("OH_Print start print native ui content is null.");
549        return PRINT_ERROR_INVALID_PARAMETER;
550    }
551    auto wrapper = new (std::nothrow) PrintDocumentAdapterWrapper(printDocCallback);
552    if (wrapper == nullptr) {
553        PRINT_HILOGE("OH_Print start print print doc adapter is null.");
554        return PRINT_ERROR_GENERIC_FAILURE;
555    }
556    OHOS::sptr<IPrintCallback> printCb = new (std::nothrow) PrintCallback(wrapper);
557    if (printCb == nullptr) {
558        PRINT_HILOGE("OH_Print start print print callback is null.");
559        delete wrapper;
560        return PRINT_ERROR_GENERIC_FAILURE;
561    }
562    auto attributes = std::make_shared<PrintAttributes>();
563    std::string printJobNameStr = printJobName;
564    int32_t ret =
565        PrintManagerClient::GetInstance()->Print(printJobNameStr, printCb, attributes, uiContent);
566    if (ret != PRINT_ERROR_NONE) {
567        PRINT_HILOGE("OH_Print start print start failed, error code : %{public}d.", ret);
568        return ConvertToNativeErrorCode(ret);
569    }
570    return PRINT_ERROR_NONE;
571}
572