1 /*
2  * Copyright (c) 2022 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 "async_command_base.h"
17 
18 #include <atomic>
19 #include <cstdint>
20 #include <ostream>
21 #include <sstream>
22 #include <string>
23 #include <vector>
24 
25 #include "iam_check.h"
26 #include "iam_defines.h"
27 #include "iam_logger.h"
28 #include "iam_para2str.h"
29 #include "iam_executor_framework_types.h"
30 
31 #define LOG_TAG "USER_AUTH_EXECUTOR"
32 
33 namespace OHOS {
34 namespace UserIam {
35 namespace UserAuth {
AsyncCommandBase(std::string type,uint64_t scheduleId,std::weak_ptr<Executor> executor,std::shared_ptr<ExecutorMessenger> executorMessenger)36 AsyncCommandBase::AsyncCommandBase(std::string type, uint64_t scheduleId, std::weak_ptr<Executor> executor,
37     std::shared_ptr<ExecutorMessenger> executorMessenger)
38     : scheduleId_(scheduleId),
39       executor_(executor),
40       executorMessenger_(executorMessenger)
41 {
42     auto commandId = GenerateCommandId();
43     std::ostringstream ss;
44     ss << "Command(type:" << type << ", id:" << commandId << ", scheduleId:" << GET_MASKED_STRING(scheduleId_) << ")";
45     description_ = ss.str();
46 }
47 
OnHdiDisconnect()48 void AsyncCommandBase::OnHdiDisconnect()
49 {
50     IAM_LOGI("driver disconnect, %{public}s end process", GetDescription());
51     // Need new result code: hal invalid
52     OnResult(ResultCode::GENERAL_ERROR);
53 }
54 
StartProcess()55 ResultCode AsyncCommandBase::StartProcess()
56 {
57     IAM_LOGI("%{public}s start process", GetDescription());
58     auto executor = executor_.lock();
59     if (executor == nullptr) {
60         IAM_LOGE("%{public}s executor has been released, start process fail", GetDescription());
61         return ResultCode::GENERAL_ERROR;
62     }
63     executor->AddCommand(shared_from_this());
64     ResultCode ret = SendRequest();
65     if (ret != ResultCode::SUCCESS) {
66         IAM_LOGE("%{public}s send request failed", GetDescription());
67         EndProcess();
68         return ret;
69     }
70     return ResultCode::SUCCESS;
71 }
72 
OnResult(ResultCode result)73 void AsyncCommandBase::OnResult(ResultCode result)
74 {
75     std::vector<uint8_t> extraInfo;
76     OnResult(result, extraInfo);
77 }
78 
OnResult(ResultCode result,const std::vector<uint8_t> & extraInfo)79 void AsyncCommandBase::OnResult(ResultCode result, const std::vector<uint8_t> &extraInfo)
80 {
81     std::lock_guard<std::mutex> guard(mutex_);
82     if (isFinished_) {
83         IAM_LOGE("command is finished, invocation of OnResult is invalid");
84         return;
85     }
86     isFinished_ = true;
87     OnResultInner(result, extraInfo);
88     EndProcess();
89 }
90 
OnAcquireInfo(int32_t acquire,const std::vector<uint8_t> & extraInfo)91 void AsyncCommandBase::OnAcquireInfo(int32_t acquire, const std::vector<uint8_t> &extraInfo)
92 {
93     std::lock_guard<std::mutex> guard(mutex_);
94     if (isFinished_) {
95         IAM_LOGE("command is finished, invocation of OnAcquireInfo is invalid");
96         return;
97     }
98     OnAcquireInfoInner(acquire, extraInfo);
99 }
100 
OnAcquireInfoInner(int32_t acquire,const std::vector<uint8_t> & extraInfo)101 void AsyncCommandBase::OnAcquireInfoInner(int32_t acquire, const std::vector<uint8_t> &extraInfo)
102 {
103     IAM_LOGI("%{public}s start", GetDescription());
104 
105     Attributes attr;
106     bool setAcquireRet = attr.SetInt32Value(Attributes::ATTR_TIP_INFO, acquire);
107     IF_FALSE_LOGE_AND_RETURN(setAcquireRet);
108     bool setExtraInfoRet = attr.SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, extraInfo);
109     IF_FALSE_LOGE_AND_RETURN(setExtraInfoRet);
110 
111     auto data = AuthMessage::As(attr.Serialize());
112     IF_FALSE_LOGE_AND_RETURN(data != nullptr);
113     int32_t ret = MessengerSendData(scheduleId_, SCHEDULER, data);
114     if (ret != USERAUTH_SUCCESS) {
115         IAM_LOGE("%{public}s call SendData fail", GetDescription());
116         return;
117     }
118     IAM_LOGI("%{public}s end, acquire %{public}d", GetDescription(), acquire);
119 }
120 
OnMessage(int destRole,const std::vector<uint8_t> & msg)121 void AsyncCommandBase::OnMessage(int destRole, const std::vector<uint8_t> &msg)
122 {
123     std::lock_guard<std::mutex> guard(mutex_);
124     if (isFinished_) {
125         IAM_LOGE("command is finished, invocation of OnMessage is invalid");
126         return;
127     }
128     OnMessageInner(destRole, msg);
129 }
130 
OnMessageInner(int destRole,const std::vector<uint8_t> & msg)131 void AsyncCommandBase::OnMessageInner(int destRole, const std::vector<uint8_t> &msg)
132 {
133     IAM_LOGI("%{public}s start", GetDescription());
134 
135     std::shared_ptr<Executor> executor = executor_.lock();
136     IF_FALSE_LOGE_AND_RETURN(executor != nullptr);
137 
138     Attributes attr;
139     bool setAcquireRet = attr.SetInt32Value(Attributes::ATTR_SRC_ROLE, executor->GetExecutorRole());
140     IF_FALSE_LOGE_AND_RETURN(setAcquireRet);
141     bool setExtraInfoRet = attr.SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, msg);
142     IF_FALSE_LOGE_AND_RETURN(setExtraInfoRet);
143 
144     auto data = AuthMessage::As(attr.Serialize());
145     IF_FALSE_LOGE_AND_RETURN(data != nullptr);
146     int32_t ret = MessengerSendData(scheduleId_, static_cast<ExecutorRole>(destRole), data);
147     if (ret != USERAUTH_SUCCESS) {
148         IAM_LOGE("%{public}s call SendData fail", GetDescription());
149         return;
150     }
151     IAM_LOGI("%{public}s end, msg size %{public}zu", GetDescription(), msg.size());
152 }
153 
GetAuthType()154 int32_t AsyncCommandBase::GetAuthType()
155 {
156     auto executor = executor_.lock();
157     if (executor == nullptr) {
158         IAM_LOGE("%{public}s executor has been released, get executor type fail", GetDescription());
159         return INVALID_AUTH_TYPE;
160     }
161     return executor->GetAuthType();
162 }
163 
EndProcess()164 void AsyncCommandBase::EndProcess()
165 {
166     IAM_LOGI("%{public}s end process", GetDescription());
167     auto executor = executor_.lock();
168     if (executor == nullptr) {
169         IAM_LOGI(
170             "%{public}s executor has been released, command has been removed, no need remove again", GetDescription());
171         return;
172     }
173     executor->RemoveCommand(shared_from_this());
174 }
175 
GetDescription()176 const char *AsyncCommandBase::GetDescription()
177 {
178     return description_.c_str();
179 }
180 
GenerateCommandId()181 uint32_t AsyncCommandBase::GenerateCommandId()
182 {
183     std::atomic<uint32_t> commandId = 0;
184     // commandId is only used in log, uint32 overflow or duplicate is ok
185     return ++commandId;
186 }
187 
GetExecutorHdi()188 std::shared_ptr<IAuthExecutorHdi> AsyncCommandBase::GetExecutorHdi()
189 {
190     auto executor = executor_.lock();
191     if (executor == nullptr) {
192         IAM_LOGE("%{public}s executor has been released, get executor hdi fail", GetDescription());
193         return nullptr;
194     }
195     return executor->GetExecutorHdi();
196 }
197 
MessengerSendData(uint64_t scheduleId,ExecutorRole dstType,std::shared_ptr<AuthMessage> msg)198 int32_t AsyncCommandBase::MessengerSendData(uint64_t scheduleId,
199     ExecutorRole dstType, std::shared_ptr<AuthMessage> msg)
200 {
201     auto messenger = executorMessenger_;
202     IF_FALSE_LOGE_AND_RETURN_VAL(messenger != nullptr, USERAUTH_ERROR);
203     return messenger->SendData(scheduleId, dstType, msg);
204 }
205 
MessengerFinish(uint64_t scheduleId,int32_t resultCode,std::shared_ptr<Attributes> finalResult)206 int32_t AsyncCommandBase::MessengerFinish(uint64_t scheduleId, int32_t resultCode,
207     std::shared_ptr<Attributes> finalResult)
208 {
209     auto messenger = executorMessenger_;
210     IF_FALSE_LOGE_AND_RETURN_VAL(messenger != nullptr, USERAUTH_ERROR);
211     int32_t ret = messenger->Finish(scheduleId, resultCode, *finalResult);
212     executorMessenger_ = nullptr;
213     return ret;
214 }
215 } // namespace UserAuth
216 } // namespace UserIam
217 } // namespace OHOS
218