1 /*
2 * Copyright (C) 2021 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 "ipc_object_proxy.h"
17
18 #include <cstdint>
19
20 #include "__mutex_base"
21 #include "algorithm"
22 #include "dbinder_error_code.h"
23 #include "errors.h"
24 #include "hilog/log_c.h"
25 #include "hilog/log_cpp.h"
26 #include "iosfwd"
27 #include "ipc_debug.h"
28 #include "ipc_process_skeleton.h"
29 #include "ipc_thread_skeleton.h"
30 #include "ipc_types.h"
31 #include "iremote_invoker.h"
32 #include "iremote_object.h"
33 #include "log_tags.h"
34 #include "message_option.h"
35 #include "message_parcel.h"
36 #include "mutex"
37 #include "process_skeleton.h"
38 #include "refbase.h"
39 #include "string"
40 #include "string_ex.h"
41 #include "type_traits"
42 #include "unistd.h"
43 #include "vector"
44
45 #ifndef CONFIG_IPC_SINGLE
46 #include "access_token_adapter.h"
47 #include "dbinder_databus_invoker.h"
48 #endif
49
50 namespace OHOS {
51 #ifdef CONFIG_IPC_SINGLE
52 using namespace IPC_SINGLE;
53 #endif
54
55 #define PRINT_SEND_REQUEST_FAIL_INFO(handle, error, desc) \
56 ZLOGE(LABEL, "failed, handle:%{public}d error:%{public}d desc:%{public}s", \
57 handle, error, (desc).c_str())
58
59 static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC_PROXY, "IPCObjectProxy" };
60 static constexpr uint32_t IPC_OBJECT_MASK = 0xffffff;
61
IPCObjectProxy(int handle,std::u16string descriptor,int proto)62 IPCObjectProxy::IPCObjectProxy(int handle, std::u16string descriptor, int proto)
63 : IRemoteObject(std::move(descriptor)), handle_(handle), proto_(proto), isFinishInit_(false), isRemoteDead_(false)
64 {
65 #ifdef CONFIG_ACTV_BINDER
66 IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
67 if (invoker != nullptr) {
68 invoker->LinkRemoteInvoker(&invokerData_);
69 }
70 #endif
71 ZLOGD(LABEL, "handle:%{public}u desc:%{public}s %{public}zu", handle_,
72 IPCProcessSkeleton::ConvertToSecureDesc(Str16ToStr8(descriptor_)).c_str(), reinterpret_cast<uintptr_t>(this));
73 ExtendObjectLifetime();
74 ProcessSkeleton *current = ProcessSkeleton::GetInstance();
75 if (current == nullptr) {
76 ZLOGE(LABEL, "ProcessSkeleton is null");
77 return;
78 }
79 current->DetachDeadObject(this);
80 }
81
~IPCObjectProxy()82 IPCObjectProxy::~IPCObjectProxy()
83 {
84 #ifdef CONFIG_ACTV_BINDER
85 IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
86 if (invoker != nullptr) {
87 invoker->UnlinkRemoteInvoker(&invokerData_);
88 }
89 #endif
90 ZLOGD(LABEL, "handle:%{public}u desc:%{public}s %{public}zu", handle_,
91 IPCProcessSkeleton::ConvertToSecureDesc(Str16ToStr8(remoteDescriptor_)).c_str(),
92 reinterpret_cast<uintptr_t>(this));
93 ProcessSkeleton *current = ProcessSkeleton::GetInstance();
94 if (current == nullptr) {
95 ZLOGE(LABEL, "ProcessSkeleton is null");
96 return;
97 }
98 uint64_t curTime = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
99 std::chrono::steady_clock::now().time_since_epoch()).count());
100 DeadObjectInfo obj = { handle_, curTime, curTime, remoteDescriptor_ };
101 current->AttachDeadObject(this, obj);
102 }
103
GetObjectRefCount()104 int32_t IPCObjectProxy::GetObjectRefCount()
105 {
106 MessageParcel data, reply;
107 MessageOption option;
108 int err = SendRequestInner(false, SYNCHRONIZE_REFERENCE, data, reply, option);
109 if (err == ERR_NONE) {
110 return reply.ReadInt32();
111 }
112 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
113 return 0;
114 }
115
Dump(int fd,const std::vector<std::u16string> & args)116 int IPCObjectProxy::Dump(int fd, const std::vector<std::u16string> &args)
117 {
118 MessageParcel data, reply;
119 MessageOption option { MessageOption::TF_SYNC };
120 data.WriteFileDescriptor(fd);
121 data.WriteString16Vector(args);
122 return SendRequestInner(false, DUMP_TRANSACTION, data, reply, option);
123 }
124
SendRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)125 int IPCObjectProxy::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
126 {
127 if (code != DUMP_TRANSACTION && code > MAX_TRANSACTION_ID) {
128 return IPC_PROXY_INVALID_CODE_ERR;
129 }
130
131 int err = SendRequestInner(false, code, data, reply, option);
132 if (err != ERR_NONE) {
133 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
134 }
135 return err;
136 }
137
SendLocalRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)138 int IPCObjectProxy::SendLocalRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
139 {
140 return SendRequestInner(true, code, data, reply, option);
141 }
142
SendRequestInner(bool isLocal,uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)143 int IPCObjectProxy::SendRequestInner(bool isLocal, uint32_t code, MessageParcel &data, MessageParcel &reply,
144 MessageOption &option)
145 {
146 if (IsObjectDead()) {
147 ZLOGE(LABEL, "proxy is already dead, handle:%{public}d desc:%{public}s",
148 handle_, Str16ToStr8(remoteDescriptor_).c_str());
149 return ERR_DEAD_OBJECT;
150 }
151
152 IRemoteInvoker *invoker = nullptr;
153 if (isLocal) {
154 invoker = IPCThreadSkeleton::GetDefaultInvoker();
155 } else {
156 invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
157 }
158 if (invoker == nullptr) {
159 ZLOGE(LABEL, "invoker is null, handle:%{public}u proto:%{public}d", handle_, proto_);
160 return ERR_NULL_OBJECT;
161 }
162
163 #ifdef CONFIG_ACTV_BINDER
164 int status = invoker->SendRequest(handle_, code, data, reply, option, invokerData_);
165 #else
166 int status = invoker->SendRequest(handle_, code, data, reply, option);
167 #endif
168 if (status == ERR_DEAD_OBJECT) {
169 MarkObjectDied();
170 }
171 return status;
172 }
173
GetInterfaceDescriptor()174 std::u16string IPCObjectProxy::GetInterfaceDescriptor()
175 {
176 if (!interfaceDesc_.empty()) {
177 return interfaceDesc_;
178 }
179 if (handle_ == 0) {
180 ZLOGD(LABEL, "handle == 0, do nothing");
181 return std::u16string();
182 }
183
184 MessageParcel data, reply;
185 MessageOption option;
186
187 int err = SendRequestInner(false, INTERFACE_TRANSACTION, data, reply, option);
188 if (err != ERR_NONE) {
189 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
190 return std::u16string();
191 }
192 interfaceDesc_ = reply.ReadString16();
193
194 return interfaceDesc_;
195 }
196
GetSessionName()197 std::string IPCObjectProxy::GetSessionName()
198 {
199 MessageParcel data, reply;
200 MessageOption option;
201
202 int err = SendRequestInner(false, GET_SESSION_NAME, data, reply, option);
203 if (err != ERR_NONE) {
204 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
205 return std::string("");
206 }
207 return reply.ReadString();
208 }
209
GetGrantedSessionName()210 std::string IPCObjectProxy::GetGrantedSessionName()
211 {
212 MessageParcel data, reply;
213 MessageOption option;
214
215 int err = SendRequestInner(false, GET_GRANTED_SESSION_NAME, data, reply, option);
216 if (err != ERR_NONE) {
217 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
218 return std::string("");
219 }
220
221 if (reply.ReadUint32() != IRemoteObject::IF_PROT_DATABUS) {
222 ZLOGE(LABEL, "GetDataBusName normal binder");
223 return std::string("");
224 }
225
226 return reply.ReadString();
227 }
228
GetSessionNameForPidUid(uint32_t uid,uint32_t pid)229 std::string IPCObjectProxy::GetSessionNameForPidUid(uint32_t uid, uint32_t pid)
230 {
231 if (pid == static_cast<uint32_t>(getpid())) {
232 ZLOGE(LABEL, "TransDataBusName can't write local pid. my/remotePid:%{public}u/%{public}u", getpid(), pid);
233 return std::string("");
234 }
235
236 MessageParcel data, reply;
237 MessageOption option;
238 if (!data.WriteUint32(pid) || !data.WriteUint32(uid)) {
239 ZLOGE(LABEL, "TransDataBusName write pid/uid:%{public}u/%{public}u failed", pid, uid);
240 return std::string("");
241 }
242 int err = SendRequestInner(false, GET_SESSION_NAME_PID_UID, data, reply, option);
243 if (err != ERR_NONE) {
244 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
245 return std::string("");
246 }
247
248 if (reply.ReadUint32() != IRemoteObject::IF_PROT_DATABUS) {
249 ZLOGE(LABEL, "TransDataBusName normal binder");
250 return std::string("");
251 }
252
253 return reply.ReadString();
254 }
255
GetPidUid(MessageParcel & reply)256 int IPCObjectProxy::GetPidUid(MessageParcel &reply)
257 {
258 MessageParcel data;
259 MessageOption option;
260
261 return SendRequestInner(true, GET_PID_UID, data, reply, option);
262 }
263
OnFirstStrongRef(const void * objectId)264 void IPCObjectProxy::OnFirstStrongRef(const void *objectId)
265 {
266 // IPC proxy: AcquireHandle->AttachObject
267 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
268 if (invoker != nullptr) {
269 invoker->AcquireHandle(handle_);
270 }
271 }
272
WaitForInit()273 void IPCObjectProxy::WaitForInit()
274 {
275 // RPC proxy: AcquireHandle->AttachObject->Open Session->IncRef to Remote Stub
276 {
277 std::lock_guard<std::mutex> lockGuard(initMutex_);
278 // When remote stub is gone, handle is reclaimed. But mapping from this handle to
279 // proxy may still exist before OnLastStrongRef called. If so, in FindOrNewObject
280 // we may find the same proxy that has been marked as dead. Thus, we need to check again.
281 if (IsObjectDead()) {
282 ZLOGW(LABEL, "proxy is dead, init again, handle:%{public}d desc:%{public}s",
283 handle_, Str16ToStr8(remoteDescriptor_).c_str());
284 isRemoteDead_ = false;
285 isFinishInit_ = false;
286 }
287
288 if (!isFinishInit_) {
289 #ifndef CONFIG_IPC_SINGLE
290 if (UpdateProto() == IRemoteObject::IF_PROT_ERROR) {
291 isRemoteDead_ = true;
292 }
293 #endif
294 isFinishInit_ = true;
295 } else {
296 #ifndef CONFIG_IPC_SINGLE
297 // Anoymous rpc proxy need to update proto anyway because ownership of session
298 // corresponding to this handle has been marked as null in TranslateRemoteHandleType
299 if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
300 if (!CheckHaveSession()) {
301 SetProto(IRemoteObject::IF_PROT_ERROR);
302 isRemoteDead_ = true;
303 }
304 }
305 #endif
306 }
307 }
308 #ifndef CONFIG_IPC_SINGLE
309 if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
310 if (IncRefToRemote() != ERR_NONE) {
311 SetProto(IRemoteObject::IF_PROT_ERROR);
312 isRemoteDead_ = true;
313 }
314 }
315 #endif
316 }
317
OnLastStrongRef(const void * objectId)318 void IPCObjectProxy::OnLastStrongRef(const void *objectId)
319 {
320 // IPC proxy: DetachObject->ReleaseHandle
321 // RPC proxy: DecRef to Remote Stub->Close Session->DetachObject->ReleaseHandle
322 ZLOGD(LABEL, "handle:%{public}u proto:%{public}d", handle_, proto_);
323 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
324 if (current == nullptr) {
325 ZLOGE(LABEL, "skeleton is null");
326 return;
327 }
328 #ifndef CONFIG_IPC_SINGLE
329 ReleaseProto();
330 #endif
331 ClearDeathRecipients();
332 // This proxy is going to be destroyed, so we need to decrease refcount of binder_ref.
333 // It may has been replace with a new proxy, thus we have no need to check result.
334 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
335 if (invoker != nullptr) {
336 invoker->ReleaseHandle(handle_);
337 }
338 current->DetachObject(this);
339 }
340
341 /* mutex_ should be called before set or get isRemoteDead_ status */
MarkObjectDied()342 void IPCObjectProxy::MarkObjectDied()
343 {
344 isRemoteDead_ = true;
345 }
346
IsObjectDead() const347 bool IPCObjectProxy::IsObjectDead() const
348 {
349 return isRemoteDead_;
350 }
351
AddDeathRecipient(const sptr<DeathRecipient> & recipient)352 bool IPCObjectProxy::AddDeathRecipient(const sptr<DeathRecipient> &recipient)
353 {
354 std::lock_guard<std::recursive_mutex> lock(mutex_);
355 if (IsObjectDead()) {
356 ZLOGE(LABEL, "proxy is already dead, handle:%{public}d desc:%{public}s",
357 handle_, Str16ToStr8(remoteDescriptor_).c_str());
358 return false;
359 }
360 recipients_.push_back(recipient);
361 if (recipients_.size() > 1 || handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
362 ZLOGD(LABEL, "death recipient is already registered, handle:%{public}d desc:%{public}s",
363 handle_, Str16ToStr8(remoteDescriptor_).c_str());
364 return true;
365 }
366
367 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
368 if (invoker == nullptr) {
369 ZLOGE(LABEL, "invoker is null");
370 return false;
371 }
372
373 if (!invoker->AddDeathRecipient(handle_, this)) {
374 ZLOGE(LABEL, "fail to add binder death recipient, handle:%{public}d desc:%{public}s",
375 handle_, Str16ToStr8(remoteDescriptor_).c_str());
376 ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, std::string(DbinderErrorCode::ERROR_TYPE),
377 DbinderErrorCode::IPC_DRIVER, std::string(DbinderErrorCode::ERROR_CODE),
378 COMMON_DRIVER_SET_DEATH_RECIPIENT_FAILURE, __FUNCTION__);
379 return false;
380 }
381 #ifndef CONFIG_IPC_SINGLE
382 if (proto_ == IRemoteObject::IF_PROT_DATABUS) {
383 if (!AddDbinderDeathRecipient()) {
384 ZLOGE(LABEL, "failed to add dbinder death recipient, handle:%{public}d desc:%{public}s",
385 handle_, Str16ToStr8(remoteDescriptor_).c_str());
386 ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, std::string(DbinderErrorCode::ERROR_TYPE),
387 DbinderErrorCode::RPC_DRIVER, std::string(DbinderErrorCode::ERROR_CODE),
388 COMMON_DRIVER_SET_DEATH_RECIPIENT_FAILURE, __FUNCTION__);
389 return false;
390 }
391 }
392 #endif
393 ZLOGI(LABEL, "success, handle:%{public}d desc:%{public}s", handle_, Str16ToStr8(remoteDescriptor_).c_str());
394 return true;
395 }
396
RemoveDeathRecipient(const sptr<DeathRecipient> & recipient)397 bool IPCObjectProxy::RemoveDeathRecipient(const sptr<DeathRecipient> &recipient)
398 {
399 std::lock_guard<std::recursive_mutex> lock(mutex_);
400
401 if (IsObjectDead()) {
402 ZLOGD(LABEL, "proxy is already dead, handle:%{public}d desc:%{public}s",
403 handle_, Str16ToStr8(remoteDescriptor_).c_str());
404 return false;
405 }
406 bool recipientErased = false;
407 auto it = find(recipients_.begin(), recipients_.end(), recipient);
408 if (it != recipients_.end()) {
409 recipients_.erase(it);
410 recipientErased = true;
411 }
412
413 if (handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE && recipientErased == true) {
414 ZLOGI(LABEL, "death recipient is already unregistered, handle:%{public}d desc:%{public}s",
415 handle_, Str16ToStr8(remoteDescriptor_).c_str());
416 return true;
417 }
418
419 if (recipientErased && recipients_.empty()) {
420 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
421 if (invoker == nullptr) {
422 ZLOGE(LABEL, "invoker is null");
423 return false;
424 }
425
426 bool dbinderStatus = true;
427 bool status = invoker->RemoveDeathRecipient(handle_, this);
428 #ifndef CONFIG_IPC_SINGLE
429 if (proto_ == IRemoteObject::IF_PROT_DATABUS || proto_ == IRemoteObject::IF_PROT_ERROR) {
430 dbinderStatus = RemoveDbinderDeathRecipient();
431 }
432 #endif
433 ZLOGI(LABEL, "result:%{public}d handle:%{public}d desc:%{public}s",
434 status && dbinderStatus, handle_, Str16ToStr8(remoteDescriptor_).c_str());
435 return status && dbinderStatus;
436 }
437 return recipientErased;
438 }
439
SendObituary()440 void IPCObjectProxy::SendObituary()
441 {
442 ZLOGW(LABEL, "handle:%{public}d desc:%{public}s", handle_, Str16ToStr8(remoteDescriptor_).c_str());
443 #ifndef CONFIG_IPC_SINGLE
444 if (handle_ < IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
445 if (proto_ == IRemoteObject::IF_PROT_DATABUS || proto_ == IRemoteObject::IF_PROT_ERROR) {
446 RemoveDbinderDeathRecipient();
447 }
448 }
449 #endif
450 std::vector<sptr<DeathRecipient>> toBeReport;
451 {
452 std::lock_guard<std::recursive_mutex> lock(mutex_);
453 MarkObjectDied();
454 toBeReport = recipients_;
455 recipients_.clear();
456 }
457
458 if (toBeReport.size() > 0 && handle_ < IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
459 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
460 if (invoker != nullptr) {
461 invoker->RemoveDeathRecipient(handle_, this);
462 } else {
463 ZLOGE(LABEL, "invoker is null");
464 }
465 }
466
467 const size_t size = toBeReport.size();
468 for (size_t i = 0; i < size; i++) {
469 sptr<DeathRecipient> recipient = toBeReport[i];
470 if (recipient != nullptr) {
471 ZLOGD(LABEL, "handle:%{public}u call OnRemoteDied begin", handle_);
472 recipient->OnRemoteDied(this);
473 ZLOGD(LABEL, "handle:%{public}u call OnRemoteDied end", handle_);
474 }
475 }
476 }
477
ClearDeathRecipients()478 void IPCObjectProxy::ClearDeathRecipients()
479 {
480 std::lock_guard<std::recursive_mutex> lock(mutex_);
481 if (recipients_.empty()) {
482 return;
483 }
484 recipients_.clear();
485 if (handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
486 return;
487 }
488 IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker();
489 if (invoker != nullptr) {
490 invoker->RemoveDeathRecipient(handle_, this);
491 }
492 #ifndef CONFIG_IPC_SINGLE
493 if (proto_ == IRemoteObject::IF_PROT_DATABUS || proto_ == IRemoteObject::IF_PROT_ERROR) {
494 RemoveDbinderDeathRecipient();
495 }
496 #endif
497 }
498
GetProto() const499 int IPCObjectProxy::GetProto() const
500 {
501 return proto_;
502 }
503
NoticeServiceDie()504 int32_t IPCObjectProxy::NoticeServiceDie()
505 {
506 ZLOGW(LABEL, "handle:%{public}d desc:%{public}s", handle_, Str16ToStr8(remoteDescriptor_).c_str());
507 MessageParcel data;
508 MessageParcel reply;
509 MessageOption option(MessageOption::TF_ASYNC);
510 data.WriteInt32(IRemoteObject::DeathRecipient::NOTICE_DEATH_RECIPIENT);
511
512 int err = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
513 if (err != ERR_NONE || reply.ReadInt32() != ERR_NONE) {
514 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
515 return IPC_PROXY_TRANSACTION_ERR;
516 }
517
518 return ERR_NONE;
519 }
520
InvokeListenThread(MessageParcel & data,MessageParcel & reply)521 int IPCObjectProxy::InvokeListenThread(MessageParcel &data, MessageParcel &reply)
522 {
523 MessageOption option;
524 return SendRequestInner(false, INVOKE_LISTEN_THREAD, data, reply, option);
525 }
526
527 #ifndef CONFIG_IPC_SINGLE
UpdateProto()528 int IPCObjectProxy::UpdateProto()
529 {
530 int proto = GetProtoInfo();
531 SetProto(proto);
532 return proto;
533 }
534
IncRefToRemote()535 int32_t IPCObjectProxy::IncRefToRemote()
536 {
537 MessageParcel data, reply;
538 MessageOption option;
539
540 int32_t err = SendRequestInner(false, DBINDER_INCREFS_TRANSACTION, data, reply, option);
541 if (err != ERR_NONE) {
542 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
543 // do nothing
544 }
545 return err;
546 }
547
548
ReleaseProto()549 void IPCObjectProxy::ReleaseProto()
550 {
551 switch (GetProto()) {
552 case IRemoteObject::IF_PROT_BINDER: {
553 ReleaseBinderProto();
554 break;
555 }
556 case IRemoteObject::IF_PROT_DATABUS:
557 case IRemoteObject::IF_PROT_ERROR: {
558 ReleaseDatabusProto();
559 break;
560 }
561 default: {
562 ZLOGE(LABEL, "release invalid proto:%{public}d", proto_);
563 break;
564 }
565 }
566 }
567
SetProto(int proto)568 void IPCObjectProxy::SetProto(int proto)
569 {
570 proto_ = proto;
571 }
572
GetProtoInfo()573 int IPCObjectProxy::GetProtoInfo()
574 {
575 if (CheckHaveSession()) {
576 return IRemoteObject::IF_PROT_DATABUS;
577 }
578 if (handle_ >= IPCProcessSkeleton::DBINDER_HANDLE_BASE) {
579 ZLOGE(LABEL, "cannot find session for handle:%{public}u", handle_);
580 return IRemoteObject::IF_PROT_ERROR;
581 }
582
583 MessageParcel data, reply;
584 MessageOption option;
585 int err = SendRequestInner(true, GET_PROTO_INFO, data, reply, option);
586 if (err != ERR_NONE && err != -EBADMSG) {
587 ZLOGW(LABEL, "GET_PROTO_INFO transact return error:%{public}d", err);
588 return IRemoteObject::IF_PROT_ERROR;
589 }
590
591 switch (reply.ReadUint32()) {
592 case IRemoteObject::IF_PROT_BINDER: {
593 remoteDescriptor_ = reply.ReadString16();
594 ZLOGD(LABEL, "binder, handle:%{public}u desc:%{public}s",
595 handle_, Str16ToStr8(remoteDescriptor_).c_str());
596 break;
597 }
598 case IRemoteObject::IF_PROT_DATABUS: {
599 if (UpdateDatabusClientSession(handle_, reply)) {
600 remoteDescriptor_ = reply.ReadString16();
601 ZLOGD(LABEL, "dbinder, handle:%{public}u desc:%{public}s",
602 handle_, Str16ToStr8(remoteDescriptor_).c_str());
603 return IRemoteObject::IF_PROT_DATABUS;
604 } else {
605 ZLOGE(LABEL, "UpdateDatabusClientSession failed");
606 return IRemoteObject::IF_PROT_ERROR;
607 }
608 }
609 default: {
610 ZLOGE(LABEL, "get Invalid proto");
611 return IRemoteObject::IF_PROT_ERROR;
612 }
613 }
614
615 return IRemoteObject::IF_PROT_BINDER;
616 }
617
AddDbinderDeathRecipient()618 bool IPCObjectProxy::AddDbinderDeathRecipient()
619 {
620 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
621 if (current == nullptr) {
622 ZLOGW(LABEL, "get current fail, handle:%{public}d desc:%{public}s",
623 handle_, Str16ToStr8(remoteDescriptor_).c_str());
624 return false;
625 }
626
627 if (current->QueryCallbackStub(this) != nullptr) {
628 ZLOGW(LABEL, "already attach callback stub, handle:%{public}d desc:%{public}s",
629 handle_, Str16ToStr8(remoteDescriptor_).c_str());
630 return true;
631 }
632
633 //note that cannot use this proxy's descriptor
634 sptr<IPCObjectStub> callbackStub = new (std::nothrow) IPCObjectStub(u"DbinderDeathRecipient" + remoteDescriptor_);
635 if (callbackStub == nullptr) {
636 ZLOGE(LABEL, "create IPCObjectStub object failed, handle:%{public}d desc:%{public}s",
637 handle_, Str16ToStr8(remoteDescriptor_).c_str());
638 return false;
639 }
640 if (!current->AttachCallbackStub(this, callbackStub)) {
641 ZLOGW(LABEL, "already attach new callback stub, handle:%{public}d desc:%{public}s",
642 handle_, Str16ToStr8(remoteDescriptor_).c_str());
643 return false;
644 }
645
646 MessageParcel data;
647 MessageParcel reply;
648 MessageOption option(MessageOption::TF_SYNC);
649 data.WriteInt32(IRemoteObject::DeathRecipient::ADD_DEATH_RECIPIENT);
650 data.WriteRemoteObject(callbackStub);
651
652 int err = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
653 if (err != ERR_NONE) {
654 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
655 current->DetachCallbackStub(this);
656 return false;
657 }
658
659 return true;
660 }
661
RemoveDbinderDeathRecipient()662 bool IPCObjectProxy::RemoveDbinderDeathRecipient()
663 {
664 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
665 if (current == nullptr) {
666 ZLOGE(LABEL, "get current fail");
667 return false;
668 }
669 ZLOGW(LABEL, "handle:%{public}d desc:%{public}s", handle_, Str16ToStr8(remoteDescriptor_).c_str());
670 sptr<IPCObjectStub> callbackStub = current->DetachCallbackStub(this);
671 if (callbackStub == nullptr) {
672 ZLOGE(LABEL, "get callbackStub fail, handle:%{public}d desc:%{public}s",
673 handle_, Str16ToStr8(remoteDescriptor_).c_str());
674 return false;
675 }
676
677 MessageParcel data;
678 MessageParcel reply;
679 MessageOption option(MessageOption::TF_SYNC);
680 data.WriteInt32(IRemoteObject::DeathRecipient::REMOVE_DEATH_RECIPIENT);
681 data.WriteRemoteObject(callbackStub);
682
683 int err = SendLocalRequest(DBINDER_OBITUARY_TRANSACTION, data, reply, option);
684 if (err != ERR_NONE) {
685 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
686 // do nothing, even send request failed
687 }
688 return err == ERR_NONE;
689 }
690
CheckHaveSession()691 bool IPCObjectProxy::CheckHaveSession()
692 {
693 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
694 if (current == nullptr) {
695 ZLOGE(LABEL, "IPCProcessSkeleton is null");
696 return false;
697 }
698
699 return current->ProxyMoveDBinderSession(handle_, this);
700 }
701
UpdateDatabusClientSession(int handle,MessageParcel & reply)702 bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply)
703 {
704 DBinderDatabusInvoker *invoker =
705 reinterpret_cast<DBinderDatabusInvoker *>(IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DATABUS));
706 if (invoker == nullptr) {
707 ZLOGE(LABEL, "invoker is null");
708 return false;
709 }
710
711 uint64_t stubIndex = reply.ReadUint64();
712 std::string serviceName = reply.ReadString();
713 std::string peerID = reply.ReadString();
714 std::string localID = reply.ReadString();
715 std::string localBusName = reply.ReadString();
716 uint32_t peerTokenId = reply.ReadUint32();
717
718 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
719 if (current == nullptr) {
720 ZLOGE(LABEL, "skeleton is nullptr");
721 return false;
722 }
723
724 std::shared_ptr<DBinderSessionObject> dbinderSession = std::make_shared<DBinderSessionObject>(
725 nullptr, serviceName, peerID, stubIndex, this, peerTokenId);
726 if (dbinderSession == nullptr) {
727 ZLOGE(LABEL, "make DBinderSessionObject fail!");
728 return false;
729 }
730
731 if (!current->CreateSoftbusServer(localBusName)) {
732 ZLOGE(LABEL, "create softbus server fail, name:%{public}s localID:%{public}s", localBusName.c_str(),
733 IPCProcessSkeleton::ConvertToSecureString(localID).c_str());
734 return false;
735 }
736
737 if (!invoker->UpdateClientSession(dbinderSession)) {
738 // no need to remove softbus server
739 ZLOGE(LABEL, "update server session object fail!");
740 return false;
741 }
742 if (!current->ProxyAttachDBinderSession(handle, dbinderSession)) {
743 // should not get here
744 ZLOGW(LABEL, "fail to attach session for handle:%{public}d, maybe a concurrent scenarios", handle);
745 if (current->QuerySessionByInfo(serviceName, peerID) == nullptr) {
746 ZLOGE(LABEL, "session is not exist, service:%{public}s devId:%{public}s",
747 serviceName.c_str(), IPCProcessSkeleton::ConvertToSecureString(peerID).c_str());
748 dbinderSession->CloseDatabusSession();
749 return false;
750 }
751 }
752 return true;
753 }
754
ReleaseDatabusProto()755 void IPCObjectProxy::ReleaseDatabusProto()
756 {
757 if (handle_ == 0) {
758 ZLOGW(LABEL, "handle == 0, do nothing");
759 return;
760 }
761
762 MessageParcel data, reply;
763 MessageOption option = { MessageOption::TF_ASYNC };
764 int err = SendRequestInner(false, DBINDER_DECREFS_TRANSACTION, data, reply, option);
765 if (err != ERR_NONE) {
766 PRINT_SEND_REQUEST_FAIL_INFO(handle_, err, Str16ToStr8(remoteDescriptor_));
767 // do nothing, if this cmd failed, stub's refcount will be decreased when OnSessionClosed called
768 }
769
770 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
771 if (current == nullptr) {
772 ZLOGE(LABEL, "release databus proto skeleton is null");
773 return;
774 }
775 std::shared_ptr<DBinderSessionObject> toBeDelete = current->ProxyDetachDBinderSession(handle_, this);
776 if (toBeDelete != nullptr &&
777 // make sure session corresponding to this sessionName and deviceId is no longer used by other proxy
778 current->QuerySessionByInfo(toBeDelete->GetServiceName(), toBeDelete->GetDeviceId()) == nullptr) {
779 // close session in lock
780 toBeDelete->CloseDatabusSession();
781 }
782 }
783
ReleaseBinderProto()784 void IPCObjectProxy::ReleaseBinderProto()
785 {
786 // do nothing
787 }
788
GetStrongRefCountForStub()789 uint32_t IPCObjectProxy::GetStrongRefCountForStub()
790 {
791 BinderInvoker *invoker = reinterpret_cast<BinderInvoker *>(IPCThreadSkeleton::GetDefaultInvoker());
792 if (invoker == nullptr) {
793 ZLOGE(LABEL, "get default invoker failed");
794 return 0; // 0 means get failed
795 }
796 return invoker->GetStrongRefCountForStub(handle_);
797 }
798 #endif
799 } // namespace OHOS
800