• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! This module is responsible for registering and publishing system services.
15 
16 use std::mem::MaybeUninit;
17 use std::sync::Mutex;
18 
19 use hisysevent::{build_number_param, write, EventType};
20 use samgr::definition::APP_MGR_SERVICE_ID;
21 use samgr::manage::SystemAbilityManager;
22 use system_ability_fwk::ability::{Ability, Handler};
23 
24 use crate::manage::app_state::AppStateListener;
25 use crate::manage::events::TaskManagerEvent;
26 use crate::manage::task_manager::TaskManagerTx;
27 use crate::manage::{account, SystemConfigManager, TaskManager};
28 use crate::service::active_counter::ActiveCounter;
29 use crate::service::client::ClientManager;
30 use crate::service::run_count::RunCountManager;
31 use crate::service::RequestServiceStub;
32 use crate::utils::update_policy;
33 
34 pub(crate) static mut PANIC_INFO: Option<String> = None;
35 
36 pub(crate) static mut SYSTEM_CONFIG_MANAGER: MaybeUninit<SystemConfigManager> =
37     MaybeUninit::uninit();
38 
39 /// The structure of `Request System Ability`.
40 ///
41 /// This structure is responsible for interacting with `System Ability Manager`.
42 pub struct RequestAbility {
43     task_manager: Mutex<Option<TaskManagerTx>>,
44     active_counter: ActiveCounter,
45 }
46 
47 impl RequestAbility {
48     /// Creates a new `RequestAbility`.
new() -> Self49     pub fn new() -> Self {
50         Self {
51             active_counter: ActiveCounter::new(),
52             task_manager: Mutex::new(None),
53         }
54     }
55 
init(&self, handler: Handler)56     fn init(&self, handler: Handler) {
57         info!("ability init");
58 
59         // Use a structure to handle panic.
60         std::panic::set_hook(Box::new(|info| unsafe {
61             let info = info.to_string();
62             error!("{}", info);
63             PANIC_INFO = Some(info);
64         }));
65 
66         ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
67             .worker_num(4)
68             .build_global()
69             .unwrap();
70         info!("ylong_runtime init ok");
71 
72         let runcount_manager = RunCountManager::init();
73         info!("runcount_manager init ok");
74 
75         let client_manger = ClientManager::init();
76         info!("client_manger init ok");
77 
78         // Use methods to handle rather than directly accessing members.
79         unsafe { SYSTEM_CONFIG_MANAGER.write(SystemConfigManager::init()) };
80         info!("system_config_manager init ok");
81 
82         let task_manager = TaskManager::init(runcount_manager.clone(), client_manger.clone(), self.active_counter.clone());
83         *self.task_manager.lock().unwrap() = Some(task_manager.clone());
84         info!("task_manager init ok");
85 
86         AppStateListener::init(client_manger.clone(), task_manager.clone());
87 
88         SystemAbilityManager::subscribe_system_ability(
89             APP_MGR_SERVICE_ID,
90             |_, _| {
91                 info!("app manager service init");
92                 AppStateListener::register();
93             },
94             |_, _| {
95                 error!("app manager service died");
96             },
97         );
98 
99         let stub = RequestServiceStub::new(
100             handler.clone(),
101             task_manager,
102             client_manger,
103             runcount_manager,
104             self.active_counter.clone(),
105         );
106 
107         info!("ability init succeed");
108         if !handler.publish(stub) {
109             service_start_fault();
110         }
111     }
112 }
113 
114 impl Ability for RequestAbility {
on_start_with_reason( &self, reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason, handler: Handler, )115     fn on_start_with_reason(
116         &self,
117         reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason,
118         handler: Handler,
119     ) {
120         info!("on_start_with_reason: {:?}", reason);
121         if reason.name == "usual.event.USER_REMOVED" {
122             let user_id = reason.value.parse::<i32>().unwrap();
123             account::remove_account_tasks(user_id);
124             self.init(handler);
125         } else {
126             self.init(handler);
127         }
128         const INIT_POLICY: bool = false;
129         let _ = update_policy(INIT_POLICY);
130     }
131 
on_active(&self, reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason)132     fn on_active(&self, reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason) {
133         info!("on_active: {:?}", reason);
134     }
135 
on_idle(&self, reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason) -> i32136     fn on_idle(&self, reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason) -> i32 {
137         if self.active_counter.is_active() {
138             info!("remote is busy reject idle, reason: {:?}", reason);
139             -1
140         } else {
141             info!("remote not busy accept idle, reason: {:?}", reason);
142             0
143         }
144     }
145 
on_device_level_changed(&self, change_type: i32, level: i32, action: String)146     fn on_device_level_changed(&self, change_type: i32, level: i32, action: String) {
147         info!(
148             "on_device_level_changed type {} level {} action {}",
149             change_type, level, action
150         );
151         if let Some(task_manager) = self.task_manager.lock().unwrap().as_ref() {
152             task_manager.send_event(TaskManagerEvent::Device(level));
153         }
154     }
155 }
156 
157 #[cfg(not(test))]
158 #[used]
159 #[link_section = ".init_array"]
160 static A: extern "C" fn() = {
161     #[link_section = ".text.startup"]
init()162     extern "C" fn init() {
163         info!("begin request service init");
164         let system_ability = RequestAbility::new()
165             .build_system_ability(samgr::definition::DOWNLOAD_SERVICE_ID, false)
166             .unwrap();
167         system_ability.register();
168         info!("request service inited");
169     }
170     init
171 };
172 
173 // TODO: Use `SysEvent` instead.
service_start_fault()174 fn service_start_fault() {
175     const DOMAIN: &str = "REQUEST";
176     const SERVICE_START_FAULT: &str = "SERVICE_START_FAULT";
177     const ERROR_INFO: &str = "ERROR_INFO";
178     const DOWNLOAD_PUBLISH_FAIL: i32 = -1;
179 
180     write(
181         DOMAIN,
182         SERVICE_START_FAULT,
183         EventType::Fault,
184         &[build_number_param!(ERROR_INFO, DOWNLOAD_PUBLISH_FAIL)],
185     );
186 }
187