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