xref: /aosp_15_r20/system/extras/profcollectd/libprofcollectd/lib.rs (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker //
2*288bf522SAndroid Build Coastguard Worker // Copyright (C) 2020 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker //
4*288bf522SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker //
8*288bf522SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker //
10*288bf522SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker // limitations under the License.
15*288bf522SAndroid Build Coastguard Worker //
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker //! ProfCollect Binder client interface.
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker mod config;
20*288bf522SAndroid Build Coastguard Worker mod report;
21*288bf522SAndroid Build Coastguard Worker mod scheduler;
22*288bf522SAndroid Build Coastguard Worker mod service;
23*288bf522SAndroid Build Coastguard Worker mod trace_provider;
24*288bf522SAndroid Build Coastguard Worker 
25*288bf522SAndroid Build Coastguard Worker use anyhow::{Context, Result};
26*288bf522SAndroid Build Coastguard Worker use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::{
27*288bf522SAndroid Build Coastguard Worker     self, BnProfCollectd,
28*288bf522SAndroid Build Coastguard Worker };
29*288bf522SAndroid Build Coastguard Worker use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProviderStatusCallback::{IProviderStatusCallback, BnProviderStatusCallback};
30*288bf522SAndroid Build Coastguard Worker use profcollectd_aidl_interface::binder::{self, BinderFeatures};
31*288bf522SAndroid Build Coastguard Worker use service::{err_to_binder_status, ProfcollectdBinderService};
32*288bf522SAndroid Build Coastguard Worker use std::time::{Duration, Instant};
33*288bf522SAndroid Build Coastguard Worker 
34*288bf522SAndroid Build Coastguard Worker const PROFCOLLECTD_SERVICE_NAME: &str = "profcollectd";
35*288bf522SAndroid Build Coastguard Worker 
36*288bf522SAndroid Build Coastguard Worker struct ProviderStatusCallback {
37*288bf522SAndroid Build Coastguard Worker     service_start_time: Instant,
38*288bf522SAndroid Build Coastguard Worker }
39*288bf522SAndroid Build Coastguard Worker 
40*288bf522SAndroid Build Coastguard Worker impl binder::Interface for ProviderStatusCallback {}
41*288bf522SAndroid Build Coastguard Worker 
42*288bf522SAndroid Build Coastguard Worker impl IProviderStatusCallback for ProviderStatusCallback {
onProviderReady(&self) -> binder::Result<()>43*288bf522SAndroid Build Coastguard Worker     fn onProviderReady(&self) -> binder::Result<()> {
44*288bf522SAndroid Build Coastguard Worker         // If we have waited too long for the provider to be ready, then we have passed
45*288bf522SAndroid Build Coastguard Worker         // boot phase, and no need to collect boot profile.
46*288bf522SAndroid Build Coastguard Worker         // TODO: should we check boottime instead?
47*288bf522SAndroid Build Coastguard Worker         const TIMEOUT_TO_COLLECT_BOOT_PROFILE: Duration = Duration::from_secs(3);
48*288bf522SAndroid Build Coastguard Worker         let elapsed = Instant::now().duration_since(self.service_start_time);
49*288bf522SAndroid Build Coastguard Worker         if elapsed < TIMEOUT_TO_COLLECT_BOOT_PROFILE {
50*288bf522SAndroid Build Coastguard Worker             trace_system("boot").map_err(err_to_binder_status)?;
51*288bf522SAndroid Build Coastguard Worker         }
52*288bf522SAndroid Build Coastguard Worker         schedule().map_err(err_to_binder_status)?;
53*288bf522SAndroid Build Coastguard Worker         Ok(())
54*288bf522SAndroid Build Coastguard Worker     }
55*288bf522SAndroid Build Coastguard Worker }
56*288bf522SAndroid Build Coastguard Worker 
57*288bf522SAndroid Build Coastguard Worker /// Initialise profcollectd service.
58*288bf522SAndroid Build Coastguard Worker /// * `schedule_now` - Immediately schedule collection after service is initialised.
init_service(schedule_now: bool) -> Result<()>59*288bf522SAndroid Build Coastguard Worker pub fn init_service(schedule_now: bool) -> Result<()> {
60*288bf522SAndroid Build Coastguard Worker     binder::ProcessState::start_thread_pool();
61*288bf522SAndroid Build Coastguard Worker 
62*288bf522SAndroid Build Coastguard Worker     let profcollect_binder_service = ProfcollectdBinderService::new()?;
63*288bf522SAndroid Build Coastguard Worker     binder::add_service(
64*288bf522SAndroid Build Coastguard Worker         PROFCOLLECTD_SERVICE_NAME,
65*288bf522SAndroid Build Coastguard Worker         BnProfCollectd::new_binder(profcollect_binder_service, BinderFeatures::default())
66*288bf522SAndroid Build Coastguard Worker             .as_binder(),
67*288bf522SAndroid Build Coastguard Worker     )
68*288bf522SAndroid Build Coastguard Worker     .context("Failed to register service.")?;
69*288bf522SAndroid Build Coastguard Worker 
70*288bf522SAndroid Build Coastguard Worker     if schedule_now {
71*288bf522SAndroid Build Coastguard Worker         let cb = BnProviderStatusCallback::new_binder(
72*288bf522SAndroid Build Coastguard Worker             ProviderStatusCallback { service_start_time: Instant::now() },
73*288bf522SAndroid Build Coastguard Worker             BinderFeatures::default(),
74*288bf522SAndroid Build Coastguard Worker         );
75*288bf522SAndroid Build Coastguard Worker         get_profcollectd_service()?.registerProviderStatusCallback(&cb)?;
76*288bf522SAndroid Build Coastguard Worker     }
77*288bf522SAndroid Build Coastguard Worker 
78*288bf522SAndroid Build Coastguard Worker     binder::ProcessState::join_thread_pool();
79*288bf522SAndroid Build Coastguard Worker     Ok(())
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker 
get_profcollectd_service() -> Result<binder::Strong<dyn IProfCollectd::IProfCollectd>>82*288bf522SAndroid Build Coastguard Worker fn get_profcollectd_service() -> Result<binder::Strong<dyn IProfCollectd::IProfCollectd>> {
83*288bf522SAndroid Build Coastguard Worker     binder::wait_for_interface(PROFCOLLECTD_SERVICE_NAME)
84*288bf522SAndroid Build Coastguard Worker         .context("Failed to get profcollectd binder service, is profcollectd running?")
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker 
87*288bf522SAndroid Build Coastguard Worker /// Schedule periodic profile collection.
schedule() -> Result<()>88*288bf522SAndroid Build Coastguard Worker pub fn schedule() -> Result<()> {
89*288bf522SAndroid Build Coastguard Worker     get_profcollectd_service()?.schedule()?;
90*288bf522SAndroid Build Coastguard Worker     Ok(())
91*288bf522SAndroid Build Coastguard Worker }
92*288bf522SAndroid Build Coastguard Worker 
93*288bf522SAndroid Build Coastguard Worker /// Terminate periodic profile collection.
terminate() -> Result<()>94*288bf522SAndroid Build Coastguard Worker pub fn terminate() -> Result<()> {
95*288bf522SAndroid Build Coastguard Worker     get_profcollectd_service()?.terminate()?;
96*288bf522SAndroid Build Coastguard Worker     Ok(())
97*288bf522SAndroid Build Coastguard Worker }
98*288bf522SAndroid Build Coastguard Worker 
99*288bf522SAndroid Build Coastguard Worker /// Immediately schedule a one-off trace.
trace_system(tag: &str) -> Result<()>100*288bf522SAndroid Build Coastguard Worker pub fn trace_system(tag: &str) -> Result<()> {
101*288bf522SAndroid Build Coastguard Worker     get_profcollectd_service()?.trace_system(tag)?;
102*288bf522SAndroid Build Coastguard Worker     Ok(())
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker 
105*288bf522SAndroid Build Coastguard Worker /// Process traces.
process() -> Result<()>106*288bf522SAndroid Build Coastguard Worker pub fn process() -> Result<()> {
107*288bf522SAndroid Build Coastguard Worker     get_profcollectd_service()?.process()?;
108*288bf522SAndroid Build Coastguard Worker     Ok(())
109*288bf522SAndroid Build Coastguard Worker }
110*288bf522SAndroid Build Coastguard Worker 
111*288bf522SAndroid Build Coastguard Worker /// Process traces and report profile.
report() -> Result<String>112*288bf522SAndroid Build Coastguard Worker pub fn report() -> Result<String> {
113*288bf522SAndroid Build Coastguard Worker     Ok(get_profcollectd_service()?.report(report::NO_USAGE_SETTING)?)
114*288bf522SAndroid Build Coastguard Worker }
115*288bf522SAndroid Build Coastguard Worker 
116*288bf522SAndroid Build Coastguard Worker /// Clear all local data.
reset() -> Result<()>117*288bf522SAndroid Build Coastguard Worker pub fn reset() -> Result<()> {
118*288bf522SAndroid Build Coastguard Worker     config::clear_data()?;
119*288bf522SAndroid Build Coastguard Worker     Ok(())
120*288bf522SAndroid Build Coastguard Worker }
121*288bf522SAndroid Build Coastguard Worker 
122*288bf522SAndroid Build Coastguard Worker /// Inits logging for Android
init_logging()123*288bf522SAndroid Build Coastguard Worker pub fn init_logging() {
124*288bf522SAndroid Build Coastguard Worker     let max_log_level =
125*288bf522SAndroid Build Coastguard Worker         if cfg!(feature = "test") { log::LevelFilter::Info } else { log::LevelFilter::Error };
126*288bf522SAndroid Build Coastguard Worker     android_logger::init_once(
127*288bf522SAndroid Build Coastguard Worker         android_logger::Config::default()
128*288bf522SAndroid Build Coastguard Worker             .with_tag("profcollectd")
129*288bf522SAndroid Build Coastguard Worker             .with_max_level(max_log_level)
130*288bf522SAndroid Build Coastguard Worker             .with_log_buffer(android_logger::LogId::System),
131*288bf522SAndroid Build Coastguard Worker     );
132*288bf522SAndroid Build Coastguard Worker }
133