• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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