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