• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 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 #![allow(unreachable_pub, missing_docs, unused)]
15 use std::collections::HashMap;
16 use std::fs::File;
17 use std::os::fd::FromRawFd;
18 use std::pin::Pin;
19 
20 pub(crate) use ffi::*;
21 pub use ffi::{OnDemandReasonExtraData, OnDemandReasonId, SystemAbilityOnDemandReason};
22 use ipc::parcel::{Deserialize, MsgParcel, Serialize};
23 use ipc::remote::RemoteStub;
24 use ipc::IpcStatusCode;
25 
26 use crate::ability::{Ability, Handler};
27 
28 // `SystemAbility` trait is not used is because their methods are not recognized
29 // by cxx.
30 #[allow(non_snake_case)]
31 impl AbilityWrapper {
OnDump(&self)32     fn OnDump(&self) {
33         self.inner.on_dump()
34     }
35 
OnStart(&self, system_ability: *mut ffi::SystemAbilityWrapper)36     fn OnStart(&self, system_ability: *mut ffi::SystemAbilityWrapper) {
37         let handle = Handler {
38             inner: system_ability,
39         };
40         self.inner.on_start(handle)
41     }
42 
OnStartWithReason( &self, reason: ffi::SystemAbilityOnDemandReason, system_ability: *mut ffi::SystemAbilityWrapper, )43     fn OnStartWithReason(
44         &self,
45         reason: ffi::SystemAbilityOnDemandReason,
46         system_ability: *mut ffi::SystemAbilityWrapper,
47     ) {
48         let handle = Handler {
49             inner: system_ability,
50         };
51         self.inner.on_start_with_reason(reason, handle);
52     }
53 
OnIdle(&self, reason: ffi::SystemAbilityOnDemandReason) -> i3254     fn OnIdle(&self, reason: ffi::SystemAbilityOnDemandReason) -> i32 {
55         self.inner.on_idle(reason)
56     }
57 
OnActive(&self, reason: ffi::SystemAbilityOnDemandReason)58     fn OnActive(&self, reason: ffi::SystemAbilityOnDemandReason) {
59         self.inner.on_active(reason)
60     }
61 
OnStop(&self)62     fn OnStop(&self) {
63         self.inner.on_stop()
64     }
65 
OnStopWithReason(&self, reason: ffi::SystemAbilityOnDemandReason)66     fn OnStopWithReason(&self, reason: ffi::SystemAbilityOnDemandReason) {
67         self.inner.on_stop_with_reason(reason)
68     }
69 
OnAddSystemAbility(&self, said: i32, device_id: String)70     fn OnAddSystemAbility(&self, said: i32, device_id: String) {
71         self.inner.on_system_ability_load_event(said, device_id)
72     }
73 
OnRemoveSystemAbility(&self, said: i32, device_id: String)74     fn OnRemoveSystemAbility(&self, said: i32, device_id: String) {
75         self.inner.on_system_ability_remove_event(said, device_id)
76     }
77 
OnDeviceLevelChanged(&self, change_type: i32, level: i32, action: String)78     fn OnDeviceLevelChanged(&self, change_type: i32, level: i32, action: String) {
79         self.inner
80             .on_device_level_changed(change_type, level, action)
81     }
82 
OnExtension( &self, extension: String, data: Pin<&mut MessageParcel>, reply: Pin<&mut MessageParcel>, ) -> i3283     fn OnExtension(
84         &self,
85         extension: String,
86         data: Pin<&mut MessageParcel>,
87         reply: Pin<&mut MessageParcel>,
88     ) -> i32 {
89         unsafe {
90             let mut data = MsgParcel::from_ptr(data.get_unchecked_mut() as *mut MessageParcel);
91             let mut reply = MsgParcel::from_ptr(reply.get_unchecked_mut() as *mut MessageParcel);
92             self.inner.on_extension(extension, &mut data, &mut reply)
93         }
94     }
95 }
96 
97 pub struct AbilityStub {
98     inner: Box<dyn RemoteStub>,
99 }
100 
101 impl AbilityStub {
new<A: RemoteStub + 'static>(remote: A) -> Self102     pub fn new<A: RemoteStub + 'static>(remote: A) -> Self {
103         Self {
104             inner: Box::new(remote),
105         }
106     }
107 
on_remote_request( &mut self, code: u32, data: Pin<&mut MessageParcel>, reply: Pin<&mut MessageParcel>, ) -> i32108     pub fn on_remote_request(
109         &mut self,
110         code: u32,
111         data: Pin<&mut MessageParcel>,
112         reply: Pin<&mut MessageParcel>,
113     ) -> i32 {
114         unsafe {
115             let mut data = MsgParcel::from_ptr(data.get_unchecked_mut() as *mut MessageParcel);
116             let mut reply = MsgParcel::from_ptr(reply.get_unchecked_mut() as *mut MessageParcel);
117             self.inner.on_remote_request(code, &mut data, &mut reply)
118         }
119     }
120 
dump(&mut self, fd: i32, args: Vec<String>) -> i32121     pub fn dump(&mut self, fd: i32, args: Vec<String>) -> i32 {
122         let file = unsafe { File::from_raw_fd(fd) };
123         self.inner.dump(file, args)
124     }
125 }
126 
127 pub struct AbilityWrapper {
128     pub(crate) inner: Box<dyn Ability>,
129 }
130 
131 impl Serialize for OnDemandReasonId {
serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()>132     fn serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()> {
133         parcel.write(&self.repr)
134     }
135 }
136 
137 impl Deserialize for OnDemandReasonId {
deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self>138     fn deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self> {
139         let res = match parcel.read::<i32>()? {
140             0 => Self::INTERFACE_CALL,
141             1 => Self::DEVICE_ONLINE,
142             2 => Self::SETTING_SWITCH,
143             3 => Self::PARAM,
144             4 => Self::COMMON_EVENT,
145             5 => Self::TIMED_EVENT,
146             _ => return Err(IpcStatusCode::Failed),
147         };
148         Ok(res)
149     }
150 }
151 
152 impl Serialize for OnDemandReasonExtraData {
serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()>153     fn serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()> {
154         if SerializeOnDemandReasonExtraData(self, parcel.pin_mut().unwrap()) {
155             Ok(())
156         } else {
157             Err(IpcStatusCode::Failed)
158         }
159     }
160 }
161 
162 impl Deserialize for OnDemandReasonExtraData {
deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self>163     fn deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self> {
164         Ok(DeserializeOnDemandReasonExtraData(
165             parcel.pin_mut().unwrap(),
166         ))
167     }
168 }
169 
170 impl Serialize for SystemAbilityOnDemandReason {
serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()>171     fn serialize(&self, parcel: &mut MsgParcel) -> ipc::IpcResult<()> {
172         parcel.write(&self.name)?;
173         parcel.write(&self.value)?;
174         parcel.write(&self.reason_id)?;
175         parcel.write(&self.extra_data)?;
176         parcel.write(&self.extra_data_id)
177     }
178 }
179 
180 impl Deserialize for SystemAbilityOnDemandReason {
deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self>181     fn deserialize(parcel: &mut MsgParcel) -> ipc::IpcResult<Self> {
182         let name = parcel.read()?;
183         let value = parcel.read()?;
184         let reason_id = parcel.read()?;
185         let extra_data = parcel.read()?;
186         let extra_data_id = parcel.read()?;
187         Ok(Self {
188             name,
189             value,
190             reason_id,
191             extra_data,
192             extra_data_id,
193         })
194     }
195 }
196 
197 impl OnDemandReasonExtraData {
want(self) -> HashMap<String, String>198     pub fn want(self) -> HashMap<String, String> {
199         let mut res = HashMap::new();
200         let mut want = self.want.into_iter();
201         while let Some(k) = want.next() {
202             if let Some(v) = want.next() {
203                 res.insert(k, v);
204             }
205         }
206         res
207     }
208 }
209 
210 /// AbilityWrapper used for cxx
211 #[cxx::bridge(namespace = "OHOS::SafwkRust")]
212 mod ffi {
213     #[repr(i32)]
214     #[derive(Debug)]
215     pub enum OnDemandReasonId {
216         INTERFACE_CALL = 0,
217         DEVICE_ONLINE = 1,
218         SETTING_SWITCH = 2,
219         PARAM = 3,
220         COMMON_EVENT = 4,
221         TIMED_EVENT = 5,
222     }
223 
224     #[derive(Debug)]
225     pub struct SystemAbilityOnDemandReason {
226         pub name: String,
227         pub value: String,
228         pub reason_id: OnDemandReasonId,
229         pub extra_data: OnDemandReasonExtraData,
230         pub extra_data_id: i64,
231     }
232 
233     #[derive(Debug)]
234     pub struct OnDemandReasonExtraData {
235         pub data: String,
236         pub code: i32,
237         pub want: Vec<String>,
238     }
239 
240     extern "Rust" {
241         type AbilityWrapper;
242         type AbilityStub;
on_remote_request( self: &mut AbilityStub, code: u32, data: Pin<&mut MessageParcel>, reply: Pin<&mut MessageParcel>, ) -> i32243         fn on_remote_request(
244             self: &mut AbilityStub,
245             code: u32,
246             data: Pin<&mut MessageParcel>,
247             reply: Pin<&mut MessageParcel>,
248         ) -> i32;
249 
dump(self: &mut AbilityStub, fd: i32, args: Vec<String>) -> i32250         fn dump(self: &mut AbilityStub, fd: i32, args: Vec<String>) -> i32;
251 
OnDump(self: &AbilityWrapper)252         fn OnDump(self: &AbilityWrapper);
253 
OnStart(self: &AbilityWrapper, system_ability: *mut SystemAbilityWrapper)254         unsafe fn OnStart(self: &AbilityWrapper, system_ability: *mut SystemAbilityWrapper);
OnStartWithReason( self: &AbilityWrapper, reason: SystemAbilityOnDemandReason, system_ability: *mut SystemAbilityWrapper, )255         unsafe fn OnStartWithReason(
256             self: &AbilityWrapper,
257             reason: SystemAbilityOnDemandReason,
258             system_ability: *mut SystemAbilityWrapper,
259         );
OnIdle(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason) -> i32260         fn OnIdle(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason) -> i32;
OnActive(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason)261         fn OnActive(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason);
OnStop(self: &AbilityWrapper)262         fn OnStop(self: &AbilityWrapper);
OnStopWithReason(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason)263         fn OnStopWithReason(self: &AbilityWrapper, reason: SystemAbilityOnDemandReason);
264 
OnAddSystemAbility(self: &AbilityWrapper, said: i32, device_id: String)265         fn OnAddSystemAbility(self: &AbilityWrapper, said: i32, device_id: String);
OnRemoveSystemAbility(self: &AbilityWrapper, said: i32, device_id: String)266         fn OnRemoveSystemAbility(self: &AbilityWrapper, said: i32, device_id: String);
OnDeviceLevelChanged( self: &AbilityWrapper, change_type: i32, level: i32, action: String, )267         fn OnDeviceLevelChanged(
268             self: &AbilityWrapper,
269             change_type: i32,
270             level: i32,
271             action: String,
272         );
OnExtension( self: &AbilityWrapper, extension: String, data: Pin<&mut MessageParcel>, reply: Pin<&mut MessageParcel>, ) -> i32273         fn OnExtension(
274             self: &AbilityWrapper,
275             extension: String,
276             data: Pin<&mut MessageParcel>,
277             reply: Pin<&mut MessageParcel>,
278         ) -> i32;
279     }
280 
281     // C++ types and signatures exposed to Rust.
282     unsafe extern "C++" {
283         include!("system_ability_wrapper.h");
284         include!("system_ability.h");
285         include!("system_ability_ondemand_reason.h");
286         #[namespace = "OHOS"]
287         type OnDemandReasonId;
288 
289         #[namespace = "OHOS"]
290         type MessageParcel = ipc::cxx_share::MessageParcel;
291 
292         type SystemAbilityWrapper;
293 
BuildSystemAbility( ability: Box<AbilityWrapper>, system_ability_id: i32, run_on_create: bool, ) -> UniquePtr<SystemAbilityWrapper>294         fn BuildSystemAbility(
295             ability: Box<AbilityWrapper>,
296             system_ability_id: i32,
297             run_on_create: bool,
298         ) -> UniquePtr<SystemAbilityWrapper>;
299 
RegisterAbility(system_ability: *mut SystemAbilityWrapper) -> bool300         unsafe fn RegisterAbility(system_ability: *mut SystemAbilityWrapper) -> bool;
301 
AddSystemAbilityListener( self: Pin<&mut SystemAbilityWrapper>, mut system_ability_id: i32, ) -> bool302         fn AddSystemAbilityListener(
303             self: Pin<&mut SystemAbilityWrapper>,
304             mut system_ability_id: i32,
305         ) -> bool;
306 
RemoveSystemAbilityListener( self: Pin<&mut SystemAbilityWrapper>, mut system_ability_id: i32, ) -> bool307         fn RemoveSystemAbilityListener(
308             self: Pin<&mut SystemAbilityWrapper>,
309             mut system_ability_id: i32,
310         ) -> bool;
311 
CancelIdleWrapper(self: Pin<&mut SystemAbilityWrapper>) -> bool312         fn CancelIdleWrapper(self: Pin<&mut SystemAbilityWrapper>) -> bool;
313 
PublishWrapper(self: Pin<&mut SystemAbilityWrapper>, ability: Box<AbilityStub>) -> bool314         fn PublishWrapper(self: Pin<&mut SystemAbilityWrapper>, ability: Box<AbilityStub>) -> bool;
315 
DeserializeOnDemandReasonExtraData( data: Pin<&mut MessageParcel>, ) -> OnDemandReasonExtraData316         fn DeserializeOnDemandReasonExtraData(
317             data: Pin<&mut MessageParcel>,
318         ) -> OnDemandReasonExtraData;
319 
SerializeOnDemandReasonExtraData( extraData: &OnDemandReasonExtraData, data: Pin<&mut MessageParcel>, ) -> bool320         fn SerializeOnDemandReasonExtraData(
321             extraData: &OnDemandReasonExtraData,
322             data: Pin<&mut MessageParcel>,
323         ) -> bool;
324 
OnExtension( self: Pin<&mut SystemAbilityWrapper>, extension: &CxxString, data: Pin<&mut MessageParcel>, reply: Pin<&mut MessageParcel>, ) -> i32325         fn OnExtension(
326             self: Pin<&mut SystemAbilityWrapper>,
327             extension: &CxxString,
328             data: Pin<&mut MessageParcel>,
329             reply: Pin<&mut MessageParcel>,
330         ) -> i32;
331     }
332 }
333 
334 #[cfg(test)]
335 mod test {
336     use std::cell::RefCell;
337     use std::rc::Rc;
338 
339     use cxx::let_cxx_string;
340 
341     use super::*;
342     #[test]
on_extension_ut()343     fn on_extension_ut() {
344         const TEST_EXTENSION: &str = "test";
345         const TEST_RETURN: i32 = 0;
346 
347         struct TestAbility {
348             inner: Rc<RefCell<String>>,
349         }
350         impl Ability for TestAbility {
351             fn on_extension(
352                 &self,
353                 extension: String,
354                 data: &mut MsgParcel,
355                 reply: &mut MsgParcel,
356             ) -> i32 {
357                 self.inner.borrow_mut().push_str(&extension);
358                 data.write(TEST_EXTENSION).unwrap();
359                 reply.write(TEST_EXTENSION).unwrap();
360                 TEST_RETURN
361             }
362         }
363 
364         let extension = Rc::new(RefCell::new(String::new()));
365         let ability = TestAbility {
366             inner: extension.clone(),
367         };
368         let ability = Box::new(AbilityWrapper {
369             inner: Box::new(ability),
370         });
371         let mut sys = BuildSystemAbility(ability, 3706, true);
372         let mut data = MsgParcel::new();
373         let mut reply = MsgParcel::new();
374         let_cxx_string!(cxx_s = TEST_EXTENSION);
375         assert_eq!(
376             sys.pin_mut()
377                 .OnExtension(&cxx_s, data.pin_mut().unwrap(), reply.pin_mut().unwrap(),),
378             TEST_RETURN
379         );
380         assert_eq!(*extension.borrow_mut(), TEST_EXTENSION);
381         assert_eq!(data.read::<String>().unwrap(), TEST_EXTENSION);
382         assert_eq!(reply.read::<String>().unwrap(), TEST_EXTENSION);
383     }
384 }
385