...
 
Commits (23)
    https://gitcode.net/openharmony/communication_ipc/-/commit/2f8e0c393293cb152f090a42ff4cc5bad20486bc avoid opening /dev/binder twice 2023-06-20T08:01:21+00:00 shufewhx wanghaoxu1@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com">shufewhx</a> &lt;<a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com">wanghaoxu1@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/ac84d256f1ad49bb5288a58b3a3b74beb72eb5a4 !713 avoid opening /dev/binder twice 2023-07-20T13:49:35+00:00 openharmony_ci 120357966@qq.com Merge pull request !713 from wanghaoxu/master https://gitcode.net/openharmony/communication_ipc/-/commit/8656808ac0673c806367c85cab41e48624716e38 回退 'Pull Request !713 : avoid opening /dev/binder twice' 2023-07-21T05:15:07+00:00 openharmony_ci 120357966@qq.com https://gitcode.net/openharmony/communication_ipc/-/commit/3933f9103dbf8dc9f0275f350cbb4da51919abbb !739 回退 'Pull Request !713 : avoid opening /dev/binder twice' 2023-07-21T05:15:25+00:00 openharmony_ci 120357966@qq.com Merge pull request !739 from openharmony_ci/revert-merge-713-master https://gitcode.net/openharmony/communication_ipc/-/commit/24d4bd1c29e414c65f0caf5ef0bf3e24e7625359 fix uaf of param in napi_remote_object 2023-07-21T07:32:37+00:00 shufewhx wanghaoxu1@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg4" style="text-decoration: none">N</a><a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com">shufewhx</a> &lt;<a href="mailto:wanghaoxu1@huawei.com" title="wanghaoxu1@huawei.com">wanghaoxu1@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/71f8d37088a114c17e0e7f942f7f6f7848877f13 !740 fix uaf of param in napi_remote_object 2023-07-21T10:09:43+00:00 openharmony_ci 120357966@qq.com Merge pull request !740 from wanghaoxu/master https://gitcode.net/openharmony/communication_ipc/-/commit/602cb1834d6521bc281f7ee4ce5b359075a9dfe6 fix NAPIRemoteObject mem leak 2023-07-22T22:05:04+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg1" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/ca9eb55402bb9cb5ec443d578be53aaac5dd51b4 update ipc/native/src/napi_common/source/napi_remote_object_holder.cpp. 2023-07-24T02:06:20+00:00 马根堂 magentang4@huawei.com fix mem leak Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg2" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">马根堂</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/2ac152a3e2397e74318b801724cb8a7b07ad996a fix mem leak 2023-07-24T20:06:15+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg4" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/497184b5bdab7d38b77c8cded4807f0f7beaf7ba fix mem leak 2023-07-24T20:39:19+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg5" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/ed6a37e97d91a9917fd778b7cedda22ab9a015ff fix mem leak 2023-07-25T21:02:35+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg5" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/282033c814229ba0fb6d532c35979f2416c78eea [Bug]: c++ hidumper服务调用rust端服务没有dumper信息 2023-07-26T15:36:00+08:00 chenchong_666 chenchong57@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:chenchong57@huawei.com" title="chenchong57@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:chenchong57@huawei.com" title="chenchong57@huawei.com">chenchong_666</a> &lt;<a href="mailto:chenchong57@huawei.com" title="chenchong57@huawei.com">chenchong57@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/de514810a3926759496d63e6022b44fe7efe0d6b !744 c++ hidumper服务调用rust端服务没有dumper信息 2023-07-26T12:09:25+00:00 openharmony_ci 120357966@qq.com Merge pull request !744 from chenchong_666/master https://gitcode.net/openharmony/communication_ipc/-/commit/81a65c36ad86584616e8f099367451b7057522d2 fix mem leak 2023-07-26T21:46:56+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg6" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/2788693e8a6453625bc821c8386f57a1b221a4de fix memleak 2023-07-27T16:14:07+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg2" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/b4f0540a8426903f0dc7eb9175ab7a237dd0b614 fix mem leak 2023-07-27T16:56:10+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg2" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/f6031f528214e65fa8afd16eee07489edc5d42ac update ipc/native/src/napi_common/source/napi_remote_object.cpp. 2023-07-27T09:28:05+00:00 马根堂 magentang4@huawei.com fix mem leak Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">马根堂</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/7aea0579b3c412e2dc5cded3ad2275053f6ea528 fix mem leak 2023-07-27T22:11:20+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/caf011a4d3c525d2f9900c583ff723ad8174baa2 mem leak 2023-07-27T22:44:32+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg2" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/42de956069f1083b9a0218f5123a193b9b78d190 fix mem leak 2023-07-27T22:47:40+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/ad0d05e275ce08721e059800ee5d5cf37106b941 fix mem leak 2023-07-28T09:21:23+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/5343cf5d3df21ad8b09582ffaff96c2b17f7eb7a fix mem leak 2023-07-28T19:24:18+08:00 18392170496 magentang4@huawei.com Signed-off-by: <span data-trailer="Signed-off-by:"><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com"></a><a href="javascript:void(0)" class="avatar s16 avatar-inline identicon bg3" style="text-decoration: none">N</a><a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">18392170496</a> &lt;<a href="mailto:magentang4@huawei.com" title="magentang4@huawei.com">magentang4@huawei.com</a>&gt;</span> https://gitcode.net/openharmony/communication_ipc/-/commit/60a3051c030bd152c9367aed709cbcc9e9109532 !742 解决NAPIRemoteObject内存泄露问题 2023-07-28T12:59:15+00:00 openharmony_ci 120357966@qq.com Merge pull request !742 from 马根堂/master
......@@ -36,7 +36,8 @@
"c_utils",
"access_token",
"dsoftbus",
"napi"
"napi",
"common"
],
"third_party": [
"libuv",
......
......@@ -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 {
......
......@@ -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<String16>) -> 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<String16>) -> i32;
}
/// Like C++ IRemoteBroker class
......@@ -64,6 +70,11 @@ pub trait IRemoteBroker: Send + Sync {
fn as_object(&self) -> Option<RemoteObj> {
panic!("This is not a RemoteObject.")
}
/// Default dump
fn dump(&self, _file: &FileDesc, _args: &mut Vec<String16>) -> 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
......
......@@ -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<String16>) -> 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::<Vec<String16>>(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
}
}
}
......
......@@ -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<T: IRemoteStub> RemoteStub<T> {
// 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<T: IRemoteStub> RemoteStub<T> {
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<T: IRemoteStub> RemoteStub<T> {
///
/// 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::<FileDesc>() {
Ok(file) => file,
_ => {
error!(LOG_LABEL, "read FileDesc failed");
return IpcStatusCode::Failed as i32;
}
};
let mut args: Vec<String16> = match data.read::<Vec<String16>>() {
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<T> on_destroy in Rust");
// T will be freed by Box after this function end.
......
......@@ -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::<f64>) -> 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::<u8>) -> bool;
pub fn CParcelReadString16Element(index: u32, data: *const c_void, value: *mut c_void,
allocator: OnCParcelBytesAllocator::<u16>) -> 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,
......
......@@ -140,8 +140,37 @@ impl DeOption for FileDesc {
impl Deserialize for FileDesc {
fn deserialize(parcel: &BorrowedMsgParcel<'_>) -> IpcResult<Self> {
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
......@@ -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<Option<Vec<Self>>> {
let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
// SAFETY: `parcel` always contains a valid pointer to a `CParcel`
// `allocate_vec<T>` expects the opaque pointer to
// be of type `*mut Option<Vec<MaybeUninit<T>>>`, 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<Vec<Self>> = 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<std::u16string>.
///
/// # Safety:
......@@ -120,3 +162,51 @@ pub unsafe extern "C" fn on_string16_writer(
}
true
}
/// Callback to deserialize a String element in Vector<String16>.
///
/// # Safety:
///
/// The opaque array data pointer must be a mutable pointer to an
/// `Option<Vec<MaybeUninit<T>>>` 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<String16> capacity, data_len will set correctly by vec.push().
unsafe { allocate_vec_maybeuninit::<String16>(value, 0) };
let vec = &mut *(value as *mut Option<Vec<MaybeUninit<String16>>>);
for index in 0..len {
let mut vec_u16: Option<Vec<u16>> = 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::<u16>
)
};
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
}
......@@ -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);
......
......@@ -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);
......
......@@ -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_;
};
......
......@@ -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<std::u16string> string16Vector;
if (len > 0 && !writer(reinterpret_cast<void *>(&string16Vector),
value, static_cast<uint32_t>(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<std::string> *stringVector = reinterpret_cast<std::vector<std::string> *>(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<std::u16string> *u16stringVector = reinterpret_cast<std::vector<std::u16string> *>(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>, 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<std::u16string> 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<void *>(&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<std::u16string> *string16Vector =
reinterpret_cast<const std::vector<std::u16string> *>(data);
if (index >= string16Vector->size()) {
ZLOGE(LOG_LABEL, "%{public}s: invalid index: %u, size: %u\n", __func__,
index, static_cast<uint32_t>(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)
{
......
......@@ -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<std::u16string> stringVector;
if (len > 0 && !writer(reinterpret_cast<void *>(&stringVector), value, static_cast<uint32_t>(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<std::u16string> string16Vector;
parcel->parcel_->ReadString16Vector(&string16Vector);
return object->remote_->Dump(fd, string16Vector);
}
bool IsObjectDead(CRemoteObject *object)
......
......@@ -26,12 +26,15 @@
namespace OHOS {
class NAPIRemoteObjectHolder : public RefBase {
public:
explicit NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor);
~NAPIRemoteObjectHolder();
sptr<NAPIRemoteObject> Get(napi_value object);
void Set(sptr<NAPIRemoteObject> object);
explicit NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor, napi_value thisVar);
~NAPIRemoteObjectHolder() = default;
sptr<IRemoteObject> Get();
void Set(sptr<IRemoteObject> object);
void attachLocalInterface(napi_value localInterface, std::string &descriptor);
napi_value queryLocalInterface(std::string &descriptor);
napi_ref GetJsObjectRef() const;
napi_env GetJsObjectEnv() const;
void CleanJsEnv();
void Lock()
{
mutex_.lock();
......@@ -63,10 +66,13 @@ public:
private:
std::mutex mutex_;
napi_env env_ = nullptr;
std::thread::id jsThreadId_;
std::u16string descriptor_;
sptr<NAPIRemoteObject> cachedObject_;
sptr<IRemoteObject> sptrCachedObject_;
wptr<IRemoteObject> wptrCachedObject_;
napi_ref localInterfaceRef_;
int32_t attachCount_;
napi_ref jsObjectRef_;
};
} // namespace OHOS
#endif // NAPI_REMOTE_OBJECT_HOLDER_H
\ No newline at end of file
......@@ -16,6 +16,8 @@
#ifndef NAPI_IPC_OHOS_REMOTE_OBJECT_INTERNAL_H
#define NAPI_IPC_OHOS_REMOTE_OBJECT_INTERNAL_H
#include <thread>
#include "ipc_object_stub.h"
#include "iremote_object.h"
#include "message_parcel.h"
......@@ -24,9 +26,33 @@
#include "napi_remote_object.h"
namespace OHOS {
struct ThreadLockInfo {
std::mutex mutex;
std::condition_variable condition;
bool ready = false;
};
struct CallbackParam {
napi_env env;
napi_ref thisVarRef;
uint32_t code;
MessageParcel *data;
MessageParcel *reply;
MessageOption *option;
CallingInfo callingInfo;
ThreadLockInfo *lockInfo;
int result;
};
struct OperateJsRefParam {
napi_env env;
napi_ref thisVarRef;
ThreadLockInfo *lockInfo;
};
class NAPIRemoteObject : public IPCObjectStub {
public:
NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor);
NAPIRemoteObject(std::thread::id jsThreadId, napi_env env, napi_ref jsObjectRef, const std::u16string &descriptor);
~NAPIRemoteObject() override;
......@@ -37,28 +63,14 @@ public:
int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
napi_ref GetJsObjectRef() const;
void ResetJsEnv();
private:
napi_env env_ = nullptr;
napi_value thisVar_ = nullptr;
std::thread::id jsThreadId_;
static napi_value ThenCallback(napi_env env, napi_callback_info info);
static napi_value CatchCallback(napi_env env, napi_callback_info info);
napi_ref thisVarRef_ = nullptr;
struct ThreadLockInfo {
std::mutex mutex;
std::condition_variable condition;
bool ready = false;
};
struct CallbackParam {
napi_env env;
napi_ref thisVarRef;
uint32_t code;
MessageParcel *data;
MessageParcel *reply;
MessageOption *option;
CallingInfo callingInfo;
ThreadLockInfo *lockInfo;
int result;
};
int OnJsRemoteRequest(CallbackParam *jsParam);
};
......
......@@ -17,7 +17,6 @@
#include <uv.h>
#include <string_ex.h>
#include <thread>
#include <hitrace_meter.h>
#include "iremote_invoker.h"
......@@ -60,15 +59,84 @@ static void RemoteObjectHolderFinalizeCb(napi_env env, void *data, void *hint)
}
holder->Lock();
int32_t curAttachCount = holder->DecAttachCount();
ZLOGD(LOG_LABEL, "NAPIRemoteObjectHolder destructed by js callback, curAttachCount:%{public}d", curAttachCount);
if (curAttachCount == 0) {
delete holder;
}
}
static void DecreaseJsObjectRef(napi_env env, napi_ref ref)
{
if (ref == nullptr) {
ZLOGI(LOG_LABEL, "ref is nullptr, do nothing");
return;
}
uint32_t result;
napi_status napiStatus = napi_reference_unref(env, ref, &result);
NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to decrease ref to js RemoteObject");
}
static void IncreaseJsObjectRef(napi_env env, napi_ref ref)
{
uint32_t result;
napi_status napiStatus = napi_reference_ref(env, ref, &result);
NAPI_ASSERT_RETURN_VOID(env, napiStatus == napi_ok, "failed to increase ref to js RemoteObject");
}
static void RemoteObjectHolderRefCb(napi_env env, void *data, void *hint)
{
NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
if (holder == nullptr) {
ZLOGW(LOG_LABEL, "RemoteObjectHolderRefCb holder is nullptr");
return;
}
holder->Lock();
int32_t curAttachCount = holder->DecAttachCount();
holder->Unlock();
ZLOGD(LOG_LABEL, "RemoteObjectHolderRefCb, curAttachCount:%{public}d", curAttachCount);
napi_ref ref = holder->GetJsObjectRef();
napi_env workerEnv = holder->GetJsObjectEnv();
if (ref == nullptr || workerEnv == nullptr) {
ZLOGE(LOG_LABEL, "ref or env is null");
return;
}
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(workerEnv, &loop);
uv_work_t *work = new(std::nothrow) uv_work_t;
NAPI_ASSERT_RETURN_VOID(workerEnv, work != nullptr, "cb failed to new work");
OperateJsRefParam *param = new OperateJsRefParam {
.env = workerEnv,
.thisVarRef = ref
};
work->data = reinterpret_cast<void *>(param);
uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
ZLOGI(LOG_LABEL, "decrease on uv work thread");
OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
napi_handle_scope scope = nullptr;
napi_open_handle_scope(param->env, &scope);
DecreaseJsObjectRef(param->env, param->thisVarRef);
napi_close_handle_scope(param->env, scope);
delete param;
delete work;
});
}
static void *RemoteObjectDetachCb(NativeEngine *engine, void *value, void *hint)
{
(void)engine;
(void)hint;
napi_env env = reinterpret_cast<napi_env>(engine);
NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(value);
napi_ref ref = holder->GetJsObjectRef();
uint32_t result;
napi_status napiStatus = napi_reference_ref(env, ref, &result);
if (napiStatus != napi_ok) {
ZLOGE(LOG_LABEL, "RemoteObjectDetachCb, failed to increase ref");
} else {
ZLOGI(LOG_LABEL, "RemoteObjectDetachCb, ref result:%{public}u", result);
}
return value;
}
......@@ -106,13 +174,24 @@ static NativeValue *RemoteObjectAttachCb(NativeEngine *engine, void *value, void
NAPIRemoteObjectHolder *createHolder = nullptr;
status = napi_remove_wrap(env, jsRemoteObject, (void **)&createHolder);
NAPI_ASSERT(env, status == napi_ok && createHolder != nullptr, "failed to remove create holder when attach");
status = napi_wrap(env, jsRemoteObject, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
status = napi_wrap(env, jsRemoteObject, holder, RemoteObjectHolderRefCb, nullptr, nullptr);
NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed when attach");
holder->IncAttachCount();
holder->Unlock();
return reinterpret_cast<NativeValue *>(jsRemoteObject);
}
static void OnEnvCleanUp(void *data)
{
if (data == nullptr) {
ZLOGE(LOG_LABEL, "data is null");
return;
}
NAPIRemoteObjectHolder *holder = reinterpret_cast<NAPIRemoteObjectHolder *>(data);
// js env has been destrcted, clear saved env info, and check befor use it
holder->CleanJsEnv();
}
napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
{
// new napi remote object
......@@ -134,7 +213,7 @@ napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
std::string descriptor = stringValue;
auto holder = new NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor));
auto holder = new NAPIRemoteObjectHolder(env, Str8ToStr16(descriptor), thisVar);
auto nativeObj = ConvertNativeValueTo<NativeObject>(reinterpret_cast<NativeValue *>(thisVar));
if (nativeObj == nullptr) {
ZLOGE(LOG_LABEL, "Failed to get RemoteObject native object");
......@@ -145,28 +224,78 @@ napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
// connect native object to js thisVar
napi_status status = napi_wrap(env, thisVar, holder, RemoteObjectHolderFinalizeCb, nullptr, nullptr);
NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed");
if (NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar) == nullptr) {
ZLOGE(LOG_LABEL, "RemoteObject_JS_Constructor create native object failed");
return nullptr;
}
// register listener for env destruction
status = napi_add_env_cleanup_hook(env, OnEnvCleanUp, holder);
NAPI_ASSERT(env, status == napi_ok, "add cleanup hook failed");
return thisVar;
}
NAPIRemoteObject::NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor)
NAPIRemoteObject::NAPIRemoteObject(std::thread::id jsThreadId, napi_env env, napi_ref jsObjectRef,
const std::u16string &descriptor)
: IPCObjectStub(descriptor)
{
env_ = env;
thisVar_ = thisVar;
napi_create_reference(env, thisVar_, 1, &thisVarRef_);
NAPI_ASSERT_RETURN_VOID(env, thisVarRef_ != nullptr, "failed to create ref to js RemoteObject");
jsThreadId_ = jsThreadId;
thisVarRef_ = jsObjectRef;
if (jsThreadId_ == std::this_thread::get_id()) {
IncreaseJsObjectRef(env, jsObjectRef);
} else {
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
uv_work_t *work = new(std::nothrow) uv_work_t;
NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "create NAPIRemoteObject, new work failed");
std::shared_ptr<struct ThreadLockInfo> lockInfo = std::make_shared<struct ThreadLockInfo>();
OperateJsRefParam *param = new OperateJsRefParam {
.env = env_,
.thisVarRef = jsObjectRef,
.lockInfo = lockInfo.get()
};
work->data = reinterpret_cast<void *>(param);
uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
napi_handle_scope scope = nullptr;
napi_open_handle_scope(param->env, &scope);
IncreaseJsObjectRef(param->env, param->thisVarRef);
std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
param->lockInfo->ready = true;
param->lockInfo->condition.notify_all();
napi_close_handle_scope(param->env, scope);
});
std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
param->lockInfo->condition.wait(lock, [&param] { return param->lockInfo->ready; });
delete param;
delete work;
}
}
NAPIRemoteObject::~NAPIRemoteObject()
{
ZLOGI(LOG_LABEL, "NAPIRemoteObject Destructor");
if (thisVarRef_ != nullptr) {
napi_status status = napi_delete_reference(env_, thisVarRef_);
NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js RemoteObject");
if (thisVarRef_ != nullptr && env_ != nullptr) {
if (jsThreadId_ == std::this_thread::get_id()) {
DecreaseJsObjectRef(env_, thisVarRef_);
} else {
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
uv_work_t *work = new(std::nothrow) uv_work_t;
NAPI_ASSERT_RETURN_VOID(env_, work != nullptr, "release NAPIRemoteObject, new work failed");
OperateJsRefParam *param = new OperateJsRefParam {
.env = env_,
.thisVarRef = thisVarRef_
};
work->data = reinterpret_cast<void *>(param);
uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
OperateJsRefParam *param = reinterpret_cast<OperateJsRefParam *>(work->data);
napi_handle_scope scope = nullptr;
napi_open_handle_scope(param->env, &scope);
DecreaseJsObjectRef(param->env, param->thisVarRef);
napi_close_handle_scope(param->env, scope);
delete param;
delete work;
});
}
thisVarRef_ = nullptr;
}
}
......@@ -186,6 +315,12 @@ napi_ref NAPIRemoteObject::GetJsObjectRef() const
return thisVarRef_;
}
void NAPIRemoteObject::ResetJsEnv()
{
env_ = nullptr;
thisVarRef_ = nullptr;
}
void NAPI_RemoteObject_getCallingInfo(CallingInfo &newCallingInfoParam)
{
newCallingInfoParam.callingPid = IPCSkeleton::GetCallingPid();
......@@ -323,6 +458,10 @@ void NAPI_RemoteObject_resetOldCallingInfo(napi_env env, NAPI_CallingInfo &oldCa
int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
{
if (thisVarRef_ == nullptr || env_ == nullptr) {
ZLOGE(LOG_LABEL, "Js env has been destructed");
return ERR_UNKNOWN_REASON;
}
uv_loop_s *loop = nullptr;
napi_get_uv_event_loop(env_, &loop);
......@@ -537,22 +676,6 @@ int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
param->result = ERR_UNKNOWN_TRANSACTION;
break;
}
// Start to call promiseThen
napi_value thenReturnValue;
ret = napi_call_function(param->env, returnVal, promiseThen, 1, &thenValue, &thenReturnValue);
if (ret != napi_ok) {
ZLOGE(LOG_LABEL, "PromiseThen got exception");
param->result = ERR_UNKNOWN_TRANSACTION;
break;
}
// Create promiseCatch
napi_value promiseCatch = nullptr;
napi_get_named_property(param->env, returnVal, "catch", &promiseCatch);
if (promiseCatch == nullptr) {
ZLOGE(LOG_LABEL, "get promiseCatch failed");
param->result = -1;
break;
}
napi_value catchValue;
ret = napi_create_function(param->env, "catchCallback",
NAPI_AUTO_LENGTH, CatchCallback, param, &catchValue);
......@@ -561,15 +684,18 @@ int NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
param->result = ERR_UNKNOWN_TRANSACTION;
break;
}
// Start to call promiseCatch
napi_value catchReturnValue;
ret = napi_call_function(param->env, returnVal, promiseCatch, 1, &catchValue, &catchReturnValue);
// Start to call promiseThen
napi_env env = param->env;
napi_value thenReturnValue;
constexpr uint32_t THEN_ARGC = 2;
napi_value thenArgv[THEN_ARGC] = {thenValue, catchValue};
ret = napi_call_function(env, returnVal, promiseThen, THEN_ARGC, thenArgv, &thenReturnValue);
if (ret != napi_ok) {
ZLOGE(LOG_LABEL, "PromiseCatch got exception");
ZLOGE(LOG_LABEL, "PromiseThen got exception");
param->result = ERR_UNKNOWN_TRANSACTION;
break;
}
napi_close_handle_scope(param->env, scope);
napi_close_handle_scope(env, scope);
return;
} while (0);
......@@ -593,12 +719,11 @@ napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteOb
return nullptr;
}
if (target->CheckObjectLegality()) {
if (!target->IsProxyObject()) {
IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
uint32_t objectType = tmp->GetObjectType();
ZLOGI(LOG_LABEL, "object type:%{public}d", objectType);
ZLOGI(LOG_LABEL, "create js object, type:%{public}d", objectType);
if (objectType == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT || objectType == IPCObjectStub::OBJECT_TYPE_NATIVE) {
sptr<NAPIRemoteObject> object = static_cast<NAPIRemoteObject *>(target.GetRefPtr());
// retrieve js remote object constructor
napi_value global = nullptr;
napi_status status = napi_get_global(env, &global);
......@@ -608,7 +733,7 @@ napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteOb
NAPI_ASSERT(env, status == napi_ok, "set stub constructor failed");
NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteObject constructor");
// retrieve descriptor and it's length
std::u16string descriptor = object->GetObjectDescriptor();
std::u16string descriptor = target->GetObjectDescriptor();
std::string desc = Str16ToStr8(descriptor);
napi_value jsDesc = nullptr;
napi_create_string_utf8(env, desc.c_str(), desc.length(), &jsDesc);
......@@ -622,7 +747,7 @@ napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr<IRemoteOb
NAPIRemoteObjectHolder *holder = nullptr;
napi_unwrap(env, jsRemoteObject, (void **)&holder);
NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
holder->Set(object);
holder->Set(target);
return jsRemoteObject;
}
}
......@@ -659,7 +784,7 @@ sptr<IRemoteObject> NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value
NAPIRemoteObjectHolder *holder = nullptr;
napi_unwrap(env, object, (void **)&holder);
NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
return holder != nullptr ? holder->Get(object) : nullptr;
return holder != nullptr ? holder->Get() : nullptr;
}
napi_value proxyConstructor = nullptr;
......
......@@ -15,56 +15,95 @@
#include "napi_remote_object_holder.h"
#include <uv.h>
#include <string_ex.h>
#include "ipc_debug.h"
#include "log_tags.h"
namespace OHOS {
NAPIRemoteObjectHolder::NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor)
: env_(env), descriptor_(descriptor), cachedObject_(nullptr), localInterfaceRef_(nullptr), attachCount_(1)
{}
static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_remoteObject_holder" };
NAPIRemoteObjectHolder::~NAPIRemoteObjectHolder()
struct DeleteJsRefParam {
napi_env env;
napi_ref thisVarRef;
};
NAPIRemoteObjectHolder::NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor, napi_value thisVar)
: env_(env), descriptor_(descriptor), sptrCachedObject_(nullptr), wptrCachedObject_(nullptr),
localInterfaceRef_(nullptr), attachCount_(1), jsObjectRef_(nullptr)
{
// free the reference of object.
cachedObject_ = nullptr;
if (localInterfaceRef_ != nullptr) {
napi_delete_reference(env_, localInterfaceRef_);
}
jsThreadId_ = std::this_thread::get_id();
// create weak ref, do not need to delete,
// increase ref count when the JS object will transfer to another thread or process.
napi_create_reference(env, thisVar, 0, &jsObjectRef_);
}
sptr<NAPIRemoteObject> NAPIRemoteObjectHolder::Get(napi_value jsRemoteObject)
sptr<IRemoteObject> NAPIRemoteObjectHolder::Get()
{
std::lock_guard<std::mutex> lockGuard(mutex_);
// grab an strong reference to the object,
// so it will not be freed util this reference released.
sptr<NAPIRemoteObject> remoteObject = nullptr;
if (cachedObject_ != nullptr) {
remoteObject = cachedObject_;
if (sptrCachedObject_ != nullptr) {
return sptrCachedObject_;
}
if (remoteObject == nullptr) {
remoteObject = new NAPIRemoteObject(env_, jsRemoteObject, descriptor_);
cachedObject_ = remoteObject;
sptr<IRemoteObject> tmp = wptrCachedObject_.promote();
if (tmp == nullptr && env_ != nullptr) {
tmp = new NAPIRemoteObject(jsThreadId_, env_, jsObjectRef_, descriptor_);
wptrCachedObject_ = tmp;
}
return remoteObject;
return tmp;
}
void NAPIRemoteObjectHolder::Set(sptr<NAPIRemoteObject> object)
void NAPIRemoteObjectHolder::Set(sptr<IRemoteObject> object)
{
std::lock_guard<std::mutex> lockGuard(mutex_);
cachedObject_ = object;
IPCObjectStub *tmp = static_cast<IPCObjectStub *>(object.GetRefPtr());
if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT) {
wptrCachedObject_ = object;
} else {
sptrCachedObject_ = object;
}
}
napi_ref NAPIRemoteObjectHolder::GetJsObjectRef() const
{
return jsObjectRef_;
}
napi_env NAPIRemoteObjectHolder::GetJsObjectEnv() const
{
return env_;
}
void NAPIRemoteObjectHolder::CleanJsEnv()
{
env_ = nullptr;
jsObjectRef_ = nullptr;
sptr<IRemoteObject> tmp = wptrCachedObject_.promote();
if (tmp != nullptr) {
NAPIRemoteObject *object = static_cast<NAPIRemoteObject *>(tmp.GetRefPtr());
ZLOGI(LOG_LABEL, "reset env and napi_ref");
object->ResetJsEnv();
}
}
void NAPIRemoteObjectHolder::attachLocalInterface(napi_value localInterface, std::string &descriptor)
{
if (localInterfaceRef_ != nullptr) {
napi_delete_reference(env_, localInterfaceRef_);
if (env_ == nullptr) {
ZLOGE(LOG_LABEL, "Js env has been destructed");
return;
}
napi_create_reference(env_, localInterface, 1, &localInterfaceRef_);
napi_create_reference(env_, localInterface, 0, &localInterfaceRef_);
descriptor_ = Str8ToStr16(descriptor);
}
napi_value NAPIRemoteObjectHolder::queryLocalInterface(std::string &descriptor)
{
if (env_ == nullptr) {
ZLOGE(LOG_LABEL, "Js env has been destructed");
return nullptr;
}
if (!descriptor_.empty() && strcmp(Str16ToStr8(descriptor_).c_str(), descriptor.c_str()) == 0) {
napi_value ret = nullptr;
napi_get_reference_value(env_, localInterfaceRef_, &ret);
......
......@@ -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<RefBase *>(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<const void *>(&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
......@@ -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<dyn ITest>
{
......@@ -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<String16> = &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);
}
......
......@@ -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<String16>) -> 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();
......
......@@ -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"
......
......@@ -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 {
......