diff --git a/bundle.json b/bundle.json index 8eb86a07..c4d2e5e5 100644 --- a/bundle.json +++ b/bundle.json @@ -37,7 +37,8 @@ "access_token", "dsoftbus", "napi", - "common" + "common", + "build_framework" ], "third_party": [ "libuv", diff --git a/interfaces/innerkits/rust/src/ipc/remote_obj.rs b/interfaces/innerkits/rust/src/ipc/remote_obj.rs index afbdd0b6..00463341 100644 --- a/interfaces/innerkits/rust/src/ipc/remote_obj.rs +++ b/interfaces/innerkits/rust/src/ipc/remote_obj.rs @@ -21,7 +21,7 @@ use crate::{ MsgParcel, BorrowedMsgParcel, AsRawPtr, IpcStatusCode, parcel::vec_u16_to_string, parse_status_code, }; -use crate::ipc_binding::{CRemoteObject, CDeathRecipient}; +use crate::ipc_binding::{CRemoteObject, CDeathRecipient, CIRemoteObject}; use crate::parcel::parcelable::{Serialize, Deserialize, allocate_vec_with_buffer}; use std::ffi::{c_void, CString, c_char}; use crate::String16; @@ -59,6 +59,26 @@ impl RemoteObj { pub unsafe fn as_inner(&self) -> *mut CRemoteObject { self.0.as_ptr() } + + /// Convert an `RemoteObj` by `CIRemoteObject` pointer. + pub fn from_raw_ciremoteobj(obj: *mut CIRemoteObject) -> Option { + if obj.is_null() { + None + } else { + // SAFETY: he returned CIRemoteObject may be a null pointer + unsafe { + let sa = ipc_binding::CreateCRemoteObject(obj as *mut _ as *mut c_void); + RemoteObj::from_raw(sa) + } + } + } + + /// Extract a raw `CIRemoteObject` pointer from this wrapper. + /// # Safety + /// The returned CIRemoteObject may be a null pointer + pub unsafe fn as_raw_ciremoteobj(&self) -> *mut CIRemoteObject { + ipc_binding::GetCIRemoteObject(self.0.as_ptr()) as *mut CIRemoteObject + } } impl IRemoteObj for RemoteObj { diff --git a/interfaces/innerkits/rust/src/ipc_binding.rs b/interfaces/innerkits/rust/src/ipc_binding.rs index 3438ba0e..9d12d3fa 100644 --- a/interfaces/innerkits/rust/src/ipc_binding.rs +++ b/interfaces/innerkits/rust/src/ipc_binding.rs @@ -22,6 +22,11 @@ pub struct CRemoteObject { _private: [u8; 0], } +#[repr(C)] +pub struct CIRemoteObject { + _private: [u8; 0], +} + #[repr(C)] pub struct CDeathRecipient { _private: [u8; 0], @@ -135,6 +140,8 @@ pub type OnCParcelReadElement = unsafe extern "C" fn ( // C interface for IPC core object extern "C" { + pub fn CreateCRemoteObject(object: *mut c_void) -> *mut CRemoteObject; + pub fn GetCIRemoteObject(object: *mut CRemoteObject) -> *mut c_void; pub fn CreateRemoteStub(descripor: *const c_char, on_remote_request: OnRemoteRequest, on_remote_object_destroy: OnRemoteObjectDestroy, user_data: *const c_void, on_remote_dump: OnRemoteDump) -> *mut CRemoteObject; diff --git a/ipc/native/src/c_wrapper/include/c_remote_object.h b/ipc/native/src/c_wrapper/include/c_remote_object.h index 70646c07..1ab7c6a1 100644 --- a/ipc/native/src/c_wrapper/include/c_remote_object.h +++ b/ipc/native/src/c_wrapper/include/c_remote_object.h @@ -30,7 +30,7 @@ struct CDeathRecipient; typedef struct CDeathRecipient CDeathRecipient; // Callback as remote stub -typedef int (*OnRemoteRequestCb)(const void *userData, int code, +typedef int (*OnRemoteRequestCb)(const void *userData, int code, const CParcel *data, CParcel *reply); typedef int (*OnRemoteDumpCb)(const void *userData, const CParcel *data); typedef void (*OnRemoteObjectDestroyCb)(const void *userData); @@ -40,6 +40,8 @@ typedef void (*OnDeathRecipientDestroyCb)(const void *userData); typedef bool (*On16BytesAllocator)(void *stringData, uint16_t **buffer, int32_t len); +CRemoteObject *CreateCRemoteObject(void *obj); +void *GetCIRemoteObject(CRemoteObject* obj); CRemoteObject *CreateRemoteStub(const char *desc, OnRemoteRequestCb callback, OnRemoteObjectDestroyCb destroy, const void *userData, OnRemoteDumpCb dumpCallback); diff --git a/ipc/native/src/c_wrapper/source/c_remote_object.cpp b/ipc/native/src/c_wrapper/source/c_remote_object.cpp index 625b23e5..5bba9878 100644 --- a/ipc/native/src/c_wrapper/source/c_remote_object.cpp +++ b/ipc/native/src/c_wrapper/source/c_remote_object.cpp @@ -289,4 +289,37 @@ bool GetInterfaceDescriptor(CRemoteObject *object, void *value, On16BytesAllocat return false; } return true; +} + +CRemoteObject *CreateCRemoteObject(void *obj) +{ + if (obj == nullptr) { + ZLOGE(LOG_LABEL, "%{public}s: recipient is null\n", __func__); + return nullptr; + } + + CRemoteObject *holder = new (std::nothrow) CRemoteObjectHolder(); + if (holder == nullptr) { + ZLOGE(LOG_LABEL, "%{public}s: create proxy holder failed\n", __func__); + return nullptr; + } + sptr sa = reinterpret_cast(obj); + holder->IncStrongRef(nullptr); + holder->remote_ = sa; + + return holder; +} + +void *GetCIRemoteObject(CRemoteObject* obj) +{ + if (!IsValidRemoteObject(obj, __func__)) { + ZLOGE(LOG_LABEL, "%{public}s: recipient is null\n", __func__); + return nullptr; + } + + if (obj->remote_ == nullptr) { + ZLOGI(LOG_LABEL, "%{public}s: The pointer inside CRemoteObject is a null pointer\n", __func__); + return nullptr; + } + return obj->remote_.GetRefPtr(); } \ No newline at end of file diff --git a/ipc/native/test/unittest/rust/client/src/main.rs b/ipc/native/test/unittest/rust/client/src/main.rs index c5b3a2e1..123f2bc1 100644 --- a/ipc/native/test/unittest/rust/client/src/main.rs +++ b/ipc/native/test/unittest/rust/client/src/main.rs @@ -13,7 +13,7 @@ * limitations under the License. */ -#![allow(clippy::needless_borrow)] +#![allow(clippy::needless_borrow)] #![allow(clippy::bool_assert_comparison)] #![allow(non_snake_case)] extern crate ipc_rust; @@ -28,6 +28,7 @@ use ipc_rust::{ get_self_token_id, get_calling_pid, get_calling_uid, IMsgParcel, IpcResult, RawData, set_max_work_thread, reset_calling_identity, set_calling_identity, is_local_calling, get_local_device_id, get_calling_device_id, IpcStatusCode, + RemoteObj, }; use ipc_rust::{Serialize, Deserialize, BorrowedMsgParcel, Ashmem}; @@ -806,4 +807,16 @@ fn test_get_interface_descriptor() { let descriptor = String16::new(TestProxy::get_descriptor()); let ret = remote.interface_descriptor().expect("get interface descriptor failed"); assert_eq!(descriptor.get_string(), ret); -} \ No newline at end of file +} + +#[test] +fn test_get_interface_descriptor_002() { + let remote = get_service(IPC_TEST_SERVICE_ID).expect("get itest service failed"); + // SAFETY: + let remote = unsafe { + RemoteObj::from_raw_ciremoteobj(remote.as_raw_ciremoteobj()).unwrap() + }; + let descriptor = String16::new(TestProxy::get_descriptor()); + let ret = remote.interface_descriptor().expect("get interface descriptor failed"); + assert_eq!(descriptor.get_string(), ret); +} diff --git a/ipc/native/test/unittest/rust/server/src/main.rs b/ipc/native/test/unittest/rust/server/src/main.rs index 63a4fd6f..721c7f2e 100644 --- a/ipc/native/test/unittest/rust/server/src/main.rs +++ b/ipc/native/test/unittest/rust/server/src/main.rs @@ -138,5 +138,5 @@ fn main() { add_service(&service.as_object().expect("get ITest service failed"), IPC_TEST_SERVICE_ID).expect("add server to samgr failed"); println!("join to ipc work thread"); - join_work_thread(); + join_work_thread(); } \ No newline at end of file