remote_stub.rs 3.5 KB
Newer Older
F
fanxiaoyu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * 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.
 */

use crate::{ipc_binding, IRemoteStub, IRemoteBroker, RemoteObj, BorrowedMsgParcel, };
use crate::ipc_binding::{CRemoteObject, CParcel};
use std::ffi::{c_void, CString};
use std::ops::{Deref};

/// RemoteStub packed the native CRemoteObject and the rust stub object T
/// which must implement IRemoteStub trait.
#[repr(C)]
pub struct RemoteStub<T: IRemoteStub> {
    native: *mut CRemoteObject,
    rust: *mut T,
}

impl<T: IRemoteStub> RemoteStub<T> {
F
fanxiaoyu 已提交
30
    /// Create a RemoteStub object
F
fanxiaoyu 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
    pub fn new(rust: T) -> Option<Self> {
        let rust = Box::into_raw(Box::new(rust));
        let descripor = CString::new(T::get_descriptor()).expect("descripor must be valid!");
        // SAFETY:TODO
        let native = unsafe {
            // 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)
        };
        if native.is_null() {
            None
        } else {
            Some( RemoteStub { native, rust } )
        }
    }
}

impl<T: IRemoteStub> IRemoteBroker for RemoteStub<T> {
    fn as_object(&self) -> Option<RemoteObj> {
        // SAFETY: TODO
        unsafe {
            // add remote object reference count
            ipc_binding::RemoteObjectIncStrongRef(self.native);
            // construct a new RemoteObject from a native pointer
            RemoteObj::from_raw(self.native)
        }
    }
}

unsafe impl<T: IRemoteStub> Send for RemoteStub<T> {}
unsafe impl<T: IRemoteStub> Sync for RemoteStub<T> {}

impl<T: IRemoteStub> Deref for RemoteStub<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        // SAFETY: Rust `Box::into_raw` poiter, so is valid
        unsafe {
            &*self.rust
        }
    }
}

impl<T: IRemoteStub> Drop for RemoteStub<T> {
    fn drop(&mut self) {
        unsafe {
            ipc_binding::RemoteObjectDecStrongRef(self.native);
        }
    }
}

/// C call Rust
impl<T: IRemoteStub> RemoteStub<T> {
    unsafe extern "C" fn on_remote_request(stub: *mut CRemoteObject, code: u32,
        data: *const CParcel, reply: *mut CParcel) -> i32 {
        let res = {
            let mut reply = BorrowedMsgParcel::from_raw(reply).unwrap();
            let data = BorrowedMsgParcel::from_raw(data as *mut CParcel).unwrap();
            let object = ipc_binding::RemoteObjectGetUserData(stub);
            let rust_object: &T = &*(object as *const T);
            rust_object.on_remote_request(code, &data, &mut reply)
        };
F
fanxiaoyu 已提交
94
        res
F
fanxiaoyu 已提交
95 96 97 98 99 100 101 102
    }

    unsafe extern "C" fn on_destroy(user_data: *mut c_void) {
        println!("RemoteStub<T> on_destroy in Rust");
        // T will be freed by Box after this function end.
        drop(Box::from_raw(user_data as *mut T));
    }
}