1886da342Sopenharmony_ci/*
2886da342Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3886da342Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4886da342Sopenharmony_ci * you may not use this file except in compliance with the License.
5886da342Sopenharmony_ci * You may obtain a copy of the License at
6886da342Sopenharmony_ci *
7886da342Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8886da342Sopenharmony_ci *
9886da342Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10886da342Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11886da342Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12886da342Sopenharmony_ci * See the License for the specific language governing permissions and
13886da342Sopenharmony_ci * limitations under the License.
14886da342Sopenharmony_ci */
15886da342Sopenharmony_ci
16886da342Sopenharmony_ci#include <common_event_manager.h>
17886da342Sopenharmony_ci#include <common_event_subscribe_info.h>
18886da342Sopenharmony_ci#include <functional>
19886da342Sopenharmony_ci#include <future>
20886da342Sopenharmony_ci#include <unistd.h>
21886da342Sopenharmony_ci#include "common_utilities_hpp.h"
22886da342Sopenharmony_ci#include "test_server_client.h"
23886da342Sopenharmony_ci#include "json.hpp"
24886da342Sopenharmony_ci#include "ipc_transactor.h"
25886da342Sopenharmony_ci
26886da342Sopenharmony_cinamespace OHOS::uitest {
27886da342Sopenharmony_ci    using namespace std;
28886da342Sopenharmony_ci    using namespace chrono;
29886da342Sopenharmony_ci    using namespace nlohmann;
30886da342Sopenharmony_ci    using namespace OHOS;
31886da342Sopenharmony_ci    using namespace OHOS::AAFwk;
32886da342Sopenharmony_ci    using namespace OHOS::EventFwk;
33886da342Sopenharmony_ci    using Message = MessageParcel &;
34886da342Sopenharmony_ci
35886da342Sopenharmony_ci    using CommonEventHandler = function<void(const CommonEventData &)>;
36886da342Sopenharmony_ci    class CommonEventForwarder : public CommonEventSubscriber {
37886da342Sopenharmony_ci    public:
38886da342Sopenharmony_ci        explicit CommonEventForwarder(const CommonEventSubscribeInfo &info, CommonEventHandler handler)
39886da342Sopenharmony_ci            : CommonEventSubscriber(info), handler_(handler)
40886da342Sopenharmony_ci        {
41886da342Sopenharmony_ci        }
42886da342Sopenharmony_ci
43886da342Sopenharmony_ci        virtual ~CommonEventForwarder() {}
44886da342Sopenharmony_ci
45886da342Sopenharmony_ci        void UpdateHandler(CommonEventHandler handler)
46886da342Sopenharmony_ci        {
47886da342Sopenharmony_ci            handler_ = handler;
48886da342Sopenharmony_ci        }
49886da342Sopenharmony_ci
50886da342Sopenharmony_ci        void OnReceiveEvent(const CommonEventData &data) override
51886da342Sopenharmony_ci        {
52886da342Sopenharmony_ci            if (handler_ != nullptr) {
53886da342Sopenharmony_ci                handler_(data);
54886da342Sopenharmony_ci            }
55886da342Sopenharmony_ci        }
56886da342Sopenharmony_ci
57886da342Sopenharmony_ci    private:
58886da342Sopenharmony_ci        CommonEventHandler handler_ = nullptr;
59886da342Sopenharmony_ci    };
60886da342Sopenharmony_ci
61886da342Sopenharmony_ci    using RemoteDiedHandler = function<void()>;
62886da342Sopenharmony_ci    class DeathRecipientForwarder : public IRemoteObject::DeathRecipient {
63886da342Sopenharmony_ci    public:
64886da342Sopenharmony_ci        explicit DeathRecipientForwarder(RemoteDiedHandler handler) : handler_(handler) {};
65886da342Sopenharmony_ci        ~DeathRecipientForwarder() = default;
66886da342Sopenharmony_ci        void OnRemoteDied(const wptr<IRemoteObject> &remote) override
67886da342Sopenharmony_ci        {
68886da342Sopenharmony_ci            if (handler_ != nullptr) {
69886da342Sopenharmony_ci                handler_();
70886da342Sopenharmony_ci            }
71886da342Sopenharmony_ci        }
72886da342Sopenharmony_ci
73886da342Sopenharmony_ci    private:
74886da342Sopenharmony_ci        const RemoteDiedHandler handler_;
75886da342Sopenharmony_ci    };
76886da342Sopenharmony_ci
77886da342Sopenharmony_ci    int ApiCaller::OnRemoteRequest(uint32_t code, Message data, Message reply, MessageOption &option)
78886da342Sopenharmony_ci    {
79886da342Sopenharmony_ci        if (data.ReadInterfaceToken() != GetDescriptor()) {
80886da342Sopenharmony_ci            return -1;
81886da342Sopenharmony_ci        }
82886da342Sopenharmony_ci        if (code == TRANS_ID_CALL) {
83886da342Sopenharmony_ci            // IPC io: verify on write
84886da342Sopenharmony_ci            ApiCallInfo call;
85886da342Sopenharmony_ci            string paramListStr;
86886da342Sopenharmony_ci            call.apiId_ = data.ReadString();
87886da342Sopenharmony_ci            call.callerObjRef_ = data.ReadString();
88886da342Sopenharmony_ci            paramListStr = data.ReadString();
89886da342Sopenharmony_ci            call.fdParamIndex_ = data.ReadInt32();
90886da342Sopenharmony_ci            call.paramList_ = nlohmann::json::parse(paramListStr, nullptr, false);
91886da342Sopenharmony_ci            DCHECK(!call.paramList_.is_discarded());
92886da342Sopenharmony_ci            if (call.fdParamIndex_ >= 0) {
93886da342Sopenharmony_ci                call.paramList_.at(call.fdParamIndex_) = data.ReadFileDescriptor();
94886da342Sopenharmony_ci            }
95886da342Sopenharmony_ci            ApiReplyInfo result;
96886da342Sopenharmony_ci            Call(call, result);
97886da342Sopenharmony_ci            auto ret = reply.WriteString(result.resultValue_.dump()) && reply.WriteUint32(result.exception_.code_) &&
98886da342Sopenharmony_ci                       reply.WriteString(result.exception_.message_);
99886da342Sopenharmony_ci            return ret ? 0 : -1;
100886da342Sopenharmony_ci        } else if (code == TRANS_ID_SET_BACKCALLER) {
101886da342Sopenharmony_ci            reply.WriteBool(SetBackCaller(data.ReadRemoteObject()));
102886da342Sopenharmony_ci            return 0;
103886da342Sopenharmony_ci        } else {
104886da342Sopenharmony_ci            return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
105886da342Sopenharmony_ci        }
106886da342Sopenharmony_ci    }
107886da342Sopenharmony_ci
108886da342Sopenharmony_ci    void ApiCaller::Call(const ApiCallInfo &call, ApiReplyInfo &result)
109886da342Sopenharmony_ci    {
110886da342Sopenharmony_ci        DCHECK(handler_ != nullptr);
111886da342Sopenharmony_ci        handler_(call, result);
112886da342Sopenharmony_ci    }
113886da342Sopenharmony_ci
114886da342Sopenharmony_ci    bool ApiCaller::SetBackCaller(const sptr<IRemoteObject> &caller)
115886da342Sopenharmony_ci    {
116886da342Sopenharmony_ci        if (backcallerHandler_ == nullptr) {
117886da342Sopenharmony_ci            LOG_W("No backcallerHandler set!");
118886da342Sopenharmony_ci            return false;
119886da342Sopenharmony_ci        }
120886da342Sopenharmony_ci        backcallerHandler_(caller);
121886da342Sopenharmony_ci        return true;
122886da342Sopenharmony_ci    }
123886da342Sopenharmony_ci
124886da342Sopenharmony_ci    void ApiCaller::SetCallHandler(ApiCallHandler handler)
125886da342Sopenharmony_ci    {
126886da342Sopenharmony_ci        handler_ = handler;
127886da342Sopenharmony_ci    }
128886da342Sopenharmony_ci
129886da342Sopenharmony_ci    void ApiCaller::SetBackCallerHandler(function<void(sptr<IRemoteObject>)> handler)
130886da342Sopenharmony_ci    {
131886da342Sopenharmony_ci        backcallerHandler_ = handler;
132886da342Sopenharmony_ci    }
133886da342Sopenharmony_ci
134886da342Sopenharmony_ci    ApiCallerProxy::ApiCallerProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<IApiCaller>(impl) {}
135886da342Sopenharmony_ci
136886da342Sopenharmony_ci    void ApiCallerProxy::Call(const ApiCallInfo &call, ApiReplyInfo &result)
137886da342Sopenharmony_ci    {
138886da342Sopenharmony_ci        MessageOption option;
139886da342Sopenharmony_ci        MessageParcel data;
140886da342Sopenharmony_ci        MessageParcel reply;
141886da342Sopenharmony_ci        // IPC io: verify on write
142886da342Sopenharmony_ci        auto ret = data.WriteInterfaceToken(GetDescriptor()) && data.WriteString(call.apiId_) &&
143886da342Sopenharmony_ci                   data.WriteString(call.callerObjRef_) && data.WriteString(call.paramList_.dump()) &&
144886da342Sopenharmony_ci                   data.WriteInt32(call.fdParamIndex_);
145886da342Sopenharmony_ci        auto fdIndex = call.fdParamIndex_;
146886da342Sopenharmony_ci        if (ret && fdIndex >= 0) {
147886da342Sopenharmony_ci            DCHECK(static_cast<size_t>(fdIndex) < call.paramList_.size());
148886da342Sopenharmony_ci            DCHECK(call.paramList_.at(fdIndex).type() == nlohmann::detail::value_t::number_integer);
149886da342Sopenharmony_ci            if (!data.WriteFileDescriptor(call.paramList_.at(fdIndex).get<uint32_t>())) {
150886da342Sopenharmony_ci                ret = false;
151886da342Sopenharmony_ci                LOG_E("Failed to write file descriptor param");
152886da342Sopenharmony_ci            }
153886da342Sopenharmony_ci        }
154886da342Sopenharmony_ci        if (!ret || Remote()->SendRequest(TRANS_ID_CALL, data, reply, option) != 0) {
155886da342Sopenharmony_ci            result.exception_ = ApiCallErr(ERR_INTERNAL, "IPC SendRequest failed");
156886da342Sopenharmony_ci            result.resultValue_ = nullptr;
157886da342Sopenharmony_ci        } else {
158886da342Sopenharmony_ci            result.resultValue_ = json::parse(reply.ReadString(), nullptr, false);
159886da342Sopenharmony_ci            DCHECK(!result.resultValue_.is_discarded());
160886da342Sopenharmony_ci            result.exception_.code_ = static_cast<ErrCode>(reply.ReadUint32());
161886da342Sopenharmony_ci            result.exception_.message_ = reply.ReadString();
162886da342Sopenharmony_ci        }
163886da342Sopenharmony_ci    }
164886da342Sopenharmony_ci
165886da342Sopenharmony_ci    bool ApiCallerProxy::SetBackCaller(const OHOS::sptr<IRemoteObject> &caller)
166886da342Sopenharmony_ci    {
167886da342Sopenharmony_ci        MessageOption option;
168886da342Sopenharmony_ci        MessageParcel data;
169886da342Sopenharmony_ci        MessageParcel reply;
170886da342Sopenharmony_ci        auto writeStat = data.WriteInterfaceToken(GetDescriptor()) && data.WriteRemoteObject(caller);
171886da342Sopenharmony_ci        if (!writeStat || (Remote()->SendRequest(TRANS_ID_SET_BACKCALLER, data, reply, option) != 0)) {
172886da342Sopenharmony_ci            LOG_E("IPC SendRequest failed");
173886da342Sopenharmony_ci            return false;
174886da342Sopenharmony_ci        }
175886da342Sopenharmony_ci        return reply.ReadBool();
176886da342Sopenharmony_ci    }
177886da342Sopenharmony_ci
178886da342Sopenharmony_ci    bool ApiCallerProxy::SetRemoteDeathCallback(const sptr<IRemoteObject::DeathRecipient> &callback)
179886da342Sopenharmony_ci    {
180886da342Sopenharmony_ci        return Remote()->AddDeathRecipient(callback);
181886da342Sopenharmony_ci    }
182886da342Sopenharmony_ci
183886da342Sopenharmony_ci    bool ApiCallerProxy::UnsetRemoteDeathCallback(const sptr<OHOS::IRemoteObject::DeathRecipient> &callback)
184886da342Sopenharmony_ci    {
185886da342Sopenharmony_ci        return Remote()->RemoveDeathRecipient(callback);
186886da342Sopenharmony_ci    }
187886da342Sopenharmony_ci
188886da342Sopenharmony_ci    constexpr string_view PUBLISH_EVENT_PREFIX = "uitest.api.caller.publish#";
189886da342Sopenharmony_ci    constexpr uint32_t PUBLISH_MAX_RETIES = 10;
190886da342Sopenharmony_ci    constexpr uint32_t WAIT_CONN_TIMEOUT_MS = 5000;
191886da342Sopenharmony_ci    constexpr uint32_t WAIT_DUMP_TIMEOUT_MS = 30000;
192886da342Sopenharmony_ci
193886da342Sopenharmony_ci    static sptr<IRemoteObject> PublishCallerAndWaitForBackcaller(const sptr<ApiCaller> &caller, string_view token)
194886da342Sopenharmony_ci    {
195886da342Sopenharmony_ci        CommonEventData event;
196886da342Sopenharmony_ci        Want want;
197886da342Sopenharmony_ci        want.SetAction(string(PUBLISH_EVENT_PREFIX) + token.data());
198886da342Sopenharmony_ci        want.SetParam(string(token), caller->AsObject());
199886da342Sopenharmony_ci        event.SetWant(want);
200886da342Sopenharmony_ci        // wait backcaller object registeration from client
201886da342Sopenharmony_ci        mutex mtx;
202886da342Sopenharmony_ci        unique_lock<mutex> lock(mtx);
203886da342Sopenharmony_ci        condition_variable condition;
204886da342Sopenharmony_ci        sptr<IRemoteObject> remoteCallerObject = nullptr;
205886da342Sopenharmony_ci        caller->SetBackCallerHandler([&remoteCallerObject, &condition](const sptr<IRemoteObject> &remote) {
206886da342Sopenharmony_ci            remoteCallerObject = remote;
207886da342Sopenharmony_ci            condition.notify_one();
208886da342Sopenharmony_ci        });
209886da342Sopenharmony_ci        constexpr auto period = chrono::milliseconds(WAIT_CONN_TIMEOUT_MS / PUBLISH_MAX_RETIES);
210886da342Sopenharmony_ci        uint32_t tries = 0;
211886da342Sopenharmony_ci        do {
212886da342Sopenharmony_ci            // publish caller with retries
213886da342Sopenharmony_ci            if (!OHOS::testserver::TestServerClient::GetInstance().PublishCommonEvent(event)) {
214886da342Sopenharmony_ci                LOG_E("Pulbish commonEvent failed");
215886da342Sopenharmony_ci            }
216886da342Sopenharmony_ci            tries++;
217886da342Sopenharmony_ci        } while (tries < PUBLISH_MAX_RETIES && condition.wait_for(lock, period) == cv_status::timeout);
218886da342Sopenharmony_ci        caller->SetBackCallerHandler(nullptr);
219886da342Sopenharmony_ci        return remoteCallerObject;
220886da342Sopenharmony_ci    }
221886da342Sopenharmony_ci
222886da342Sopenharmony_ci    static sptr<IRemoteObject> WaitForPublishedCaller(string_view token)
223886da342Sopenharmony_ci    {
224886da342Sopenharmony_ci        MatchingSkills matchingSkills;
225886da342Sopenharmony_ci        matchingSkills.AddEvent(string(PUBLISH_EVENT_PREFIX) + token.data());
226886da342Sopenharmony_ci        CommonEventSubscribeInfo info(matchingSkills);
227886da342Sopenharmony_ci        mutex mtx;
228886da342Sopenharmony_ci        unique_lock<mutex> lock(mtx);
229886da342Sopenharmony_ci        condition_variable condition;
230886da342Sopenharmony_ci        sptr<IRemoteObject> remoteObject = nullptr;
231886da342Sopenharmony_ci        auto onEvent = [&condition, &remoteObject, &token](const CommonEventData &data) {
232886da342Sopenharmony_ci            LOG_D("Received commonEvent");
233886da342Sopenharmony_ci            const auto &want = data.GetWant();
234886da342Sopenharmony_ci            remoteObject = want.GetRemoteObject(string(token));
235886da342Sopenharmony_ci            if (remoteObject == nullptr) {
236886da342Sopenharmony_ci                LOG_W("Not a proxy object!");
237886da342Sopenharmony_ci                remoteObject = nullptr;
238886da342Sopenharmony_ci            } else {
239886da342Sopenharmony_ci                condition.notify_one();
240886da342Sopenharmony_ci            }
241886da342Sopenharmony_ci        };
242886da342Sopenharmony_ci        shared_ptr<CommonEventForwarder> subscriber = make_shared<CommonEventForwarder>(info, onEvent);
243886da342Sopenharmony_ci        if (!CommonEventManager::SubscribeCommonEvent(subscriber)) {
244886da342Sopenharmony_ci            LOG_E("Fail to subscribe commonEvent");
245886da342Sopenharmony_ci            return nullptr;
246886da342Sopenharmony_ci        }
247886da342Sopenharmony_ci        const auto timeout = chrono::milliseconds(WAIT_CONN_TIMEOUT_MS);
248886da342Sopenharmony_ci        auto ret = condition.wait_for(lock, timeout);
249886da342Sopenharmony_ci        CommonEventManager::UnSubscribeCommonEvent(subscriber);
250886da342Sopenharmony_ci        subscriber->UpdateHandler(nullptr); // unset handler
251886da342Sopenharmony_ci        if (ret == cv_status::timeout) {
252886da342Sopenharmony_ci            LOG_E("Wait for ApiCaller publish by server timeout");
253886da342Sopenharmony_ci        } else if (remoteObject == nullptr) {
254886da342Sopenharmony_ci            LOG_E("Published ApiCaller object is null");
255886da342Sopenharmony_ci        }
256886da342Sopenharmony_ci        return remoteObject;
257886da342Sopenharmony_ci    }
258886da342Sopenharmony_ci
259886da342Sopenharmony_ci    ApiTransactor::ApiTransactor(bool asServer) : asServer_(asServer) {};
260886da342Sopenharmony_ci
261886da342Sopenharmony_ci    void ApiTransactor::SetDeathCallback(function<void()> callback)
262886da342Sopenharmony_ci    {
263886da342Sopenharmony_ci        if (singlenessMode_) {
264886da342Sopenharmony_ci            LOG_E("Cannot SetDeathCallback in singleness mode");
265886da342Sopenharmony_ci            return;
266886da342Sopenharmony_ci        }
267886da342Sopenharmony_ci        onDeathCallback_ = callback;
268886da342Sopenharmony_ci    }
269886da342Sopenharmony_ci
270886da342Sopenharmony_ci    void ApiTransactor::OnPeerDeath()
271886da342Sopenharmony_ci    {
272886da342Sopenharmony_ci        LOG_W("Connection with peer died!");
273886da342Sopenharmony_ci        connectState_ = DISCONNECTED;
274886da342Sopenharmony_ci        if (onDeathCallback_ != nullptr) {
275886da342Sopenharmony_ci            onDeathCallback_();
276886da342Sopenharmony_ci        }
277886da342Sopenharmony_ci    }
278886da342Sopenharmony_ci
279886da342Sopenharmony_ci    ApiTransactor::~ApiTransactor()
280886da342Sopenharmony_ci    {
281886da342Sopenharmony_ci        if (connectState_ == UNINIT) {
282886da342Sopenharmony_ci            return;
283886da342Sopenharmony_ci        }
284886da342Sopenharmony_ci        if (remoteCaller_ != nullptr && peerDeathCallback_ != nullptr) {
285886da342Sopenharmony_ci            remoteCaller_->UnsetRemoteDeathCallback(peerDeathCallback_);
286886da342Sopenharmony_ci        }
287886da342Sopenharmony_ci        caller_ = nullptr;
288886da342Sopenharmony_ci        remoteCaller_ = nullptr;
289886da342Sopenharmony_ci        peerDeathCallback_ = nullptr;
290886da342Sopenharmony_ci    }
291886da342Sopenharmony_ci
292886da342Sopenharmony_ci    bool ApiTransactor::InitAndConnectPeer(string_view token, ApiCallHandler handler)
293886da342Sopenharmony_ci    {
294886da342Sopenharmony_ci        LOG_I("Begin");
295886da342Sopenharmony_ci        DCHECK(connectState_ == UNINIT);
296886da342Sopenharmony_ci        connectState_ = DISCONNECTED;
297886da342Sopenharmony_ci        caller_ = new ApiCaller();
298886da342Sopenharmony_ci        caller_->SetCallHandler(handler);
299886da342Sopenharmony_ci        sptr<IRemoteObject> remoteObject = nullptr;
300886da342Sopenharmony_ci        if (asServer_) {
301886da342Sopenharmony_ci            // public caller object, and wait for backcaller registration from client
302886da342Sopenharmony_ci            remoteObject = PublishCallerAndWaitForBackcaller(caller_, token);
303886da342Sopenharmony_ci            if (remoteObject != nullptr) {
304886da342Sopenharmony_ci                remoteCaller_ = new ApiCallerProxy(remoteObject);
305886da342Sopenharmony_ci            }
306886da342Sopenharmony_ci        } else {
307886da342Sopenharmony_ci            // wait for published caller object, then register backcaller to server
308886da342Sopenharmony_ci            remoteObject = WaitForPublishedCaller(token);
309886da342Sopenharmony_ci            if (remoteObject != nullptr) {
310886da342Sopenharmony_ci                remoteCaller_ = new ApiCallerProxy(remoteObject);
311886da342Sopenharmony_ci                if (!remoteCaller_->SetBackCaller(caller_)) {
312886da342Sopenharmony_ci                    LOG_E("Failed to set backcaller to server");
313886da342Sopenharmony_ci                    return false;
314886da342Sopenharmony_ci                }
315886da342Sopenharmony_ci            }
316886da342Sopenharmony_ci        }
317886da342Sopenharmony_ci        if (remoteObject == nullptr || remoteCaller_ == nullptr) {
318886da342Sopenharmony_ci            LOG_E("Failed to get apiCaller object from peer");
319886da342Sopenharmony_ci            return false;
320886da342Sopenharmony_ci        }
321886da342Sopenharmony_ci        // in singleness mode, C/S runs in the same shell process and the remoteObject is a stub instead of proxy
322886da342Sopenharmony_ci        singlenessMode_ = !remoteObject->IsProxyObject();
323886da342Sopenharmony_ci        // link connectionState to it to remoteCaller
324886da342Sopenharmony_ci        if (!singlenessMode_) {
325886da342Sopenharmony_ci            peerDeathCallback_ = new DeathRecipientForwarder([this]() { this->OnPeerDeath(); });
326886da342Sopenharmony_ci            if (!remoteCaller_->SetRemoteDeathCallback(peerDeathCallback_)) {
327886da342Sopenharmony_ci                LOG_E("Failed to register remote caller DeathRecipient");
328886da342Sopenharmony_ci                return false;
329886da342Sopenharmony_ci            }
330886da342Sopenharmony_ci        }
331886da342Sopenharmony_ci        // connect done
332886da342Sopenharmony_ci        connectState_ = CONNECTED;
333886da342Sopenharmony_ci        LOG_I("Done");
334886da342Sopenharmony_ci        return true;
335886da342Sopenharmony_ci    }
336886da342Sopenharmony_ci
337886da342Sopenharmony_ci    ConnectionStat ApiTransactor::GetConnectionStat() const
338886da342Sopenharmony_ci    {
339886da342Sopenharmony_ci        return connectState_;
340886da342Sopenharmony_ci    }
341886da342Sopenharmony_ci
342886da342Sopenharmony_ci    void ApiTransactor::Finalize() {}
343886da342Sopenharmony_ci
344886da342Sopenharmony_ci    void ApiTransactor::Transact(const ApiCallInfo &call, ApiReplyInfo &reply)
345886da342Sopenharmony_ci    {
346886da342Sopenharmony_ci        // check connection state
347886da342Sopenharmony_ci        DCHECK(connectState_ != UNINIT);
348886da342Sopenharmony_ci        if (connectState_ == DISCONNECTED) {
349886da342Sopenharmony_ci            reply.exception_ = ApiCallErr(ERR_INTERNAL, "ipc connection is dead");
350886da342Sopenharmony_ci            return;
351886da342Sopenharmony_ci        }
352886da342Sopenharmony_ci        // check concurrent call
353886da342Sopenharmony_ci        if (!processingApi_.empty()) {
354886da342Sopenharmony_ci            constexpr auto msg = "uitest-api dose not allow calling concurrently, current processing:";
355886da342Sopenharmony_ci            reply.exception_.code_ = ERR_API_USAGE;
356886da342Sopenharmony_ci            reply.exception_.message_ = string(msg) + processingApi_ + ", incoming: " + call.apiId_;
357886da342Sopenharmony_ci            return;
358886da342Sopenharmony_ci        }
359886da342Sopenharmony_ci        processingApi_ = call.apiId_;
360886da342Sopenharmony_ci        // forward to peer
361886da342Sopenharmony_ci        DCHECK(remoteCaller_ != nullptr);
362886da342Sopenharmony_ci        remoteCaller_->Call(call, reply);
363886da342Sopenharmony_ci        processingApi_.clear();
364886da342Sopenharmony_ci    }
365886da342Sopenharmony_ci
366886da342Sopenharmony_ci    // functions for sending/handling broadcast commands
367886da342Sopenharmony_ci    BroadcastCommandHandler g_broadcastCommandHandler = nullptr;
368886da342Sopenharmony_ci    shared_ptr<CommonEventForwarder> g_broadcastCommandSubscriber = nullptr;
369886da342Sopenharmony_ci    void ApiTransactor::SendBroadcastCommand(const OHOS::AAFwk::Want &cmd, ApiCallErr &err)
370886da342Sopenharmony_ci    {
371886da342Sopenharmony_ci        LOG_I("Send uitest.broadcast.command begin");
372886da342Sopenharmony_ci        CommonEventData event;
373886da342Sopenharmony_ci        auto want = OHOS::AAFwk::Want(cmd);
374886da342Sopenharmony_ci        want.SetAction("uitest.broadcast.command");
375886da342Sopenharmony_ci        event.SetWant(want);
376886da342Sopenharmony_ci        if (!OHOS::testserver::TestServerClient::GetInstance().PublishCommonEvent(event)) {
377886da342Sopenharmony_ci            err = ApiCallErr(ERR_INTERNAL, "Failed to publish uitest.broadcast.command");
378886da342Sopenharmony_ci            return;
379886da342Sopenharmony_ci        }
380886da342Sopenharmony_ci        LOG_I("Send uitest.broadcast.command end");
381886da342Sopenharmony_ci        MatchingSkills matchingSkills;
382886da342Sopenharmony_ci        matchingSkills.AddEvent("uitest.broadcast.command.reply");
383886da342Sopenharmony_ci        CommonEventSubscribeInfo info(matchingSkills);
384886da342Sopenharmony_ci        mutex mtx;
385886da342Sopenharmony_ci        unique_lock<mutex> lock(mtx);
386886da342Sopenharmony_ci        condition_variable condition;
387886da342Sopenharmony_ci        auto onEvent = [&err, &condition](const CommonEventData &data) {
388886da342Sopenharmony_ci            const auto &reply = data.GetWant();
389886da342Sopenharmony_ci            auto code = static_cast<ErrCode>(reply.GetIntParam("code", 0));
390886da342Sopenharmony_ci            err = ApiCallErr(code, reply.GetStringParam("message"));
391886da342Sopenharmony_ci            condition.notify_one();
392886da342Sopenharmony_ci        };
393886da342Sopenharmony_ci        auto broadcastReplySubscriber = make_shared<CommonEventForwarder>(info, onEvent);
394886da342Sopenharmony_ci        if (!CommonEventManager::SubscribeCommonEvent(broadcastReplySubscriber)) {
395886da342Sopenharmony_ci            err = ApiCallErr(INTERNAL_ERROR, "Fail to subscribe uitest.broadcast.command.reply");
396886da342Sopenharmony_ci        }
397886da342Sopenharmony_ci        const auto timeout = chrono::milliseconds(WAIT_DUMP_TIMEOUT_MS);
398886da342Sopenharmony_ci        if (condition.wait_for(lock, timeout) == cv_status::timeout) {
399886da342Sopenharmony_ci            err = ApiCallErr(INTERNAL_ERROR, "Wait for subscribe uitest.broadcast.command.reply timeout");
400886da342Sopenharmony_ci        }
401886da342Sopenharmony_ci        CommonEventManager::UnSubscribeCommonEvent(broadcastReplySubscriber);
402886da342Sopenharmony_ci        LOG_I("Receive uitest.broadcast.command.reply end");
403886da342Sopenharmony_ci    }
404886da342Sopenharmony_ci
405886da342Sopenharmony_ci    void ApiTransactor::SetBroadcastCommandHandler(BroadcastCommandHandler handler)
406886da342Sopenharmony_ci    {
407886da342Sopenharmony_ci        if (handler == nullptr) {
408886da342Sopenharmony_ci            LOG_W("BroadcastCommandHandler is null");
409886da342Sopenharmony_ci            return;
410886da342Sopenharmony_ci        }
411886da342Sopenharmony_ci        g_broadcastCommandHandler = handler;
412886da342Sopenharmony_ci        if (g_broadcastCommandSubscriber != nullptr) {
413886da342Sopenharmony_ci            return;
414886da342Sopenharmony_ci        }
415886da342Sopenharmony_ci        MatchingSkills matchingSkills;
416886da342Sopenharmony_ci        matchingSkills.AddEvent("uitest.broadcast.command");
417886da342Sopenharmony_ci        CommonEventSubscribeInfo info(matchingSkills);
418886da342Sopenharmony_ci        auto onEvent = [](const CommonEventData &commandData) {
419886da342Sopenharmony_ci            auto commandWant = OHOS::AAFwk::Want(commandData.GetWant());
420886da342Sopenharmony_ci            // handle command in new thread, do not block in CommonEvent dispatching thread
421886da342Sopenharmony_ci            auto _ = async(launch::async, [&commandWant]() {
422886da342Sopenharmony_ci                LOG_I("HandleBroadcastCommand begin");
423886da342Sopenharmony_ci                auto replyWant = OHOS::AAFwk::Want();
424886da342Sopenharmony_ci                ApiCallErr err = ApiCallErr(NO_ERROR);
425886da342Sopenharmony_ci                if (g_broadcastCommandHandler == nullptr) {
426886da342Sopenharmony_ci                    err = ApiCallErr(INTERNAL_ERROR, "Received uitest.broadcast.command but handler is null!");
427886da342Sopenharmony_ci                } else {
428886da342Sopenharmony_ci                    g_broadcastCommandHandler(commandWant, err);
429886da342Sopenharmony_ci                }
430886da342Sopenharmony_ci                if (err.code_ != NO_ERROR) {
431886da342Sopenharmony_ci                    LOG_E("Cannot handle this.");
432886da342Sopenharmony_ci                    return;
433886da342Sopenharmony_ci                }
434886da342Sopenharmony_ci                replyWant.SetAction("uitest.broadcast.command.reply");
435886da342Sopenharmony_ci                replyWant.SetParam("code", (int)(err.code_));
436886da342Sopenharmony_ci                replyWant.SetParam("message", err.message_);
437886da342Sopenharmony_ci                CommonEventData replyData;
438886da342Sopenharmony_ci                replyData.SetWant(replyWant);
439886da342Sopenharmony_ci                if (!OHOS::testserver::TestServerClient::GetInstance().PublishCommonEvent(replyData)) {
440886da342Sopenharmony_ci                    LOG_E("Fail to publish uitest.broadcast.command.reply");
441886da342Sopenharmony_ci                }
442886da342Sopenharmony_ci                LOG_I("HandleBroadcastCommand end");
443886da342Sopenharmony_ci            });
444886da342Sopenharmony_ci        };
445886da342Sopenharmony_ci        g_broadcastCommandSubscriber = make_shared<CommonEventForwarder>(info, onEvent);
446886da342Sopenharmony_ci        if (!CommonEventManager::SubscribeCommonEvent(g_broadcastCommandSubscriber)) {
447886da342Sopenharmony_ci            LOG_E("Fail to subscribe uitest.broadcast.command");
448886da342Sopenharmony_ci        }
449886da342Sopenharmony_ci    }
450886da342Sopenharmony_ci
451886da342Sopenharmony_ci    void ApiTransactor::UnsetBroadcastCommandHandler()
452886da342Sopenharmony_ci    {
453886da342Sopenharmony_ci        if (g_broadcastCommandSubscriber != nullptr) {
454886da342Sopenharmony_ci            CommonEventManager::UnSubscribeCommonEvent(g_broadcastCommandSubscriber);
455886da342Sopenharmony_ci        }
456886da342Sopenharmony_ci        if (g_broadcastCommandHandler != nullptr) {
457886da342Sopenharmony_ci            g_broadcastCommandHandler = nullptr;
458886da342Sopenharmony_ci        }
459886da342Sopenharmony_ci    }
460886da342Sopenharmony_ci} // namespace OHOS::uitest