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
14use std::mem;
15use std::sync::Arc;
16
17use cxx::UniquePtr;
18
19use super::wrapper::{
20    CloneRemoteObj, DeathRecipientRemoveHandler, FromCIRemoteObject, FromSptrRemote, IRemoteObject,
21    IRemoteObjectWrapper, RemoteStubWrapper, SptrIRemoteObject,
22};
23use super::RemoteStub;
24use crate::errors::{IpcResult, IpcStatusCode};
25use crate::ipc_async::{IpcAsyncRuntime, Runtime};
26use crate::parcel::msg::ParcelMem;
27use crate::parcel::{MsgOption, MsgParcel};
28
29/// Remote Object
30pub struct RemoteObj {
31    pub(crate) inner: UniquePtr<IRemoteObjectWrapper>,
32}
33
34impl Clone for RemoteObj {
35    fn clone(&self) -> Self {
36        Self {
37            inner: CloneRemoteObj(self.inner.as_ref().unwrap()),
38        }
39    }
40}
41
42unsafe impl Send for RemoteObj {}
43unsafe impl Sync for RemoteObj {}
44
45pub struct RecipientRemoveHandler {
46    inner: UniquePtr<DeathRecipientRemoveHandler>,
47}
48
49impl RemoteObj {
50    /// Creates a Remote Object from C++ IRemoteObejectWrapper.
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.
59    pub unsafe fn new_unchecked(wrap: UniquePtr<IRemoteObjectWrapper>) -> Self {
60        Self { inner: wrap }
61    }
62
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.
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
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
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
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.
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.
143    pub fn is_proxy(&self) -> bool {
144        self.inner.IsProxyObject()
145    }
146
147    /// Dumps a service through a String
148    pub fn dump(&self, fd: i32, args: &[String]) -> i32 {
149        self.inner.Dump(fd, args)
150    }
151
152    ///
153    pub fn check_legalit(&self) -> bool {
154        self.inner.CheckObjectLegality()
155    }
156
157    /// Returns true if the object is dead.
158    pub fn is_dead(&self) -> bool {
159        self.inner.IsObjectDead()
160    }
161
162    /// Returns interface descriptor.
163    pub fn interface_descriptor(&self) -> IpcResult<String> {
164        Ok(self.inner.GetInterfaceDescriptor())
165    }
166
167    /// Returns Object descriptor.
168    pub fn object_descriptor(&self) -> IpcResult<String> {
169        Ok(self.inner.GetObjectDescriptor())
170    }
171}
172
173impl RecipientRemoveHandler {
174    pub fn remove_recipient(self) {
175        self.inner.remove();
176    }
177}
178