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