1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! Ashmem provides interfaces for operating shared memory.
15 
16 use std::ffi::{c_char, CString};
17 
18 use cxx::SharedPtr;
19 
20 /// Memory protection corresponding to PROT_NONE in C code.
21 pub const PROT_NONE: i32 = 0;
22 /// Memory protection corresponding to PROT_READ in C code.
23 pub const PROT_READ: i32 = 1;
24 /// Memory protection corresponding to PROT_WRITE in C code.
25 pub const PROT_WRITE: i32 = 2;
26 /// Memory protection corresponding to PROT_EXEC in C code.
27 pub const PROT_EXEC: i32 = 4;
28 
29 #[cxx::bridge(namespace = "OHOS")]
30 /// Module Ashmem::ffi. Includes interfaces which will call c++ counterparts via
31 /// FFI.
32 pub mod ffi {
33     unsafe extern "C++" {
34         include!("commonlibrary/c_utils/base/include/ashmem.h");
35 
36         // global function
37         /// Create an C++ Ashmem object managed by std::shared_ptr.
38         /// # Safety
39         /// Requires C-style string as parameter to specify the name of Ashmem.
CreateAshmemStd(name: *const c_char, size: i32) -> SharedPtr<Ashmem>40         pub unsafe fn CreateAshmemStd(name: *const c_char, size: i32) -> SharedPtr<Ashmem>;
41 
42         /// Set protection flag of created ashmem specified by FD.
AshmemSetProt(fd: i32, prot: i32) -> i3243         pub fn AshmemSetProt(fd: i32, prot: i32) -> i32;
44 
45         /// Get size of created ashmem specified by FD.
AshmemGetSize(fd: i32) -> i3246         pub fn AshmemGetSize(fd: i32) -> i32;
47 
48         /// C++ void type.
49         pub type c_void;
50         /// Cast c_char to c_void
51         /// # Safety
AsVoidPtr(inPtr: *const c_char) -> *const c_void52         pub unsafe fn AsVoidPtr(inPtr: *const c_char) -> *const c_void;
53 
54         /// Cast c_char to c_void
55         /// # Safety
AsCharPtr(inPtr: *const c_void) -> *const c_char56         pub unsafe fn AsCharPtr(inPtr: *const c_void) -> *const c_char;
57 
58         /// C++ Ashmem class.
59         pub type Ashmem;
60 
61         // member function
62         /// Close inner ashmem.
CloseAshmem(self: &Ashmem) -> ()63         pub fn CloseAshmem(self: &Ashmem) -> ();
64 
65         /// Map inner ashmem to user-space memory with specified map type.
MapAshmem(self: &Ashmem, mapType: i32) -> bool66         pub fn MapAshmem(self: &Ashmem, mapType: i32) -> bool;
67 
68         /// Map inner ashmem to user-space memory with read-write type.
MapReadAndWriteAshmem(self: &Ashmem) -> bool69         pub fn MapReadAndWriteAshmem(self: &Ashmem) -> bool;
70 
71         /// Map inner ashmem to user-space memory with read-only type.
MapReadOnlyAshmem(self: &Ashmem) -> bool72         pub fn MapReadOnlyAshmem(self: &Ashmem) -> bool;
73 
74         /// UnMap inner ashmem.
UnmapAshmem(self: &Ashmem) -> ()75         pub fn UnmapAshmem(self: &Ashmem) -> ();
76 
77         /// Set protection flag of inner ashmem.
SetProtection(self: &Ashmem, protType: i32) -> bool78         pub fn SetProtection(self: &Ashmem, protType: i32) -> bool;
79 
80         /// Get protection flag of inner ashmem.
GetProtection(self: &Ashmem) -> i3281         pub fn GetProtection(self: &Ashmem) -> i32;
82 
83         /// Get size of inner ashmem.
GetAshmemSize(self: &Ashmem) -> i3284         pub fn GetAshmemSize(self: &Ashmem) -> i32;
85 
86         /// Write data to inner ashmem.
87         /// # Safety
88         /// Requires a C++-style void pointer as parameter to indicates data
89         /// expected to be written.
WriteToAshmem( self: &Ashmem, data: *const c_void, size: i32, offset: i32, ) -> bool90         pub unsafe fn WriteToAshmem(
91             self: &Ashmem,
92             data: *const c_void,
93             size: i32,
94             offset: i32,
95         ) -> bool;
96 
97         /// Read data from inner ashmem.
98         /// # Safety
99         /// Returns a C++-style void pointer to indicates data expected to be
100         /// read.
ReadFromAshmem(self: &Ashmem, size: i32, offset: i32) -> *const c_void101         pub unsafe fn ReadFromAshmem(self: &Ashmem, size: i32, offset: i32) -> *const c_void;
102 
103         /// Get FD of inner ashmem.
GetAshmemFd(self: &Ashmem) -> i32104         pub fn GetAshmemFd(self: &Ashmem) -> i32;
105     }
106 }
107 
108 /// Ashmem in rust.
109 pub struct Ashmem {
110     c_ashmem: SharedPtr<ffi::Ashmem>,
111 }
112 
113 /// Ashmem implementation.
114 impl Ashmem {
115     /// Create an ashmem object.
new(c_ashmem: SharedPtr<ffi::Ashmem>) -> Ashmem116     pub fn new(c_ashmem: SharedPtr<ffi::Ashmem>) -> Ashmem {
117         Ashmem { c_ashmem }
118     }
119 
120     /// Get corresponding fd.
get_ashmem_fd(&self) -> i32121     pub fn get_ashmem_fd(&self) -> i32 {
122         self.c_ashmem.GetAshmemFd()
123     }
124 
125     /// Get size of the shared memory.
get_ashmem_size(&self) -> i32126     pub fn get_ashmem_size(&self) -> i32 {
127         self.c_ashmem.GetAshmemSize()
128     }
129 
130     /// Get memory protection flags.
get_protection(&self) -> i32131     pub fn get_protection(&self) -> i32 {
132         self.c_ashmem.GetProtection()
133     }
134 
135     /// Set memory protection flags.
set_protection(&self, prot_type: i32) -> bool136     pub fn set_protection(&self, prot_type: i32) -> bool {
137         self.c_ashmem.SetProtection(prot_type)
138     }
139 
140     /// Map the shared memory to user-space.
map_ashmem(&self, prot_type: i32) -> bool141     pub fn map_ashmem(&self, prot_type: i32) -> bool {
142         self.c_ashmem.MapAshmem(prot_type)
143     }
144 
145     /// Map ashmem in read&write mode.
map_read_write_ashmem(&self) -> bool146     pub fn map_read_write_ashmem(&self) -> bool {
147         self.c_ashmem.MapReadAndWriteAshmem()
148     }
149 
150     /// Map ashmem in read-only mode.
map_read_only_ashmem(&self) -> bool151     pub fn map_read_only_ashmem(&self) -> bool {
152         self.c_ashmem.MapReadOnlyAshmem()
153     }
154 
155     /// Unmap ashmem.
unmap_ashmem(&self)156     pub fn unmap_ashmem(&self) {
157         self.c_ashmem.UnmapAshmem()
158     }
159 
160     /// Close ashmem.
close_ashmem(&self)161     pub fn close_ashmem(&self) {
162         self.c_ashmem.CloseAshmem()
163     }
164 
165     /// Write data to ashmem.
166     /// # Safety
167     /// Requires c-style data(*const c_char)
write_to_ashmem(&self, data: *const c_char, size: i32, offset: i32) -> bool168     pub unsafe fn write_to_ashmem(&self, data: *const c_char, size: i32, offset: i32) -> bool {
169         let c_void_ptr = ffi::AsVoidPtr(data);
170         self.c_ashmem.WriteToAshmem(c_void_ptr, size, offset)
171     }
172 
173     /// Gets inner c_ashemem.
174     ///
175     /// # Safety
176     /// Returns c++ opaque shared ptr.
c_ashmem(&self) -> &SharedPtr<ffi::Ashmem>177     pub unsafe fn c_ashmem(&self) -> &SharedPtr<ffi::Ashmem> {
178         &self.c_ashmem
179     }
180 
181     /// Read data from ashmem.
182     /// # Safety
183     /// Returns c-style data(*const c_char)
read_from_ashmem(&self, size: i32, offset: i32) -> *const c_char184     pub unsafe fn read_from_ashmem(&self, size: i32, offset: i32) -> *const c_char {
185         let c_void_ptr = self.c_ashmem.ReadFromAshmem(size, offset);
186         ffi::AsCharPtr(c_void_ptr)
187     }
188 }
189 
190 /// Create Ashmem struct in Rust, which holds a refrence to c++ Ashmem object.
191 /// # Safety
192 /// Transmits c-style string of `name`.
create_ashmem_instance(name: &str, size: i32) -> Option<Ashmem>193 pub unsafe fn create_ashmem_instance(name: &str, size: i32) -> Option<Ashmem> {
194     let c_name = CString::new(name).expect("CString::new Failed!");
195     let name_ptr = c_name.as_ptr();
196     let c_ashmem_ptr = ffi::CreateAshmemStd(name_ptr, size);
197 
198     if c_ashmem_ptr.is_null() {
199         None
200     } else {
201         Some(Ashmem::new(c_ashmem_ptr))
202     }
203 }
204