1 /*
2  * Copyright (c) 2021 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 "ic_sdk_impl.h"
17 
18 #include <algorithm>
19 
20 #include "aie_guard.h"
21 #include "aie_retcode_inner.h"
22 #include "encdec_facade.h"
23 #include "i_aie_client.inl"
24 #include "ic_retcode.h"
25 #include "plugin_helper.h"
26 
27 using namespace OHOS::AI;
28 namespace {
29     const uint32_t MAX_IPC_BUFFER_SIZE = 25600;
30 }
31 
32 IMPLEMENT_SINGLE_INSTANCE(IcSdkImpl);
33 
34 IcSdkImpl::IcSdkImpl() = default;
35 
36 IcSdkImpl::~IcSdkImpl() = default;
37 
Create()38 int32_t IcSdkImpl::Create()
39 {
40     HILOGI("[IcSdkImpl]Start");
41     if (icHandle_ != INVALID_IC_HANDLE) {
42         HILOGE("[IcSdkImpl]Do not create again");
43         return IC_RETCODE_INIT_ERROR;
44     }
45     int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
46     if (retCode != RETCODE_SUCCESS) {
47         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_INIT_ERROR))
48                                : HILOGD("[IcSdkImpl]No callback");
49         HILOGE("[IcSdkImpl]AieClientInit failed. Error code[%d]", retCode);
50         return IC_RETCODE_INIT_ERROR;
51     }
52     if (clientInfo_.clientId == INVALID_CLIENT_ID) {
53         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_INIT_ERROR))
54                                : HILOGD("[IcSdkImpl]No callback");
55         HILOGE("[IcSdkImpl]Fail to allocate client id");
56         return IC_RETCODE_INIT_ERROR;
57     }
58     DataInfo inputInfo = {.data = nullptr, .length = 0};
59     DataInfo outputInfo = {.data = nullptr, .length = 0};
60     retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
61     if (retCode != RETCODE_SUCCESS) {
62         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_INIT_ERROR))
63                                : HILOGD("[IcSdkImpl]No callback");
64         HILOGE("[IcSdkImpl]AieClientPrepare failed. Error code[%d]", retCode);
65         return IC_RETCODE_INIT_ERROR;
66     }
67     if (outputInfo.data == nullptr || outputInfo.length <= 0) {
68         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_INIT_ERROR))
69                                : HILOGD("[IcSdkImpl]No callback");
70         HILOGE("[IcSdkImpl]The data or length of output info is invalid");
71         return IC_RETCODE_INIT_ERROR;
72     }
73     MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
74     retCode = EncdecFacade::ProcessDecode(outputInfo, icHandle_);
75     if (retCode != RETCODE_SUCCESS) {
76         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_UNSERIALIZATION_ERROR))
77                                : HILOGD("[IcSdkImpl]No callback");
78         HILOGE("[IcSdkImpl]Failed to UnSerializeHandle");
79         return IC_RETCODE_UNSERIALIZATION_ERROR;
80     }
81     return IC_RETCODE_SUCCESS;
82 }
83 
OnSyncExecute(const IcInput & inputData,DataInfo & outputInfo)84 int32_t IcSdkImpl::OnSyncExecute(const IcInput &inputData, DataInfo &outputInfo)
85 {
86     if (inputData.data == nullptr || inputData.size == 0) {
87         HILOGE("[IcSdkImpl]Empty input");
88         return IC_RETCODE_NULL_PARAM;
89     }
90     DataInfo inputInfo = {
91         .data = nullptr,
92         .length = 0
93     };
94     IcInput tmpImage = {
95         .data = nullptr,
96         .size = MAX_IPC_BUFFER_SIZE
97     };
98     uint32_t offset = 0;
99     int32_t retCode = RETCODE_SUCCESS;
100     while (offset < inputData.size) {
101         tmpImage.data = &inputData.data[offset];
102         tmpImage.size = std::min(inputData.size - offset, MAX_IPC_BUFFER_SIZE);
103         inputInfo.data = nullptr;
104         inputInfo.length = 0;
105         outputInfo.data = nullptr;
106         outputInfo.length = 0;
107         retCode = EncdecFacade::ProcessEncode(inputInfo, icHandle_, offset, tmpImage);
108         if (retCode != RETCODE_SUCCESS) {
109             (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_SERIALIZATION_ERROR))
110                                    : HILOGD("[IcSdkImpl]No callback");
111             HILOGE("[IcSdkImpl]Failed to UnSerializeHandle");
112             return IC_RETCODE_SERIALIZATION_ERROR;
113         }
114         retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
115         if (retCode != RETCODE_SUCCESS) {
116             (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_FAILURE))
117                                    : HILOGD("[IcSdkImpl]No callback");
118             HILOGE("[IcSdkImpl]SyncExecute AieClientSyncProcess failed");
119             return IC_RETCODE_FAILURE;
120         }
121         offset += tmpImage.size;
122     }
123     return IC_RETCODE_SUCCESS;
124 }
125 
SyncExecute(const IcInput & inputData)126 int32_t IcSdkImpl::SyncExecute(const IcInput &inputData)
127 {
128     HILOGI("[IcSdkImpl]Start");
129     DataInfo outputInfo = {.data = nullptr, .length = 0};
130     int32_t retCode = OnSyncExecute(inputData, outputInfo);
131     if (outputInfo.data == nullptr || outputInfo.length <= 0 || retCode != IC_RETCODE_SUCCESS) {
132         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_FAILURE))
133                                : HILOGD("[IcSdkImpl]No callback");
134         HILOGE("[IcSdkImpl]SyncExecute failed");
135         return retCode;
136     }
137     IcOutput icResult = {.data = nullptr, .size = 0};
138     intptr_t receivedHandle = INVALID_IC_HANDLE;
139     MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
140     retCode = EncdecFacade::ProcessDecode(outputInfo, receivedHandle, icResult);
141     if (retCode != RETCODE_SUCCESS) {
142         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_UNSERIALIZATION_ERROR))
143                                : HILOGD("[IcSdkImpl]No callback");
144         HILOGE("[IcSdkImpl]Failed to UnSerializeHandle");
145         return IC_RETCODE_UNSERIALIZATION_ERROR;
146     }
147     if (icHandle_ != receivedHandle) {
148         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_FAILURE))
149                                : HILOGD("[IcSdkImpl]No callback");
150         HILOGE("[IcSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
151             (long long)receivedHandle, (long long)icHandle_);
152         return IC_RETCODE_FAILURE;
153     }
154     (callback_ != nullptr) ? (callback_->OnResult(icResult))
155                            : HILOGD("[IcSdkImpl]No callback");
156     return IC_RETCODE_SUCCESS;
157 }
158 
SetCallback(std::shared_ptr<IcCallback> callback)159 int32_t IcSdkImpl::SetCallback(std::shared_ptr<IcCallback> callback)
160 {
161     if (callback == nullptr) {
162         return IC_RETCODE_FAILURE;
163     }
164     callback_ = callback;
165     return IC_RETCODE_SUCCESS;
166 }
167 
Destroy()168 int32_t IcSdkImpl::Destroy()
169 {
170     HILOGI("[IcSdkImpl]Destroy");
171     if (icHandle_ == INVALID_IC_HANDLE) {
172         return IC_RETCODE_SUCCESS;
173     }
174     DataInfo inputInfo = {.data = nullptr, .length = 0};
175     int32_t retCode = EncdecFacade::ProcessEncode(inputInfo, icHandle_);
176     if (retCode != RETCODE_SUCCESS) {
177         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_SERIALIZATION_ERROR))
178                                : HILOGD("[IcSdkImpl]No callback");
179         HILOGE("[IcSdkImpl]Failed to SerializeHandle");
180         return IC_RETCODE_SERIALIZATION_ERROR;
181     }
182     retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
183     if (retCode != RETCODE_SUCCESS) {
184         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_FAILURE))
185                                : HILOGD("[IcSdkImpl]No callback");
186         HILOGE("[IcSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
187         return IC_RETCODE_FAILURE;
188     }
189     retCode = AieClientDestroy(clientInfo_);
190     icHandle_ = INVALID_IC_HANDLE;
191     if (retCode != RETCODE_SUCCESS) {
192         (callback_ != nullptr) ? (callback_->OnError(IC_RETCODE_FAILURE))
193                                : HILOGD("[IcSdkImpl]No callback");
194         HILOGE("[IcSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
195         return IC_RETCODE_FAILURE;
196     }
197     return IC_RETCODE_SUCCESS;
198 }