• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <unistd.h>
17 #include "common_utils.h"
18 #include "api_caller_client.h"
19 
20 namespace OHOS::perftest {
21     using namespace std;
22     using namespace chrono;
23     using namespace OHOS;
24     using namespace OHOS::AAFwk;
25     using namespace OHOS::EventFwk;
26 
~ApiCallerClient()27     ApiCallerClient::~ApiCallerClient()
28     {
29         if (connectState_ == UNINIT) {
30             return;
31         }
32         if (remoteCaller_ != nullptr && peerDeathCallback_ != nullptr) {
33             remoteCaller_->UnsetRemoteDeathCallback(peerDeathCallback_);
34         }
35         caller_ = nullptr;
36         remoteCaller_ = nullptr;
37         peerDeathCallback_ = nullptr;
38     }
39 
InitAndConnectPeer(string_view token,ApiCallHandler handler)40     bool ApiCallerClient::InitAndConnectPeer(string_view token, ApiCallHandler handler)
41     {
42         LOG_I("InitAndConnectPeer Begin");
43         if (connectState_ == CONNECTED) {
44             LOG_I("InitAndConnectPeer, client has connected with server");
45             return true;
46         }
47         DCHECK(connectState_ == UNINIT);
48         connectState_ = DISCONNECTED;
49         caller_ = new ApiCallerStub();
50         caller_->SetCallHandler(handler);
51         // wait for published caller object, then register backcaller to server
52         sptr<IRemoteObject> remoteObject = WaitForPublishedCaller(token);
53         if (remoteObject != nullptr) {
54             remoteCaller_ = new ApiCallerProxy(remoteObject);
55             if (!remoteCaller_->SetBackCaller(caller_)) {
56                 LOG_E("Failed to set backcaller to server");
57                 return false;
58             }
59         }
60         if (remoteObject == nullptr || remoteCaller_ == nullptr) {
61             LOG_E("Failed to get apiCaller object from peer");
62             return false;
63         }
64         // link connectionState to it to remoteCaller
65         peerDeathCallback_ = new DeathRecipientForwarder([this]() { this->OnPeerDeath(); });
66         if (!remoteCaller_->SetRemoteDeathCallback(peerDeathCallback_)) {
67             LOG_E("Failed to register remote caller DeathRecipient");
68             return false;
69         }
70         // connect done
71         connectState_ = CONNECTED;
72         LOG_I("ApiCallerClient InitAndConnectPeer Done");
73         return true;
74     }
75 
Transact(const ApiCallInfo & call,ApiReplyInfo & reply)76     void ApiCallerClient::Transact(const ApiCallInfo &call, ApiReplyInfo &reply)
77     {
78         // check connection state
79         DCHECK(connectState_ != UNINIT);
80         if (connectState_ == DISCONNECTED) {
81             reply.exception_ = ApiCallErr(ERR_INTERNAL, "ipc connection is dead");
82             return;
83         }
84         DCHECK(remoteCaller_ != nullptr);
85         // check concurrent call
86         if (!processingApi_.empty()) {
87             constexpr auto msg = "perftest-api dose not allow calling concurrently, current processing:";
88             reply.exception_.code_ = ERR_API_USAGE;
89             reply.exception_.message_ = string(msg) + processingApi_ + ", incoming: " + call.apiId_;
90             return;
91         }
92         processingApi_ = call.apiId_;
93         // forward to peer
94         remoteCaller_->Call(call, reply);
95         processingApi_.clear();
96     }
97 
SetDeathCallback(function<void ()> callback)98     void ApiCallerClient::SetDeathCallback(function<void()> callback)
99     {
100         onDeathCallback_ = callback;
101     }
102 
GetConnectionStat() const103     ConnectionStat ApiCallerClient::GetConnectionStat() const
104     {
105         return connectState_;
106     }
107 
WaitForPublishedCaller(string_view token)108     sptr<IRemoteObject> ApiCallerClient::WaitForPublishedCaller(string_view token)
109     {
110         MatchingSkills matchingSkills;
111         matchingSkills.AddEvent(string(PUBLISH_EVENT_PREFIX) + token.data());
112         CommonEventSubscribeInfo info(matchingSkills);
113         mutex mtx;
114         unique_lock<mutex> lock(mtx);
115         condition_variable condition;
116         sptr<IRemoteObject> remoteObject = nullptr;
117         auto onEvent = [&condition, &remoteObject, &token](const CommonEventData &data) {
118             LOG_I("Received commonEvent");
119             const auto &want = data.GetWant();
120             remoteObject = want.GetRemoteObject(string(token));
121             if (remoteObject == nullptr) {
122                 LOG_W("Not a proxy object!");
123                 remoteObject = nullptr;
124             } else {
125                 condition.notify_one();
126             }
127         };
128         shared_ptr<CommonEventForwarder> subscriber = make_shared<CommonEventForwarder>(info, onEvent);
129         if (!CommonEventManager::SubscribeCommonEvent(subscriber)) {
130             LOG_E("Fail to subscribe commonEvent");
131             return nullptr;
132         }
133         const auto timeout = chrono::milliseconds(WAIT_CONN_TIMEOUT_MS);
134         auto ret = condition.wait_for(lock, timeout);
135         CommonEventManager::UnSubscribeCommonEvent(subscriber);
136         subscriber->UpdateHandler(nullptr); // unset handler
137         if (ret == cv_status::timeout) {
138             LOG_E("Wait for ApiCaller publish by server timeout");
139         } else if (remoteObject == nullptr) {
140             LOG_E("Published ApiCaller object is null");
141         }
142         return remoteObject;
143     }
144 
OnPeerDeath()145     void ApiCallerClient::OnPeerDeath()
146     {
147         LOG_W("Connection with peer died!");
148         connectState_ = DISCONNECTED;
149         if (onDeathCallback_ != nullptr) {
150             onDeathCallback_();
151         }
152     }
153 
UpdateHandler(CommonEventHandler handler)154     void CommonEventForwarder::UpdateHandler(CommonEventHandler handler)
155     {
156         handler_ = handler;
157     }
158 
OnReceiveEvent(const CommonEventData & data)159     void CommonEventForwarder::OnReceiveEvent(const CommonEventData &data)
160     {
161         if (handler_ != nullptr) {
162             handler_(data);
163         }
164     }
165 } // namespace OHOS::perftest