Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 1 | // |
| 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 Kong | 80f579d | 2020-11-09 20:40:01 +0800 | [diff] [blame] | 17 | //! ProfCollect Binder client interface. |
| 18 | |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 19 | mod config; |
| 20 | mod report; |
| 21 | mod scheduler; |
| 22 | mod service; |
| 23 | mod simpleperf_etm_trace_provider; |
Yabin Cui | ffc25f8 | 2023-12-13 11:04:40 -0800 | [diff] [blame] | 24 | mod simpleperf_lbr_trace_provider; |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 25 | mod trace_provider; |
| 26 | |
Yi Kong | 8c59b8f | 2021-06-18 16:28:54 -0700 | [diff] [blame] | 27 | #[cfg(feature = "test")] |
| 28 | mod logging_trace_provider; |
| 29 | |
Yi Kong | c6d5ff1 | 2021-03-10 02:20:45 +0800 | [diff] [blame] | 30 | use anyhow::{Context, Result}; |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 31 | use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::{ |
| 32 | self, BnProfCollectd, |
| 33 | }; |
Yabin Cui | f158a75 | 2022-01-10 15:35:59 -0800 | [diff] [blame] | 34 | use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProviderStatusCallback::{IProviderStatusCallback, BnProviderStatusCallback}; |
Andrew Walbran | 064c365 | 2021-04-14 13:53:09 +0000 | [diff] [blame] | 35 | use profcollectd_aidl_interface::binder::{self, BinderFeatures}; |
Yabin Cui | f158a75 | 2022-01-10 15:35:59 -0800 | [diff] [blame] | 36 | use service::{err_to_binder_status, ProfcollectdBinderService}; |
| 37 | use std::time::{Duration, Instant}; |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 38 | |
| 39 | const PROFCOLLECTD_SERVICE_NAME: &str = "profcollectd"; |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 40 | |
Yabin Cui | f158a75 | 2022-01-10 15:35:59 -0800 | [diff] [blame] | 41 | struct ProviderStatusCallback { |
| 42 | service_start_time: Instant, |
| 43 | } |
| 44 | |
| 45 | impl binder::Interface for ProviderStatusCallback {} |
| 46 | |
| 47 | impl IProviderStatusCallback for ProviderStatusCallback { |
| 48 | fn onProviderReady(&self) -> binder::Result<()> { |
| 49 | // If we have waited too long for the provider to be ready, then we have passed |
| 50 | // boot phase, and no need to collect boot profile. |
| 51 | // TODO: should we check boottime instead? |
| 52 | const TIMEOUT_TO_COLLECT_BOOT_PROFILE: Duration = Duration::from_secs(3); |
| 53 | let elapsed = Instant::now().duration_since(self.service_start_time); |
| 54 | if elapsed < TIMEOUT_TO_COLLECT_BOOT_PROFILE { |
Yi Kong | c26c15b | 2024-07-06 17:20:44 +0900 | [diff] [blame] | 55 | trace_system("boot").map_err(err_to_binder_status)?; |
Yabin Cui | f158a75 | 2022-01-10 15:35:59 -0800 | [diff] [blame] | 56 | } |
| 57 | schedule().map_err(err_to_binder_status)?; |
| 58 | Ok(()) |
| 59 | } |
| 60 | } |
| 61 | |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 62 | /// Initialise profcollectd service. |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 63 | /// * `schedule_now` - Immediately schedule collection after service is initialised. |
| 64 | pub fn init_service(schedule_now: bool) -> Result<()> { |
| 65 | binder::ProcessState::start_thread_pool(); |
| 66 | |
| 67 | let profcollect_binder_service = ProfcollectdBinderService::new()?; |
| 68 | binder::add_service( |
Chris Wailes | 8f571e1 | 2021-07-27 16:04:09 -0700 | [diff] [blame] | 69 | PROFCOLLECTD_SERVICE_NAME, |
Andrew Walbran | 064c365 | 2021-04-14 13:53:09 +0000 | [diff] [blame] | 70 | BnProfCollectd::new_binder(profcollect_binder_service, BinderFeatures::default()) |
| 71 | .as_binder(), |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 72 | ) |
| 73 | .context("Failed to register service.")?; |
| 74 | |
| 75 | if schedule_now { |
Yabin Cui | f158a75 | 2022-01-10 15:35:59 -0800 | [diff] [blame] | 76 | let cb = BnProviderStatusCallback::new_binder( |
| 77 | ProviderStatusCallback { service_start_time: Instant::now() }, |
| 78 | BinderFeatures::default(), |
| 79 | ); |
| 80 | get_profcollectd_service()?.registerProviderStatusCallback(&cb)?; |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 81 | } |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 82 | |
| 83 | binder::ProcessState::join_thread_pool(); |
| 84 | Ok(()) |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 85 | } |
| 86 | |
Yi Kong | 74071ea | 2021-04-10 16:28:30 +0800 | [diff] [blame] | 87 | fn get_profcollectd_service() -> Result<binder::Strong<dyn IProfCollectd::IProfCollectd>> { |
Frederick Mayle | 6b7ad7e | 2024-05-08 13:43:26 -0700 | [diff] [blame] | 88 | binder::wait_for_interface(PROFCOLLECTD_SERVICE_NAME) |
Yi Kong | 74071ea | 2021-04-10 16:28:30 +0800 | [diff] [blame] | 89 | .context("Failed to get profcollectd binder service, is profcollectd running?") |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 90 | } |
| 91 | |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 92 | /// Schedule periodic profile collection. |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 93 | pub fn schedule() -> Result<()> { |
Yi Kong | 74071ea | 2021-04-10 16:28:30 +0800 | [diff] [blame] | 94 | get_profcollectd_service()?.schedule()?; |
Yi Kong | c6d5ff1 | 2021-03-10 02:20:45 +0800 | [diff] [blame] | 95 | Ok(()) |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | /// Terminate periodic profile collection. |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 99 | pub fn terminate() -> Result<()> { |
Yi Kong | 74071ea | 2021-04-10 16:28:30 +0800 | [diff] [blame] | 100 | get_profcollectd_service()?.terminate()?; |
Yi Kong | c6d5ff1 | 2021-03-10 02:20:45 +0800 | [diff] [blame] | 101 | Ok(()) |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | /// Immediately schedule a one-off trace. |
Yi Kong | c26c15b | 2024-07-06 17:20:44 +0900 | [diff] [blame] | 105 | pub fn trace_system(tag: &str) -> Result<()> { |
| 106 | get_profcollectd_service()?.trace_system(tag)?; |
Yi Kong | c6d5ff1 | 2021-03-10 02:20:45 +0800 | [diff] [blame] | 107 | Ok(()) |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 108 | } |
| 109 | |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 110 | /// Process traces. |
| 111 | pub fn process() -> Result<()> { |
Yi Kong | e762742 | 2021-11-15 16:20:02 +0800 | [diff] [blame] | 112 | get_profcollectd_service()?.process()?; |
Yi Kong | c6d5ff1 | 2021-03-10 02:20:45 +0800 | [diff] [blame] | 113 | Ok(()) |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 114 | } |
| 115 | |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 116 | /// Process traces and report profile. |
Yi Kong | 037bde8 | 2021-03-23 14:25:38 +0800 | [diff] [blame] | 117 | pub fn report() -> Result<String> { |
Yabin Cui | 1c3d80e | 2023-05-12 20:47:27 +0000 | [diff] [blame] | 118 | Ok(get_profcollectd_service()?.report(report::NO_USAGE_SETTING)?) |
Yi Kong | 4e25de7 | 2020-09-08 14:43:33 +0800 | [diff] [blame] | 119 | } |
| 120 | |
Yi Kong | 34ebf87 | 2021-11-29 19:57:55 +0800 | [diff] [blame] | 121 | /// Clear all local data. |
| 122 | pub fn reset() -> Result<()> { |
| 123 | config::clear_data()?; |
| 124 | Ok(()) |
| 125 | } |
| 126 | |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 127 | /// Inits logging for Android |
| 128 | pub fn init_logging() { |
Jeff Vander Stoep | 743b98e | 2024-01-29 19:39:15 +0100 | [diff] [blame] | 129 | let max_log_level = |
| 130 | if cfg!(feature = "test") { log::LevelFilter::Info } else { log::LevelFilter::Error }; |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 131 | android_logger::init_once( |
Yi Kong | d1cca10 | 2022-02-23 21:26:09 +0800 | [diff] [blame] | 132 | android_logger::Config::default() |
| 133 | .with_tag("profcollectd") |
Jeff Vander Stoep | 743b98e | 2024-01-29 19:39:15 +0100 | [diff] [blame] | 134 | .with_max_level(max_log_level) |
| 135 | .with_log_buffer(android_logger::LogId::System), |
Yi Kong | e3aab14 | 2021-03-02 13:58:25 +0800 | [diff] [blame] | 136 | ); |
Yi Kong | e5576ae | 2020-08-05 02:00:05 +0800 | [diff] [blame] | 137 | } |