1 // Copyright (C) 2024 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::mem;
15 use std::sync::Arc;
16 
17 use cxx::UniquePtr;
18 
19 use super::wrapper::{
20     CloneRemoteObj, DeathRecipientRemoveHandler, FromCIRemoteObject, FromSptrRemote, IRemoteObject,
21     IRemoteObjectWrapper, RemoteStubWrapper, SptrIRemoteObject,
22 };
23 use super::RemoteStub;
24 use crate::errors::{IpcResult, IpcStatusCode};
25 use crate::ipc_async::{IpcAsyncRuntime, Runtime};
26 use crate::parcel::msg::ParcelMem;
27 use crate::parcel::{MsgOption, MsgParcel};
28 
29 /// Remote Object
30 pub struct RemoteObj {
31     pub(crate) inner: UniquePtr<IRemoteObjectWrapper>,
32 }
33 
34 impl Clone for RemoteObj {
clone(&self) -> Self35     fn clone(&self) -> Self {
36         Self {
37             inner: CloneRemoteObj(self.inner.as_ref().unwrap()),
38         }
39     }
40 }
41 
42 unsafe impl Send for RemoteObj {}
43 unsafe impl Sync for RemoteObj {}
44 
45 pub struct RecipientRemoveHandler {
46     inner: UniquePtr<DeathRecipientRemoveHandler>,
47 }
48 
49 impl RemoteObj {
50     /// Creates a Remote Object from C++ IRemoteObejectWrapper.
try_new(wrap: UniquePtr<IRemoteObjectWrapper>) -> Option<Self>51     pub fn try_new(wrap: UniquePtr<IRemoteObjectWrapper>) -> Option<Self> {
52         if wrap.is_null() {
53             return None;
54         }
55         Some(Self { inner: wrap })
56     }
57 
58     /// Creates a Remote Object from C++ IRemoteObejectWrapper.
new_unchecked(wrap: UniquePtr<IRemoteObjectWrapper>) -> Self59     pub unsafe fn new_unchecked(wrap: UniquePtr<IRemoteObjectWrapper>) -> Self {
60         Self { inner: wrap }
61     }
62 
from_ciremote(remote: *mut IRemoteObject) -> Option<Self>63     pub unsafe fn from_ciremote(remote: *mut IRemoteObject) -> Option<Self> {
64         if remote.is_null() {
65             return None;
66         }
67 
68         let inner = FromCIRemoteObject(remote);
69         if inner.is_null() {
70             return None;
71         }
72 
73         Some(Self { inner })
74     }
75 
76     /// Creates a RemoteObj from RemoteStub.
from_stub<T: RemoteStub + 'static>(stub: T) -> Option<Self>77     pub fn from_stub<T: RemoteStub + 'static>(stub: T) -> Option<Self> {
78         RemoteStubWrapper::new(stub).into_remote()
79     }
80 
81     /// Creates a RemoteObj from sptr
from_sptr(sptr: UniquePtr<SptrIRemoteObject>) -> Option<Self>82     pub fn from_sptr(sptr: UniquePtr<SptrIRemoteObject>) -> Option<Self> {
83         Self::try_new(FromSptrRemote(sptr))
84     }
85 
86     /// Sends a IPC request to remote service
send_request(&self, code: u32, data: &mut MsgParcel) -> IpcResult<MsgParcel>87     pub fn send_request(&self, code: u32, data: &mut MsgParcel) -> IpcResult<MsgParcel> {
88         let mut reply = MsgParcel::new();
89         let mut option = MsgOption::new();
90         match mem::replace(&mut data.inner, ParcelMem::Null) {
91             ParcelMem::Unique(mut p) => {
92                 let res = self.inner.SendRequest(
93                     code,
94                     p.pin_mut(),
95                     reply.pin_mut().unwrap(),
96                     option.inner.pin_mut(),
97                 );
98                 data.inner = ParcelMem::Unique(p);
99                 if res != 0 {
100                     return Err(IpcStatusCode::Failed);
101                 }
102                 Ok(reply)
103             }
104             _ => Err(IpcStatusCode::Failed),
105         }
106     }
107 
108     /// Sends asynchronous IPC requests to remote services, The current
109     /// interface will use ylong runtime to start a separate thread to execute
110     /// requests
async_send_request<F, R>( self: &Arc<Self>, code: u32, mut data: MsgParcel, mut option: MsgOption, call_back: F, ) where F: FnOnce(MsgParcel) -> R, F: Send + 'static, R: Send + 'static,111     pub fn async_send_request<F, R>(
112         self: &Arc<Self>,
113         code: u32,
114         mut data: MsgParcel,
115         mut option: MsgOption,
116         call_back: F,
117     ) where
118         F: FnOnce(MsgParcel) -> R,
119         F: Send + 'static,
120         R: Send + 'static,
121     {
122         let remote = self.clone();
123         Runtime::spawn_blocking(move || {
124             let reply = remote.send_request(code, &mut data);
125             match reply {
126                 Ok(reply) => {
127                     call_back(reply);
128                     IpcStatusCode::Ok
129                 }
130                 _ => IpcStatusCode::Failed,
131             }
132         });
133     }
134 
135     /// Registries a death recipient, and returns a RecipientRemoveHandler, if
136     /// the registration is successful.
add_death_recipient(&self, f: fn(Box<RemoteObj>)) -> Option<RecipientRemoveHandler>137     pub fn add_death_recipient(&self, f: fn(Box<RemoteObj>)) -> Option<RecipientRemoveHandler> {
138         let inner = self.inner.AddDeathRecipient(f);
139         inner.is_null().then_some(RecipientRemoveHandler { inner })
140     }
141 
142     /// Returns true if it is a proxy object.
is_proxy(&self) -> bool143     pub fn is_proxy(&self) -> bool {
144         self.inner.IsProxyObject()
145     }
146 
147     /// Dumps a service through a String
dump(&self, fd: i32, args: &[String]) -> i32148     pub fn dump(&self, fd: i32, args: &[String]) -> i32 {
149         self.inner.Dump(fd, args)
150     }
151 
152     ///
check_legalit(&self) -> bool153     pub fn check_legalit(&self) -> bool {
154         self.inner.CheckObjectLegality()
155     }
156 
157     /// Returns true if the object is dead.
is_dead(&self) -> bool158     pub fn is_dead(&self) -> bool {
159         self.inner.IsObjectDead()
160     }
161 
162     /// Returns interface descriptor.
interface_descriptor(&self) -> IpcResult<String>163     pub fn interface_descriptor(&self) -> IpcResult<String> {
164         Ok(self.inner.GetInterfaceDescriptor())
165     }
166 
167     /// Returns Object descriptor.
object_descriptor(&self) -> IpcResult<String>168     pub fn object_descriptor(&self) -> IpcResult<String> {
169         Ok(self.inner.GetObjectDescriptor())
170     }
171 }
172 
173 impl RecipientRemoveHandler {
remove_recipient(self)174     pub fn remove_recipient(self) {
175         self.inner.remove();
176     }
177 }
178