diff --git a/bundle.json b/bundle.json index 85623d033bd79df0decc9cb8046070e61b29a9ab..8eb86a075bde9ad8219888c6a7955705ded19ddc 100644 --- a/bundle.json +++ b/bundle.json @@ -36,7 +36,8 @@ "c_utils", "access_token", "dsoftbus", - "napi" + "napi", + "common" ], "third_party": [ "libuv", diff --git a/interfaces/innerkits/rust/src/ipc/macros.rs b/interfaces/innerkits/rust/src/ipc/macros.rs index d1a97947e5a732f1a76636f2b7e3d8705efdceb5..fcd0c01f0ebc1318d7f604b6b4fa7b2babce5506 100644 --- a/interfaces/innerkits/rust/src/ipc/macros.rs +++ b/interfaces/innerkits/rust/src/ipc/macros.rs @@ -97,6 +97,9 @@ macro_rules! define_remote_object { } } } + fn on_dump(&self, file: &$crate::FileDesc, args: &mut Vec<$crate::String16>) -> i32 { + self.0.dump(file, args) + } } impl $crate::FromRemoteObj for dyn $remote_broker { diff --git a/interfaces/innerkits/rust/src/ipc/mod.rs b/interfaces/innerkits/rust/src/ipc/mod.rs index 5f617de04b4a6e436dfbdd6828fba415ccf156d1..699ab224507d6549522f908afe56e1262d985f15 100644 --- a/interfaces/innerkits/rust/src/ipc/mod.rs +++ b/interfaces/innerkits/rust/src/ipc/mod.rs @@ -17,7 +17,10 @@ pub mod remote_obj; pub mod remote_stub; pub mod macros; -use crate::{BorrowedMsgParcel, MsgParcel, IpcResult, DeathRecipient,}; +use crate::{ + BorrowedMsgParcel, MsgParcel, IpcResult, DeathRecipient, + FileDesc, IpcStatusCode, +}; use std::ops::{Deref}; use std::cmp::Ordering; use crate::String16; @@ -39,7 +42,7 @@ pub trait IRemoteObj { /// Determine whether it is a proxy object fn is_proxy(&self) -> bool; - /// Dump a service through a string + /// Dump a service through a String16 fn dump(&self, fd: i32, args: &mut Vec) -> i32; /// Judge whether the object is dead @@ -56,6 +59,9 @@ pub trait IRemoteStub: Send + Sync { /// Callback for deal IPC request fn on_remote_request(&self, code: u32, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> i32; + + /// Callback for IPC dump + fn on_dump(&self, file: &FileDesc, args: &mut Vec) -> i32; } /// Like C++ IRemoteBroker class @@ -64,6 +70,11 @@ pub trait IRemoteBroker: Send + Sync { fn as_object(&self) -> Option { panic!("This is not a RemoteObject.") } + /// Default dump + fn dump(&self, _file: &FileDesc, _args: &mut Vec) -> i32 { + println!("This is the default dump function, and you can override it to implement your own dump function"); + IpcStatusCode::Ok as i32 + } } /// Define function which how to convert a RemoteObj to RemoteObjRef, the later contains a diff --git a/interfaces/innerkits/rust/src/ipc/remote_obj.rs b/interfaces/innerkits/rust/src/ipc/remote_obj.rs index 3236600bd4d3a8e209222b11196775bab142d581..afbdd0b662d4133aa1566f5e419e661c64210fec 100644 --- a/interfaces/innerkits/rust/src/ipc/remote_obj.rs +++ b/interfaces/innerkits/rust/src/ipc/remote_obj.rs @@ -17,14 +17,21 @@ use std::ptr; use crate::{ - ipc_binding, IRemoteObj, DeathRecipient, IpcResult, IpcStatusCode, - MsgParcel, BorrowedMsgParcel, AsRawPtr, parcel::on_string16_writer, + ipc_binding, IRemoteObj, DeathRecipient, IpcResult, + MsgParcel, BorrowedMsgParcel, AsRawPtr, IpcStatusCode, parcel::vec_u16_to_string, parse_status_code, }; use crate::ipc_binding::{CRemoteObject, CDeathRecipient}; use crate::parcel::parcelable::{Serialize, Deserialize, allocate_vec_with_buffer}; -use std::ffi::{c_void}; +use std::ffi::{c_void, CString, c_char}; use crate::String16; +use hilog_rust::{error, hilog, HiLogLabel, LogType}; + +const LOG_LABEL: HiLogLabel = HiLogLabel { + log_type: LogType::LogCore, + domain: 0xd001510, + tag: "RustRemoteObj" +}; pub mod death_recipient; pub mod cmp; @@ -93,11 +100,24 @@ impl IRemoteObj for RemoteObj { } fn dump(&self, fd: i32, args: &mut Vec) -> i32 { - let slice = &args[..]; - // SAFETY: - unsafe { - ipc_binding::Dump(self.as_inner(), fd, slice.as_ptr() as *const c_void, - slice.len().try_into().unwrap(), on_string16_writer) + let mut parcel = match MsgParcel::new() { + Some(parcel) => parcel, + None => { + error!(LOG_LABEL, "create MsgParcel failed"); + return IpcStatusCode::Failed as i32; + } + }; + match parcel.write::>(args) { + Ok(_) => { + // SAFETY: `parcel` always contains a valid pointer to a `CParcel` + unsafe { + ipc_binding::Dump(self.as_inner(), fd, parcel.into_raw()) + } + } + _ => { + error!(LOG_LABEL, "create MsgParcel failed"); + IpcStatusCode::Failed as i32 + } } } diff --git a/interfaces/innerkits/rust/src/ipc/remote_stub.rs b/interfaces/innerkits/rust/src/ipc/remote_stub.rs index c86b44422fad12ec4c05f81531f3f32efb3a5815..3e3dc446119a6828e291e951eb44d8404ab518ea 100644 --- a/interfaces/innerkits/rust/src/ipc/remote_stub.rs +++ b/interfaces/innerkits/rust/src/ipc/remote_stub.rs @@ -13,11 +13,14 @@ * limitations under the License. */ -use crate::{ipc_binding, IRemoteStub, IRemoteBroker, RemoteObj, BorrowedMsgParcel}; +use crate::{ + ipc_binding, IRemoteStub, IRemoteBroker, IpcStatusCode, + RemoteObj, BorrowedMsgParcel, FileDesc, String16, +}; use crate::ipc_binding::{CRemoteObject, CParcel}; use std::ffi::{c_void, CString, c_char}; use std::ops::{Deref}; -use hilog_rust::{info, hilog, HiLogLabel, LogType}; +use hilog_rust::{info, error, hilog, HiLogLabel, LogType}; const LOG_LABEL: HiLogLabel = HiLogLabel { log_type: LogType::LogCore, @@ -49,8 +52,9 @@ impl RemoteStub { // set rust object pointer to native, so we can figure out who deal // the request during on_remote_request(). ipc_binding::CreateRemoteStub(descripor.as_ptr(), Self::on_remote_request, - Self::on_destroy, rust as *mut c_void) + Self::on_destroy, rust as *mut c_void, Self::on_dump) }; + if native.is_null() { None } else { @@ -108,6 +112,8 @@ impl RemoteStub { unsafe extern "C" fn on_remote_request(user_data: *mut c_void, code: u32, data: *const CParcel, reply: *mut CParcel) -> i32 { let res = { + // BorrowedMsgParcel calls the correlation function from_raw must return as Some, + // direct deconstruction will not crash. let mut reply = BorrowedMsgParcel::from_raw(reply).unwrap(); let data = BorrowedMsgParcel::from_raw(data as *mut CParcel).unwrap(); let rust_object: &T = &*(user_data as *mut T); @@ -119,6 +125,34 @@ impl RemoteStub { /// /// The parameters passed in should ensure FFI safety /// user_data pointer, data pointer and reply pointer on the c side must be guaranteed not to be null + unsafe extern "C" fn on_dump(user_data: *mut c_void, data: *const CParcel) -> i32 { + let res = { + let rust_object: &T = &*(user_data as *mut T); + // BorrowedMsgParcel calls the correlation functio from_raw must return as Some, + // direct deconstruction will not crash. + let data = BorrowedMsgParcel::from_raw(data as *mut CParcel).unwrap(); + let file: FileDesc = match data.read::() { + Ok(file) => file, + _ => { + error!(LOG_LABEL, "read FileDesc failed"); + return IpcStatusCode::Failed as i32; + } + }; + let mut args: Vec = match data.read::>() { + Ok(args) => args, + _ => { + error!(LOG_LABEL, "read String16 array failed"); + return IpcStatusCode::Failed as i32; + } + }; + rust_object.on_dump(&file, &mut args) + }; + res + } + /// # Safety + /// + /// The parameters passed in should ensure FFI safety + /// user_data pointer, data pointer and reply pointer on the c side must be guaranteed not to be null unsafe extern "C" fn on_destroy(user_data: *mut c_void) { info!(LOG_LABEL, "RemoteStub on_destroy in Rust"); // T will be freed by Box after this function end. diff --git a/interfaces/innerkits/rust/src/ipc_binding.rs b/interfaces/innerkits/rust/src/ipc_binding.rs index 93ab5418438d8707e585d89a9054e82157491dd2..3438ba0ef3aaf1395097cb89915100ced8293317 100644 --- a/interfaces/innerkits/rust/src/ipc_binding.rs +++ b/interfaces/innerkits/rust/src/ipc_binding.rs @@ -46,6 +46,13 @@ pub type OnRemoteRequest = unsafe extern "C" fn ( reply: *mut CParcel ) -> i32; +// Callback function type for OnRemoteDump() from native, this +// callback will be called when native recive client IPC dump. +pub type OnRemoteDump = unsafe extern "C" fn ( + user_data: *mut c_void, + data: *const CParcel, +) -> i32; + // Callback function type for OnRemoteObjectDestroy() from native, // this callback will be called when native remote object destroyed. pub type OnRemoteObjectDestroy = unsafe extern "C" fn ( @@ -87,6 +94,15 @@ pub type OnStringArrayRead = unsafe extern "C" fn( len: u32 // C++ vector length ) -> bool; +// Callback function type for CParcelReadString16Array() from native. +// Rust side need read string one by one from native according calling +// CParcelReadString16Element(). +pub type OnString16ArrayRead = unsafe extern "C" fn( + data: *const c_void, // C++ vector pointer + value: *mut c_void, // Rust vector pointer + len: u32 // C++ vector length +) -> bool; + // Callback function type for CParcelWriteStringArray() from native. // Rust side need write string one by one to native according calling // CParcelWriteStringElement(). @@ -96,6 +112,15 @@ pub type OnStringArrayWrite = unsafe extern "C" fn( len: u32, // Rust vector length ) -> bool; +// Callback function type for CParcelWriteString16Array() from native. +// Rust side need write string one by one to native according calling +// CParcelWriteString16Element(). +pub type OnString16ArrayWrite = unsafe extern "C" fn( + array: *const c_void, // C++ vector pointer + value: *mut c_void, // Rust vector pointer + len: u32, // Rust vector length +) -> bool; + pub type OnCParcelWriteElement = unsafe extern "C" fn ( value: *mut CParcel, arr: *const c_void, @@ -112,7 +137,7 @@ pub type OnCParcelReadElement = unsafe extern "C" fn ( extern "C" { pub fn CreateRemoteStub(descripor: *const c_char, on_remote_request: OnRemoteRequest, on_remote_object_destroy: OnRemoteObjectDestroy, - user_data: *const c_void) -> *mut CRemoteObject; + user_data: *const c_void, on_remote_dump: OnRemoteDump) -> *mut CRemoteObject; pub fn RemoteObjectIncStrongRef(object: *mut CRemoteObject); pub fn RemoteObjectDecStrongRef(object: *mut CRemoteObject); @@ -131,8 +156,7 @@ extern "C" { recipient: *mut CDeathRecipient) -> bool; pub fn IsProxyObject(object: *mut CRemoteObject) -> bool; - pub fn Dump(object: *mut CRemoteObject, fd: i32, value: *const c_void, len: i32, - writer: OnStringArrayWrite) -> i32; + pub fn Dump(object: *mut CRemoteObject, fd: i32, parcel: *mut CParcel) -> i32; pub fn IsObjectDead(object: *mut CRemoteObject) -> bool; pub fn GetInterfaceDescriptor(object: *mut CRemoteObject, @@ -200,14 +224,20 @@ extern "C" { allocator: OnCParcelBytesAllocator::) -> bool; pub fn CParcelWriteStringArray(parcel: *mut CParcel, value: *const c_void, len: i32, writer: OnStringArrayWrite) -> bool; + pub fn CParcelWriteString16Array(parcel: *mut CParcel, value: *const c_void, len: i32, + writer: OnString16ArrayWrite) -> bool; pub fn CParcelWriteStringElement(data: *const c_void, value: *const c_char, len: i32) -> bool; pub fn CParcelWritU16stringElement(data: *const c_void, value: *const c_char, len: i32) -> bool; pub fn CParcelReadStringArray(parcel: *const CParcel, value: *mut c_void, reader: OnStringArrayRead) -> bool; + pub fn CParcelReadString16Array(parcel: *const CParcel, value: *mut c_void, + reader: OnString16ArrayRead) -> bool; pub fn CParcelReadStringElement(index: u32, data: *const c_void, value: *mut c_void, allocator: OnCParcelBytesAllocator::) -> bool; + pub fn CParcelReadString16Element(index: u32, data: *const c_void, value: *mut c_void, + allocator: OnCParcelBytesAllocator::) -> bool; pub fn CParcelWriteParcelableArray(parcel: *mut CParcel, value: *const c_void, len: i32, element_writer: OnCParcelWriteElement) -> bool; pub fn CParcelReadParcelableArray(parcel: *const CParcel, value: *mut c_void, diff --git a/interfaces/innerkits/rust/src/parcel/types/file_desc.rs b/interfaces/innerkits/rust/src/parcel/types/file_desc.rs index 4caad8d9e43811df607bf2438f8f4721a0391e1f..373839cade72ad3b4b058aca36b36190c1b33c1d 100644 --- a/interfaces/innerkits/rust/src/parcel/types/file_desc.rs +++ b/interfaces/innerkits/rust/src/parcel/types/file_desc.rs @@ -140,8 +140,37 @@ impl DeOption for FileDesc { impl Deserialize for FileDesc { fn deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult { - Deserialize::deserialize(parcel) - .transpose() - .unwrap_or(Err(IpcStatusCode::Failed)) + let mut fd = -1i32; + // SAFETY: + // `parcel` always contains a valid pointer to an `CParcel`. + // `CParcelWriteFileDescriptor` accepts the value `-1` as the file + // descriptor to signify serializing a null file descriptor. + // The read function passes ownership of the file + // descriptor to its caller if it was non-null, so we must take + // ownership of the file and ensure that it is eventually closed. + let ok_status = unsafe { + ipc_binding::CParcelReadFileDescriptor( + parcel.as_raw(), + &mut fd, + ) + }; + if ok_status{ + if fd < 0 { + error!(LOG_LABEL, "file descriptor is invalid from native"); + Err(IpcStatusCode::Failed) + } else { + // SAFETY: + // At this point, we know that the file descriptor was + // not -1, so must be a valid, owned file descriptor which we + // can safely turn into a `File`. + let file = unsafe { + File::from_raw_fd(fd) + }; + Ok(FileDesc::new(file)) + } + } else { + error!(LOG_LABEL, "read file descriptor failed from native"); + Err(IpcStatusCode::Failed) + } } } \ No newline at end of file diff --git a/interfaces/innerkits/rust/src/parcel/types/string16.rs b/interfaces/innerkits/rust/src/parcel/types/string16.rs index 75d6d6165eb55bb8b95956edf696eb4f22240fb2..764d60d198d6e6e0440ccd8fc192aa161b1884be 100644 --- a/interfaces/innerkits/rust/src/parcel/types/string16.rs +++ b/interfaces/innerkits/rust/src/parcel/types/string16.rs @@ -16,6 +16,7 @@ use super::*; use crate::{ipc_binding, BorrowedMsgParcel, IpcResult, IpcStatusCode, status_result, AsRawPtr}; use std::convert::TryInto; +use std::mem::MaybeUninit; use std::ffi::{CString}; use hilog_rust::{error, hilog, HiLogLabel, LogType}; @@ -86,6 +87,47 @@ impl Deserialize for String16 { } } +impl SerArray for String16 { + fn ser_array(slice: &[Self], parcel: &mut BorrowedMsgParcel<'_>) -> IpcResult<()> { + // SAFETY: `parcel` always contains a valid pointer to a `CParcel` + let ret = unsafe { + ipc_binding::CParcelWriteString16Array( + parcel.as_mut_raw(), + slice.as_ptr() as *const c_void, + slice.len().try_into().unwrap(), + on_string16_writer, + ) + }; + status_result::<()>(ret as i32, ()) + } +} + +impl DeArray for String16 { + fn de_array(parcel: &BorrowedMsgParcel<'_>) -> IpcResult>> { + let mut vec: Option>> = None; + // SAFETY: `parcel` always contains a valid pointer to a `CParcel` + // `allocate_vec` expects the opaque pointer to + // be of type `*mut Option>>`, so `&mut vec` is + // correct for it. + let ok_status = unsafe { + ipc_binding::CParcelReadString16Array( + parcel.as_raw(), + &mut vec as *mut _ as *mut c_void, + on_string16_reader, + ) + }; + if ok_status { + // SAFETY: all the MaybeUninits are now properly initialized. + let vec: Option> = unsafe { + vec.map(|vec| vec_assume_init(vec)) + }; + Ok(vec) + } else { + error!(LOG_LABEL, "read string16 from native fail"); + Err(IpcStatusCode::Failed) + } + } +} /// Callback to serialize a String16 array to c++ std::vector. /// /// # Safety: @@ -120,3 +162,51 @@ pub unsafe extern "C" fn on_string16_writer( } true } + +/// Callback to deserialize a String element in Vector. +/// +/// # Safety: +/// +/// The opaque array data pointer must be a mutable pointer to an +/// `Option>>` with at least enough elements for `index` to be valid +/// (zero-based). +#[allow(dead_code)] +unsafe extern "C" fn on_string16_reader( + data: *const c_void, // C++ vector pointer + value: *mut c_void, // Rust vector pointer + len: u32, // C++ vector length +) -> bool { + // SAFETY: + // Allocate Vec capacity, data_len will set correctly by vec.push(). + unsafe { allocate_vec_maybeuninit::(value, 0) }; + let vec = &mut *(value as *mut Option>>); + for index in 0..len { + let mut vec_u16: Option> = None; + // SAFETY: The length of the index will not exceed the range, + // as the traversal range is the pointer length of the data passed from the C++side + let ok_status = unsafe { + ipc_binding::CParcelReadString16Element( + index, + data, + &mut vec_u16 as *mut _ as *mut c_void, + allocate_vec_with_buffer:: + ) + }; + if ok_status { + if let Ok(string) = vec_u16_to_string(vec_u16) { + if let Some(new_vec) = vec { + new_vec.push(MaybeUninit::new(String16::new(string.as_str()))); + } else { + error!(LOG_LABEL, "on_string_reader allocate vec failed"); + return false; + } + } else { + error!(LOG_LABEL, "on_string_reader vec_to_string failed"); + return false; + } + } else { + return false; + } + } + true +} diff --git a/ipc/native/src/c_wrapper/include/c_parcel.h b/ipc/native/src/c_wrapper/include/c_parcel.h index 3e4dd60ed4feeb244efdd1356651e57afb705423..e27141cd5e141b17f5deb533e5ce73793124abc5 100644 --- a/ipc/native/src/c_wrapper/include/c_parcel.h +++ b/ipc/native/src/c_wrapper/include/c_parcel.h @@ -32,6 +32,7 @@ struct CRemoteObjectHolder; typedef struct CRemoteObjectHolder CRemoteObject; typedef bool (*OnCParcelBytesAllocator)(void *stringData, char **buffer, int32_t len); +typedef bool (*OnCParcelBytesAllocator16)(void *stringData, int16_t **buffer, int32_t len); typedef bool (*OnCParcelBoolAllocator)(void *value, bool **buffer, int32_t len); typedef bool (*OnCParcelInt8Allocator)(void *value, int8_t **buffer, int32_t len); typedef bool (*OnCParcelInt16Allocator)(void *value, int16_t **buffer, int32_t len); @@ -41,7 +42,9 @@ typedef bool (*OnCParcelFloatAllocator)(void *value, float **buffer, int32_t len typedef bool (*OnCParcelDoubleAllocator)(void *value, double **buffer, int32_t len); typedef bool (*OnCParcelAllocator)(void *value, int32_t len); typedef bool (*OnStringArrayWrite)(const void *array, const void *value, uint32_t len); +typedef bool (*OnString16ArrayWrite)(const void *array, const void *value, uint32_t len); typedef bool (*OnStringArrayRead)(const void *array, const void *value, uint32_t len); +typedef bool (*OnString16ArrayRead)(const void *array, const void *value, uint32_t len); typedef bool (*OnCParcelWriteElement)(CParcel *value, const void *arr, unsigned long index); typedef bool (*OnCParcelReadElement)(const CParcel *value, void *arr, unsigned long index); @@ -94,12 +97,17 @@ bool CParcelWriteDoubleArray(CParcel *parcel, const double *array, int32_t len); bool CParcelReadDoubleArray(const CParcel *parcel, void *value, OnCParcelDoubleAllocator allocator); bool CParcelWriteStringArray(CParcel *parcel, const void *value, int32_t len, OnStringArrayWrite writer); +bool CParcelWriteString16Array(CParcel *parcel, const void *value, + int32_t len, OnString16ArrayWrite writer); bool CParcelWriteStringElement(void *data, const char *value, int32_t len); -bool CParcelWritU16stringElement(void *data, const char16_t *value, int32_t len); +bool CParcelWritU16stringElement(void *data, const char *value, int32_t len); bool CParcelReadStringArray(const CParcel *parcel, void *value, OnStringArrayRead reader); +bool CParcelReadString16Array(const CParcel *parcel, void *value, OnString16ArrayRead reader); bool CParcelReadStringElement(uint32_t index, const void *data, void *value, OnCParcelBytesAllocator allocator); +bool CParcelReadString16Element(uint32_t index, const void *data, void *value, + OnCParcelBytesAllocator16 allocator); bool CParcelWriteParcelableArray(CParcel *parcel, const void *value, int32_t len, OnCParcelWriteElement elementWriter); 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 9189fa61ec43aa4f82cf568bb61af155634c92ac..70646c072ff6fefec3ea2cc82ca1aefd50eefba9 100644 --- a/ipc/native/src/c_wrapper/include/c_remote_object.h +++ b/ipc/native/src/c_wrapper/include/c_remote_object.h @@ -32,6 +32,7 @@ typedef struct CDeathRecipient CDeathRecipient; // Callback as remote stub 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); // Callback as death recipient typedef void (*OnDeathRecipientCb)(const void *userData); @@ -40,7 +41,7 @@ typedef void (*OnDeathRecipientDestroyCb)(const void *userData); typedef bool (*On16BytesAllocator)(void *stringData, uint16_t **buffer, int32_t len); CRemoteObject *CreateRemoteStub(const char *desc, OnRemoteRequestCb callback, - OnRemoteObjectDestroyCb destroy, const void *userData); + OnRemoteObjectDestroyCb destroy, const void *userData, OnRemoteDumpCb dumpCallback); void RemoteObjectIncStrongRef(CRemoteObject *object); void RemoteObjectDecStrongRef(CRemoteObject *object); @@ -58,8 +59,7 @@ bool AddDeathRecipient(CRemoteObject *object, CDeathRecipient *recipient); bool RemoveDeathRecipient(CRemoteObject *object, CDeathRecipient *recipient); bool IsProxyObject(CRemoteObject *object); -int Dump(CRemoteObject *object, int fd, const void *value, - int32_t len, OnStringArrayWrite writer); +int Dump(CRemoteObject *object, int fd, CParcel *parcel); bool IsObjectDead(CRemoteObject *object); bool GetInterfaceDescriptor(CRemoteObject *object, void *value, On16BytesAllocator allocator); diff --git a/ipc/native/src/c_wrapper/include/c_remote_object_internal.h b/ipc/native/src/c_wrapper/include/c_remote_object_internal.h index 6e1874d5441eb4de0e6d460d7b4f9ebf0ea81439..b9f4b9eb435122a8228038bd2e80c378c202cb3c 100644 --- a/ipc/native/src/c_wrapper/include/c_remote_object_internal.h +++ b/ipc/native/src/c_wrapper/include/c_remote_object_internal.h @@ -49,14 +49,17 @@ private: class RemoteServiceHolderStub: public OHOS::IPCObjectStub { public: explicit RemoteServiceHolderStub(std::u16string &desc, OnRemoteRequestCb callback, - const void *userData, OnRemoteObjectDestroyCb destroy); + const void *userData, OnRemoteObjectDestroyCb destroy, OnRemoteDumpCb dump); ~RemoteServiceHolderStub(); int OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply, OHOS::MessageOption &option) override; + int OnRemoteDump(uint32_t code, OHOS::MessageParcel &data, + OHOS::MessageParcel &reply, OHOS::MessageOption &option) override; private: OnRemoteRequestCb callback_; + OnRemoteDumpCb dumpCallback_; const void *userData_; OnRemoteObjectDestroyCb destroy_; }; diff --git a/ipc/native/src/c_wrapper/source/c_parcel.cpp b/ipc/native/src/c_wrapper/source/c_parcel.cpp index 4d7c0c228b887be92839b9d897a91f0fd83bfd38..0a110d5274bf1e5e7b44b2cae6541d0116df9d9d 100644 --- a/ipc/native/src/c_wrapper/source/c_parcel.cpp +++ b/ipc/native/src/c_wrapper/source/c_parcel.cpp @@ -618,6 +618,26 @@ bool CParcelWriteStringArray(CParcel *parcel, const void *value, return true; } +bool CParcelWriteString16Array(CParcel *parcel, const void *value, + int32_t len, OnString16ArrayWrite writer) +{ + if (!IsValidParcel(parcel, __func__) || writer == nullptr) { + return false; + } + std::vector string16Vector; + if (len > 0 && !writer(reinterpret_cast(&string16Vector), + value, static_cast(len))) { + ZLOGE(LOG_LABEL, "%{public}s: write u16string array to vector failed\n", __func__); + return false; + } + + if (!parcel->parcel_->WriteString16Vector(string16Vector)) { + ZLOGE(LOG_LABEL, "%{public}s: write u16string array to parcel failed\n", __func__); + return false; + } + return true; +} + bool CParcelWriteStringElement(void *data, const char *value, int32_t len) { std::vector *stringVector = reinterpret_cast *>(data); @@ -633,7 +653,7 @@ bool CParcelWriteStringElement(void *data, const char *value, int32_t len) return true; } -bool CParcelWritU16stringElement(void *data, const char16_t *value, int32_t len) +bool CParcelWritU16stringElement(void *data, const char *value, int32_t len) { std::vector *u16stringVector = reinterpret_cast *>(data); if (u16stringVector == nullptr) { @@ -644,7 +664,11 @@ bool CParcelWritU16stringElement(void *data, const char16_t *value, int32_t len) ZLOGE(LOG_LABEL, "%{public}s: string len is invalid: %d\n", __func__, len); return false; } - u16stringVector->push_back(std::u16string(value, len)); + + std::u16string u16str = std::wstring_convert< std::codecvt_utf8_utf16, char16_t >{}.from_bytes( + std::string(value, len)); + u16stringVector->push_back(u16str); + return true; } @@ -665,6 +689,56 @@ bool CParcelReadStringArray(const CParcel *parcel, void *value, OnStringArrayRea return true; } +bool CParcelReadString16Array(const CParcel *parcel, void *value, OnString16ArrayRead reader) +{ + if (!IsValidParcel(parcel, __func__) || reader == nullptr) { + return false; + } + std::vector string16Vector; + if (!parcel->parcel_->ReadString16Vector(&string16Vector)) { + ZLOGE(LOG_LABEL, "%{public}s: read u16string array from parcel failed\n", __func__); + return false; + } + if (!reader(reinterpret_cast(&string16Vector), value, string16Vector.size())) { + ZLOGE(LOG_LABEL, "%{public}s: read u16string to vector failed\n", __func__); + return false; + } + return true; +} + +bool CParcelReadString16Element(uint32_t index, const void *data, void *value, + OnCParcelBytesAllocator16 allocator) +{ + if (data == nullptr || allocator == nullptr) { + ZLOGE(LOG_LABEL, "%{public}s: invalid data and allocator\n", __func__); + return false; + } + const std::vector *string16Vector = + reinterpret_cast *>(data); + + if (index >= string16Vector->size()) { + ZLOGE(LOG_LABEL, "%{public}s: invalid index: %u, size: %u\n", __func__, + index, static_cast(string16Vector->size())); + return false; + } + + const std::u16string &string16Value = (*string16Vector)[index]; + int16_t *buffer = nullptr; + bool isSuccess = allocator(value, &buffer, string16Value.length()); + if (!isSuccess) { + ZLOGE(LOG_LABEL, "%{public}s: allocate string16Value buffer failed\n", __func__); + return false; + } + + if (string16Value.length() > 0 && + memcpy_s(buffer, string16Value.length() * sizeof(char16_t), + string16Value.data(), string16Value.length() * sizeof(char16_t)) != EOK) { + ZLOGE(LOG_LABEL, "%{public}s: memcpy string16Value failed\n", __func__); + return false; + } + return true; +} + bool CParcelReadStringElement(uint32_t index, const void *data, void *value, OnCParcelBytesAllocator allocator) { 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 0a90b8c0389fc9c36ff710ec0a0a9e93d8ab1bc1..625b23e572235d1f3da286d4890bc7ae332bd33d 100644 --- a/ipc/native/src/c_wrapper/source/c_remote_object.cpp +++ b/ipc/native/src/c_wrapper/source/c_remote_object.cpp @@ -25,9 +25,9 @@ using namespace OHOS; static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "CRemoteObject" }; -RemoteServiceHolderStub::RemoteServiceHolderStub(std::u16string &desc, - OnRemoteRequestCb callback, const void *userData, OnRemoteObjectDestroyCb destroy) - : IPCObjectStub(desc), callback_(callback) +RemoteServiceHolderStub::RemoteServiceHolderStub(std::u16string &desc, OnRemoteRequestCb callback, + const void *userData, OnRemoteObjectDestroyCb destroy, OnRemoteDumpCb dumpCallback) + : IPCObjectStub(desc), callback_(callback), dumpCallback_(dumpCallback) , userData_(userData), destroy_(destroy) { } @@ -53,6 +53,20 @@ int RemoteServiceHolderStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel return callback_(userData_, code, &parcelData, &parcelReply); } +int RemoteServiceHolderStub::OnRemoteDump(uint32_t code, OHOS::MessageParcel &data, + OHOS::MessageParcel &reply, OHOS::MessageOption &option) +{ + (void)option; + (void)reply; + if (dumpCallback_ == nullptr) { + ZLOGE(LOG_LABEL, "%{public}s: dumpCallback_ is null for code: %u\n", __func__, code); + return -1; + } + CParcel parcelData(&data); + return dumpCallback_(userData_, &parcelData); +} + + CDeathRecipient::CDeathRecipient(OnDeathRecipientCb onDeathRecipient, OnDeathRecipientDestroyCb onDestroy, const void *userData) : userData_(userData) @@ -92,7 +106,7 @@ bool IsValidRemoteObject(const CRemoteObject *object, const char *promot) } CRemoteObject *CreateRemoteStub(const char *desc, OnRemoteRequestCb callback, - OnRemoteObjectDestroyCb destroy, const void *userData) + OnRemoteObjectDestroyCb destroy, const void *userData, OnRemoteDumpCb dumpCallback) { if (desc == nullptr || callback == nullptr || destroy == nullptr) { return nullptr; @@ -104,7 +118,7 @@ CRemoteObject *CreateRemoteStub(const char *desc, OnRemoteRequestCb callback, } std::u16string descriptor = Str8ToStr16(std::string(desc)); holder->remote_ = new (std::nothrow) RemoteServiceHolderStub( - descriptor, callback, userData, destroy); + descriptor, callback, userData, destroy, dumpCallback); if (holder->remote_ == nullptr) { ZLOGE(LOG_LABEL, "%{public}s: new RemoteServiceHolderStub failed\n", __func__); delete holder; @@ -223,18 +237,20 @@ bool IsProxyObject(CRemoteObject *object) return object->remote_->IsProxyObject(); } -int Dump(CRemoteObject *object, int fd, const void *value, int32_t len, OnStringArrayWrite writer) +int Dump(CRemoteObject *object, int fd, CParcel *parcel) { - if (!IsValidRemoteObject(object, __func__) || writer == nullptr) { + if (!IsValidRemoteObject(object, __func__) || parcel == nullptr) { ZLOGE(LOG_LABEL, "%{public}s: recipient is null\n", __func__); return -1; } - std::vector stringVector; - if (len > 0 && !writer(reinterpret_cast(&stringVector), value, static_cast(len))) { - ZLOGE(LOG_LABEL, "%{public}s: write string array to vector failed\n", __func__); + if (fd < 0) { + ZLOGE(LOG_LABEL, "%{public}s: fd is valid\n", __func__); return -1; } - return object->remote_->Dump(fd, stringVector); + std::vector string16Vector; + parcel->parcel_->ReadString16Vector(&string16Vector); + + return object->remote_->Dump(fd, string16Vector); } bool IsObjectDead(CRemoteObject *object) diff --git a/ipc/native/test/unittest/common/ipc_c_remote_object_unittest.cpp b/ipc/native/test/unittest/common/ipc_c_remote_object_unittest.cpp index d65869758a86f36ea65cde5a772ee1ad4a753b8a..6f4be188f0a1b779ed8d3530bd25159264e23c7f 100644 --- a/ipc/native/test/unittest/common/ipc_c_remote_object_unittest.cpp +++ b/ipc/native/test/unittest/common/ipc_c_remote_object_unittest.cpp @@ -90,15 +90,6 @@ static bool Bytes16Allocator(void *stringData, uint16_t **buffer, int32_t len) return true; } -static bool StringArrayWrite(const void *array, const void *value, uint32_t len) -{ - if (value == nullptr || len < 0) { - return false; - } - array = value; - return true; -} - /** * @tc.name: CRemoteObjectRefCount * @tc.desc: Verify the CRemoteObject reference count functions @@ -106,9 +97,9 @@ static bool StringArrayWrite(const void *array, const void *value, uint32_t len) */ HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectRefCount, TestSize.Level1) { - CRemoteObject *remote = CreateRemoteStub(nullptr, OnRemoteRequest, OnRemoteObjectDestroy, nullptr); + CRemoteObject *remote = CreateRemoteStub(nullptr, OnRemoteRequest, OnRemoteObjectDestroy, nullptr, nullptr); EXPECT_EQ(remote, nullptr); - remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, nullptr); + remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, nullptr, nullptr); EXPECT_NE(remote, nullptr); RefBase *ref = static_cast(remote); EXPECT_EQ(ref->GetSptrRefCount(), 1); @@ -130,7 +121,7 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectRefCount, TestSize.Level1) HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectCompare, TestSize.Level1) { int8_t userData; - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); EXPECT_FALSE(RemoteObjectLessThan(nullptr, remote)); EXPECT_FALSE(RemoteObjectLessThan(remote, nullptr)); @@ -216,7 +207,7 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CDeathRecipientStub, TestSize.Level1) int8_t userData; CDeathRecipient *recipient = CreateDeathRecipient(OnDeathRecipient, OnDeathRecipientDestroy, &userData); EXPECT_NE(recipient, nullptr); - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); EXPECT_FALSE(AddDeathRecipient(remote, recipient)); EXPECT_FALSE(RemoveDeathRecipient(remote, recipient)); @@ -259,7 +250,7 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CDeathRecipient, TestSize.Level1) HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectIsProxyObject, TestSize.Level1) { int8_t userData; - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); bool ret = IsProxyObject(remote); @@ -274,7 +265,7 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectIsProxyObject, TestSize.Level1) HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectIsObjectDead, TestSize.Level1) { int8_t userData; - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); bool ret = IsObjectDead(remote); @@ -289,7 +280,7 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectIsObjectDead, TestSize.Level1) HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectGetInterfaceDescriptor, TestSize.Level1) { int8_t userData; - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); void *data = nullptr; @@ -308,10 +299,11 @@ HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectGetInterfaceDescriptor, TestSize HWTEST_F(IpcCRemoteObjectUnitTest, CRemoteObjectDump, TestSize.Level1) { int8_t userData; - CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData); + CRemoteObject *remote = CreateRemoteStub(SERVICE_NAME, OnRemoteRequest, OnRemoteObjectDestroy, &userData, nullptr); EXPECT_NE(remote, nullptr); - const char *data = SERVICE_NAME; - int ret = Dump(remote, 0, reinterpret_cast(&data), strlen(data), StringArrayWrite); + CParcel *parcel = CParcelObtain(); + EXPECT_NE(parcel, nullptr); + int ret = Dump(remote, 0, parcel); EXPECT_EQ(ret, 0); } \ 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 6e008b3cfe722615a2c7cef5984149714c05b18c..c5b3a2e108e128bf60ad58caf4e91e2fc6a6fca0 100644 --- a/ipc/native/test/unittest/rust/client/src/main.rs +++ b/ipc/native/test/unittest/rust/client/src/main.rs @@ -33,6 +33,7 @@ use ipc_rust::{ use ipc_rust::{Serialize, Deserialize, BorrowedMsgParcel, Ashmem}; use test_ipc_service::{ITest, TestProxy, IPC_TEST_SERVICE_ID, IFoo, init_access_token}; use std::fs::File; +use std::os::fd::AsRawFd; fn get_test_service() -> RemoteObjRef { @@ -786,8 +787,9 @@ fn test_is_proxy_object() { fn test_dump() { let object = get_service(IPC_TEST_SERVICE_ID).expect("get itest service failed"); let args: &mut Vec = &mut Vec::new(); + let file = File::create("data.txt").expect("create failed"); args.push(String16::new("test.ipc.ITestService")); - let res = object.dump(0, args); + let res = object.dump(file.as_raw_fd(), args); assert_eq!(0, res); } diff --git a/ipc/native/test/unittest/rust/server/src/main.rs b/ipc/native/test/unittest/rust/server/src/main.rs index b07fbad3eaf0cfb44193861c8ee1c2c411132533..63a4fd6fdaae7ccd1a064641cba820544d3847de 100644 --- a/ipc/native/test/unittest/rust/server/src/main.rs +++ b/ipc/native/test/unittest/rust/server/src/main.rs @@ -24,9 +24,13 @@ use ipc_rust::{ get_calling_uid, String16, RemoteObj, IRemoteStub, get_local_device_id, get_calling_device_id, IpcStatusCode, }; -use test_ipc_service::{ITest, TestStub, IPC_TEST_SERVICE_ID, reverse, IFoo, FooStub, init_access_token}; +use test_ipc_service::{ + ITest, TestStub, IPC_TEST_SERVICE_ID, IPC_TEST_STATUS_SUCCESS, + reverse, IFoo, FooStub, init_access_token, IPC_TEST_STATUS_FAILED, +}; use std::io::Write; use std::fs::OpenOptions; +use std::os::fd::AsRawFd; use std::{thread, time}; /// FooService type @@ -110,7 +114,22 @@ impl ITest for TestService { } } -impl IRemoteBroker for TestService {} +impl IRemoteBroker for TestService { + /// Dump implementation of service rewrite ipc + fn dump(&self, _file: &FileDesc, _args: &mut Vec) -> i32 { + let fd = _file.as_raw_fd(); + if fd < 0 { + println!("fd is invalid: {}", fd); + return IPC_TEST_STATUS_FAILED; + } + + for arg in _args.as_slice() { + println!("{}", arg.get_string().as_str()); + _file.as_ref().write_all(arg.get_string().as_str().as_bytes()).expect("write failed"); + } + IPC_TEST_STATUS_SUCCESS + } +} fn main() { init_access_token(); diff --git a/ipc/native/test/unittest/rust/service/BUILD.gn b/ipc/native/test/unittest/rust/service/BUILD.gn index e12382bab72b8e63bbe90e64026fb186128c460b..a81aeced14c7cae2eee021f8fcbe390b89dd0345 100644 --- a/ipc/native/test/unittest/rust/service/BUILD.gn +++ b/ipc/native/test/unittest/rust/service/BUILD.gn @@ -9,7 +9,7 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and -# limitations under the License. +# limitations under the License. import("//build/ohos.gni") @@ -21,10 +21,11 @@ ohos_rust_shared_library("test_ipc_service") { "src/lib.rs", ] - deps = [ - "$SUBSYSTEM_DIR/interfaces/innerkits/rust:ipc_rust", - "//base/security/access_token/interfaces/innerkits/nativetoken:libnativetoken", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", + deps = [ "$SUBSYSTEM_DIR/interfaces/innerkits/rust:ipc_rust" ] + + external_deps = [ + "access_token:libnativetoken", + "access_token:libtoken_setproc", ] crate_name = "test_ipc_service" diff --git a/ipc/native/test/unittest/rust/service/src/lib.rs b/ipc/native/test/unittest/rust/service/src/lib.rs index f1950bf6601870bf721fc5a8d95eb2f07df0a1ae..318727c32e3541ffecfd1956bacd170ce155d23f 100644 --- a/ipc/native/test/unittest/rust/service/src/lib.rs +++ b/ipc/native/test/unittest/rust/service/src/lib.rs @@ -43,6 +43,10 @@ pub fn reverse(mut value: i32) -> i32 { /// SA ID for "test.ipc.ITestService" pub const IPC_TEST_SERVICE_ID: i32 = 1118; +/// Test service success status +pub const IPC_TEST_STATUS_SUCCESS: i32 = 0; +/// Test service failed status +pub const IPC_TEST_STATUS_FAILED: i32 = -1; /// Function code of ITestService pub enum ITestCode {