1 /* 2 * Copyright (c) 2025 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 <common_event_manager.h> 17 #include <functional> 18 #include <future> 19 #include <unistd.h> 20 #include <want.h> 21 #include "common_utils.h" 22 #include "test_server_client.h" 23 #include "api_caller_server.h" 24 25 namespace OHOS::perftest { 26 using namespace std; 27 using namespace chrono; 28 using namespace OHOS; 29 using namespace OHOS::AAFwk; 30 using namespace OHOS::EventFwk; 31 ~ApiCallerServer()32 ApiCallerServer::~ApiCallerServer() 33 { 34 if (connectState_ == UNINIT) { 35 return; 36 } 37 if (remoteCaller_ != nullptr && peerDeathCallback_ != nullptr) { 38 remoteCaller_->UnsetRemoteDeathCallback(peerDeathCallback_); 39 } 40 caller_ = nullptr; 41 remoteCaller_ = nullptr; 42 peerDeathCallback_ = nullptr; 43 } 44 InitAndConnectPeer(string_view token,ApiCallHandler handler)45 bool ApiCallerServer::InitAndConnectPeer(string_view token, ApiCallHandler handler) 46 { 47 LOG_I("ApiCallerServer InitAndConnectPeer Begin"); 48 DCHECK(connectState_ == UNINIT); 49 connectState_ = DISCONNECTED; 50 caller_ = new ApiCallerStub(); 51 caller_->SetCallHandler(handler); 52 sptr<IRemoteObject> remoteObject = nullptr; 53 // public caller object, and wait for backcaller registration from client 54 remoteObject = PublishCallerAndWaitForBackcaller(caller_, token); 55 if (remoteObject != nullptr) { 56 remoteCaller_ = new ApiCallerProxy(remoteObject); 57 } 58 if (remoteObject == nullptr || remoteCaller_ == nullptr) { 59 LOG_E("Failed to get apiCaller object from peer"); 60 return false; 61 } 62 // link connectionState to it to remoteCaller 63 peerDeathCallback_ = new DeathRecipientForwarder([this]() { this->OnPeerDeath(); }); 64 if (!remoteCaller_->SetRemoteDeathCallback(peerDeathCallback_)) { 65 LOG_E("Failed to register remote caller DeathRecipient"); 66 return false; 67 } 68 // connect done 69 connectState_ = CONNECTED; 70 LOG_I("ApiCallerServer InitAndConnectPeer Done"); 71 return true; 72 } 73 Transact(const ApiCallInfo & call,ApiReplyInfo & reply)74 void ApiCallerServer::Transact(const ApiCallInfo &call, ApiReplyInfo &reply) 75 { 76 // check connection state 77 DCHECK(connectState_ != UNINIT); 78 if (connectState_ == DISCONNECTED) { 79 reply.exception_ = ApiCallErr(ERR_INTERNAL, "ipc connection is dead"); 80 return; 81 } 82 // forward to peer 83 DCHECK(remoteCaller_ != nullptr); 84 remoteCaller_->Call(call, reply); 85 } 86 SetDeathCallback(function<void ()> callback)87 void ApiCallerServer::SetDeathCallback(function<void()> callback) 88 { 89 onDeathCallback_ = callback; 90 } 91 GetConnectionStat() const92 ConnectionStat ApiCallerServer::GetConnectionStat() const 93 { 94 return connectState_; 95 } 96 Finalize()97 void ApiCallerServer::Finalize() {} 98 PublishCallerAndWaitForBackcaller(const sptr<ApiCallerStub> & caller,string_view token)99 sptr<IRemoteObject> ApiCallerServer::PublishCallerAndWaitForBackcaller(const sptr<ApiCallerStub> &caller, 100 string_view token) 101 { 102 CommonEventData event; 103 Want want; 104 want.SetAction(string(PUBLISH_EVENT_PREFIX) + token.data()); 105 want.SetParam(string(token), caller->AsObject()); 106 event.SetWant(want); 107 // wait backcaller object registeration from client 108 mutex mtx; 109 unique_lock<mutex> lock(mtx); 110 condition_variable condition; 111 sptr<IRemoteObject> remoteCallerObject = nullptr; 112 caller->SetBackCallerHandler([&remoteCallerObject, &condition](const sptr<IRemoteObject> &remote) { 113 remoteCallerObject = remote; 114 condition.notify_one(); 115 }); 116 constexpr auto period = chrono::milliseconds(WAIT_CONN_TIMEOUT_MS / PUBLISH_MAX_RETIES); 117 uint32_t tries = 0; 118 do { 119 // publish caller with retries 120 if (!OHOS::testserver::TestServerClient::GetInstance().PublishCommonEvent(event)) { 121 LOG_E("Pulbish commonEvent failed"); 122 } 123 tries++; 124 } while (tries < PUBLISH_MAX_RETIES && condition.wait_for(lock, period) == cv_status::timeout); 125 caller->SetBackCallerHandler(nullptr); 126 return remoteCallerObject; 127 } 128 OnPeerDeath()129 void ApiCallerServer::OnPeerDeath() 130 { 131 LOG_W("Connection with peer died!"); 132 connectState_ = DISCONNECTED; 133 if (onDeathCallback_ != nullptr) { 134 onDeathCallback_(); 135 } 136 } 137 } // namespace OHOS::perftest