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 <hitrace_meter.h>
17 #include <string_ex.h>
18
19 #include "cj_lambda.h"
20 #include "ipc_utils_ffi.h"
21 #include "message_option.h"
22 #include "remote_proxy_holder_impl.h"
23
24 static std::atomic<int32_t> bytraceId = 1000;
25 namespace OHOS {
RemoteProxyHolderImpl()26 RemoteProxyHolderImpl::RemoteProxyHolderImpl() : object_(nullptr) {}
27
~RemoteProxyHolderImpl()28 RemoteProxyHolderImpl::~RemoteProxyHolderImpl()
29 {
30 object_ = nullptr;
31 }
32
CJDeathRecipient(int64_t funcId)33 CJDeathRecipient::CJDeathRecipient(int64_t funcId)
34 {
35 funcId_ = funcId;
36 }
37
OnRemoteDied(const wptr<IRemoteObject> & object)38 void CJDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& object)
39 {
40 auto func = reinterpret_cast<void (*)()>(funcId_);
41 auto handler = CJLambda::Create(func);
42 if (handler == nullptr) {
43 ZLOGE(LOG_LABEL, "failed to get property onRemoteDied");
44 return;
45 }
46 handler();
47 }
48
Matches(int64_t funcId)49 bool CJDeathRecipient::Matches(int64_t funcId)
50 {
51 return funcId_ == funcId;
52 }
53
CJDeathRecipientList()54 CJDeathRecipientList::CJDeathRecipientList() {}
55
~CJDeathRecipientList()56 CJDeathRecipientList::~CJDeathRecipientList()
57 {
58 std::lock_guard<std::mutex> lockGuard(mutex_);
59 set_.clear();
60 }
61
Add(const sptr<CJDeathRecipient> & recipient)62 bool CJDeathRecipientList::Add(const sptr<CJDeathRecipient>& recipient)
63 {
64 std::lock_guard<std::mutex> lockGuard(mutex_);
65 auto ret = set_.insert(recipient);
66 return ret.second;
67 }
68
Remove(const sptr<CJDeathRecipient> & recipient)69 bool CJDeathRecipientList::Remove(const sptr<CJDeathRecipient>& recipient)
70 {
71 std::lock_guard<std::mutex> lockGuard(mutex_);
72 return (set_.erase(recipient) > 0);
73 }
74
Find(int64_t funcId)75 sptr<CJDeathRecipient> CJDeathRecipientList::Find(int64_t funcId)
76 {
77 std::lock_guard<std::mutex> lockGuard(mutex_);
78 for (auto it = set_.begin(); it != set_.end(); it++) {
79 if ((*it)->Matches(funcId)) {
80 return *it;
81 }
82 }
83 return nullptr;
84 }
85
SendMessageRequest(uint32_t code,int64_t dataId,int64_t replyId,MessageOption option,int64_t funcId)86 int32_t RemoteProxyHolderImpl::SendMessageRequest(
87 uint32_t code, int64_t dataId, int64_t replyId, MessageOption option, int64_t funcId)
88 {
89 auto data = FFIData::GetData<MessageSequenceImpl>(dataId);
90 if (!data) {
91 ZLOGE(LOG_LABEL, "[RPC] failed to get data message parcel");
92 return errorDesc::CHECK_PARAM_ERROR;
93 }
94 auto reply = FFIData::GetData<MessageSequenceImpl>(replyId);
95 if (!reply) {
96 ZLOGE(LOG_LABEL, "[RPC] failed to get reply message parcel");
97 return errorDesc::CHECK_PARAM_ERROR;
98 }
99 if (object_ == nullptr) {
100 ZLOGE(LOG_LABEL, "invalid proxy object");
101 return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
102 }
103 std::string remoteDescriptor = Str16ToStr8(object_->GetObjectDescriptor());
104 if (!remoteDescriptor.empty()) {
105 std::string traceValue = remoteDescriptor + std::to_string(code);
106 int32_t traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
107 StartAsyncTrace(HITRACE_TAG_RPC, traceValue.c_str(), traceId);
108 }
109 int32_t errCode =
110 object_->SendRequest(code, *(data->GetMessageParcel().get()), *(reply->GetMessageParcel().get()), option);
111 auto callback = CJLambda::Create(reinterpret_cast<void (*)(RequestResult)>(funcId));
112 if (callback) {
113 ZLOGI(LOG_LABEL, "callback started");
114 RequestResult result = RequestResult { .errCode = errCode, .code = code, .data = dataId, .reply = replyId };
115 callback(result);
116 }
117 return 0;
118 }
119
GetDescriptor(int32_t * errCode)120 char* RemoteProxyHolderImpl::GetDescriptor(int32_t* errCode)
121 {
122 if (object_ == nullptr) {
123 ZLOGE(LOG_LABEL, "proxy object is nullptr");
124 *errCode = errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
125 return nullptr;
126 }
127 std::u16string remoteDescriptor = object_->GetInterfaceDescriptor();
128 if (remoteDescriptor == std::u16string()) {
129 ZLOGE(LOG_LABEL, "failed to get interface descriptor");
130 *errCode = errorDesc::COMMUNICATION_ERROR;
131 return nullptr;
132 }
133 return MallocCString(Str16ToStr8(remoteDescriptor));
134 }
135
IsObjectDead()136 bool RemoteProxyHolderImpl::IsObjectDead()
137 {
138 if (object_ == nullptr) {
139 ZLOGE(LOG_LABEL, "Invalid proxy object");
140 return false;
141 }
142 return object_->IsObjectDead();
143 }
144
RegisterDeathRecipient(int64_t funcId,int32_t flag)145 int32_t RemoteProxyHolderImpl::RegisterDeathRecipient(int64_t funcId, int32_t flag)
146 {
147 if ((object_ == nullptr) || !object_->IsProxyObject()) {
148 ZLOGE(LOG_LABEL, "could not add recipient from invalid target");
149 return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
150 }
151 sptr<CJDeathRecipient> nativeRecipient = new (std::nothrow) CJDeathRecipient(funcId);
152 if (nativeRecipient == nullptr) {
153 ZLOGE(LOG_LABEL, "new CJDeathRecipient failed");
154 return errorDesc::CHECK_PARAM_ERROR;
155 }
156 bool ret = object_->AddDeathRecipient(nativeRecipient);
157 if (ret) {
158 list_->Add(nativeRecipient);
159 }
160 ZLOGI(LOG_LABEL, "%{public}s", ret ? "succ" : "fail");
161 return 0;
162 }
163
UnregisterDeathRecipient(int64_t funcId,int32_t flag)164 int32_t RemoteProxyHolderImpl::UnregisterDeathRecipient(int64_t funcId, int32_t flag)
165 {
166 if ((object_ == nullptr) || !object_->IsProxyObject()) {
167 ZLOGE(LOG_LABEL, "could not remove recipient from invalid target");
168 return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
169 }
170 sptr<CJDeathRecipient> nativeRecipient = list_->Find(funcId);
171 if (nativeRecipient == nullptr) {
172 ZLOGE(LOG_LABEL, "recipient not found");
173 return 0;
174 }
175 object_->RemoveDeathRecipient(nativeRecipient);
176 bool ret = list_->Remove(nativeRecipient);
177 ZLOGI(LOG_LABEL, "%{public}s", ret ? "succ" : "fail");
178 return 0;
179 }
180
IsProxyObject()181 bool RemoteProxyHolderImpl::IsProxyObject()
182 {
183 if (object_ == nullptr) {
184 ZLOGE(LOG_LABEL, "object_ is nullptr");
185 return false;
186 }
187 return object_->IsProxyObject();
188 }
189
GetRemoteObject()190 sptr<IRemoteObject> RemoteProxyHolderImpl::GetRemoteObject()
191 {
192 return object_;
193 }
194 } // namespace OHOS