blob: c0e12e32424c93cf21a8828571a9091e65e95f42 [file] [log] [blame]
Yi Konge5576ae2020-08-05 02:00:05 +08001//
2// Copyright (C) 2020 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Yi Kong80f579d2020-11-09 20:40:01 +080017//! ProfCollect Binder client interface.
18
Yi Konge3aab142021-03-02 13:58:25 +080019mod config;
20mod report;
21mod scheduler;
22mod service;
23mod simpleperf_etm_trace_provider;
24mod trace_provider;
25
Yi Kong8c59b8f2021-06-18 16:28:54 -070026#[cfg(feature = "test")]
27mod logging_trace_provider;
28
Yi Kongc6d5ff12021-03-10 02:20:45 +080029use anyhow::{Context, Result};
Yi Konge3aab142021-03-02 13:58:25 +080030use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::{
31 self, BnProfCollectd,
32};
Yabin Cuif158a752022-01-10 15:35:59 -080033use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProviderStatusCallback::{IProviderStatusCallback, BnProviderStatusCallback};
Andrew Walbran064c3652021-04-14 13:53:09 +000034use profcollectd_aidl_interface::binder::{self, BinderFeatures};
Yabin Cuif158a752022-01-10 15:35:59 -080035use service::{err_to_binder_status, ProfcollectdBinderService};
36use std::time::{Duration, Instant};
Yi Konge3aab142021-03-02 13:58:25 +080037
38const PROFCOLLECTD_SERVICE_NAME: &str = "profcollectd";
Yi Konge5576ae2020-08-05 02:00:05 +080039
Yabin Cuif158a752022-01-10 15:35:59 -080040struct ProviderStatusCallback {
41 service_start_time: Instant,
42}
43
44impl binder::Interface for ProviderStatusCallback {}
45
46impl IProviderStatusCallback for ProviderStatusCallback {
47 fn onProviderReady(&self) -> binder::Result<()> {
48 // If we have waited too long for the provider to be ready, then we have passed
49 // boot phase, and no need to collect boot profile.
50 // TODO: should we check boottime instead?
51 const TIMEOUT_TO_COLLECT_BOOT_PROFILE: Duration = Duration::from_secs(3);
52 let elapsed = Instant::now().duration_since(self.service_start_time);
53 if elapsed < TIMEOUT_TO_COLLECT_BOOT_PROFILE {
54 trace_once("boot").map_err(err_to_binder_status)?;
55 }
56 schedule().map_err(err_to_binder_status)?;
57 Ok(())
58 }
59}
60
Yi Konge5576ae2020-08-05 02:00:05 +080061/// Initialise profcollectd service.
Yi Konge3aab142021-03-02 13:58:25 +080062/// * `schedule_now` - Immediately schedule collection after service is initialised.
63pub fn init_service(schedule_now: bool) -> Result<()> {
64 binder::ProcessState::start_thread_pool();
65
66 let profcollect_binder_service = ProfcollectdBinderService::new()?;
67 binder::add_service(
Chris Wailes8f571e12021-07-27 16:04:09 -070068 PROFCOLLECTD_SERVICE_NAME,
Andrew Walbran064c3652021-04-14 13:53:09 +000069 BnProfCollectd::new_binder(profcollect_binder_service, BinderFeatures::default())
70 .as_binder(),
Yi Konge3aab142021-03-02 13:58:25 +080071 )
72 .context("Failed to register service.")?;
73
74 if schedule_now {
Yabin Cuif158a752022-01-10 15:35:59 -080075 let cb = BnProviderStatusCallback::new_binder(
76 ProviderStatusCallback { service_start_time: Instant::now() },
77 BinderFeatures::default(),
78 );
79 get_profcollectd_service()?.registerProviderStatusCallback(&cb)?;
Yi Konge5576ae2020-08-05 02:00:05 +080080 }
Yi Konge3aab142021-03-02 13:58:25 +080081
82 binder::ProcessState::join_thread_pool();
83 Ok(())
Yi Konge5576ae2020-08-05 02:00:05 +080084}
85
Yi Kong74071ea2021-04-10 16:28:30 +080086fn get_profcollectd_service() -> Result<binder::Strong<dyn IProfCollectd::IProfCollectd>> {
Chris Wailes8f571e12021-07-27 16:04:09 -070087 binder::get_interface(PROFCOLLECTD_SERVICE_NAME)
Yi Kong74071ea2021-04-10 16:28:30 +080088 .context("Failed to get profcollectd binder service, is profcollectd running?")
Yi Konge3aab142021-03-02 13:58:25 +080089}
90
Yi Konge5576ae2020-08-05 02:00:05 +080091/// Schedule periodic profile collection.
Yi Konge3aab142021-03-02 13:58:25 +080092pub fn schedule() -> Result<()> {
Yi Kong74071ea2021-04-10 16:28:30 +080093 get_profcollectd_service()?.schedule()?;
Yi Kongc6d5ff12021-03-10 02:20:45 +080094 Ok(())
Yi Konge5576ae2020-08-05 02:00:05 +080095}
96
97/// Terminate periodic profile collection.
Yi Konge3aab142021-03-02 13:58:25 +080098pub fn terminate() -> Result<()> {
Yi Kong74071ea2021-04-10 16:28:30 +080099 get_profcollectd_service()?.terminate()?;
Yi Kongc6d5ff12021-03-10 02:20:45 +0800100 Ok(())
Yi Konge5576ae2020-08-05 02:00:05 +0800101}
102
103/// Immediately schedule a one-off trace.
Yi Konge3aab142021-03-02 13:58:25 +0800104pub fn trace_once(tag: &str) -> Result<()> {
Yi Kong74071ea2021-04-10 16:28:30 +0800105 get_profcollectd_service()?.trace_once(tag)?;
Yi Kongc6d5ff12021-03-10 02:20:45 +0800106 Ok(())
Yi Konge5576ae2020-08-05 02:00:05 +0800107}
108
Yi Konge3aab142021-03-02 13:58:25 +0800109/// Process traces.
110pub fn process() -> Result<()> {
Yi Konge7627422021-11-15 16:20:02 +0800111 get_profcollectd_service()?.process()?;
Yi Kongc6d5ff12021-03-10 02:20:45 +0800112 Ok(())
Yi Konge5576ae2020-08-05 02:00:05 +0800113}
114
Yi Konge3aab142021-03-02 13:58:25 +0800115/// Process traces and report profile.
Yi Kong037bde82021-03-23 14:25:38 +0800116pub fn report() -> Result<String> {
Yabin Cui1a2601f2023-05-11 14:28:57 -0700117 Ok(get_profcollectd_service()?.report(report::NO_USAGE_SETTING)?)
Yi Kong4e25de72020-09-08 14:43:33 +0800118}
119
Yi Kong34ebf872021-11-29 19:57:55 +0800120/// Clear all local data.
121pub fn reset() -> Result<()> {
122 config::clear_data()?;
123 Ok(())
124}
125
Yi Konge3aab142021-03-02 13:58:25 +0800126/// Inits logging for Android
127pub fn init_logging() {
Yi Kong8c59b8f2021-06-18 16:28:54 -0700128 let min_log_level = if cfg!(feature = "test") { log::Level::Info } else { log::Level::Error };
Yi Konge3aab142021-03-02 13:58:25 +0800129 android_logger::init_once(
Yi Kongd1cca102022-02-23 21:26:09 +0800130 android_logger::Config::default()
131 .with_tag("profcollectd")
132 .with_min_level(min_log_level)
133 .with_log_id(android_logger::LogId::System),
Yi Konge3aab142021-03-02 13:58:25 +0800134 );
Yi Konge5576ae2020-08-05 02:00:05 +0800135}