diff options
-rwxr-xr-x | boottime_tools/bootanalyze/bootanalyze.py | 132 | ||||
-rw-r--r-- | boottime_tools/bootanalyze/config.yaml | 2 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/Android.bp | 3 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/config.rs | 25 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/lib.rs | 14 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/logging_trace_provider.rs | 56 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/scheduler.rs | 36 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/service.rs | 13 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/simpleperf_etm_trace_provider.rs | 6 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/trace_provider.rs | 19 | ||||
-rw-r--r-- | profcollectd/profcollectctl.rs | 7 | ||||
-rw-r--r-- | profcollectd/profcollectd.rc | 18 | ||||
-rw-r--r-- | simpleperf/test_util.cpp | 1 |
13 files changed, 253 insertions, 79 deletions
diff --git a/boottime_tools/bootanalyze/bootanalyze.py b/boottime_tools/bootanalyze/bootanalyze.py index 7eea05b9..5bed9f29 100755 --- a/boottime_tools/bootanalyze/bootanalyze.py +++ b/boottime_tools/bootanalyze/bootanalyze.py @@ -35,7 +35,6 @@ import yaml from datetime import datetime, date - TIME_DMESG = r"\[\s*(\d+\.\d+)\]" TIME_LOGCAT = r"[0-9]+\.?[0-9]*" KERNEL_TIME_KEY = "kernel" @@ -46,6 +45,7 @@ LAUNCHER_START = "LauncherStart" BOOT_TIME_TOO_BIG = 200.0 MAX_RETRIES = 5 DEBUG = False +DEBUG_PATTERN = False ADB_CMD = "adb" TIMING_THRESHOLD = 5.0 BOOT_PROP = r"\[ro\.boottime\.([^\]]+)\]:\s+\[(\d+)\]" @@ -99,6 +99,8 @@ def main(): for key, pattern in cfg['timings'].items()} shutdown_events_pattern = {key: re.compile(pattern) for key, pattern in cfg['shutdown_events'].items()} + if DEBUG_PATTERN: + print("search event:{} timing event:{}".format(search_events_pattern, timing_events_pattern)) data_points = {} kernel_timing_points = collections.OrderedDict() @@ -301,6 +303,13 @@ def handle_reboot_log(capture_log_on_error, shutdown_events_pattern, components_ print('{0:30}: {1:<7.5}'.format(item[0], item[1])) return shutdown_events, shutdown_timing_events +def collect_dmesg_events(search_events_pattern, timings_pattern, results): + dmesg_events, kernel_timing_events = collect_events(search_events_pattern, ADB_CMD +\ + ' shell su root dmesg -w', timings_pattern,\ + [KERNEL_BOOT_COMPLETE], True) + results.append(dmesg_events) + results.append(kernel_timing_events) + def iterate(args, search_events_pattern, timings_pattern, shutdown_events_pattern, cfg, error_time,\ components_to_monitor): shutdown_events = None @@ -315,16 +324,22 @@ def iterate(args, search_events_pattern, timings_pattern, shutdown_events_patter components_to_monitor) t.join() - dmesg_events, kernel_timing_events = collect_events(search_events_pattern, ADB_CMD +\ - ' shell su root dmesg -w', timings_pattern,\ - [KERNEL_BOOT_COMPLETE], True) + results = [] + t = threading.Thread(target=collect_dmesg_events, args=(search_events_pattern,\ + timings_pattern, results)) + t.start() - logcat_stop_events = [LOGCAT_BOOT_COMPLETE, KERNEL_BOOT_COMPLETE, LAUNCHER_START] + logcat_stop_events = [LOGCAT_BOOT_COMPLETE, LAUNCHER_START] if args.fs_check: logcat_stop_events.append("FsStat") logcat_events, logcat_timing_events = collect_events( search_events_pattern, ADB_CMD + ' logcat -b all -v epoch', timings_pattern,\ logcat_stop_events, False) + + t.join() + dmesg_events = results[0] + kernel_timing_events = results[1] + logcat_event_time = extract_time(logcat_events, TIME_LOGCAT, float) logcat_original_time = extract_time(logcat_events, TIME_LOGCAT, str); dmesg_event_time = extract_time(dmesg_events, TIME_DMESG, float); @@ -352,11 +367,12 @@ def iterate(args, search_events_pattern, timings_pattern, shutdown_events_patter v = v + time_correction_delta debug("correcting event to event[{0}, {1}]".format(k, v)) - if logcat_event_time.get(KERNEL_TIME_KEY) is None: - print("kernel time not captured in logcat, cannot get time diff") - return None, None, None, None, None, None diffs = [] - diffs.append((logcat_event_time[KERNEL_TIME_KEY], logcat_event_time[KERNEL_TIME_KEY])) + if logcat_event_time.get(KERNEL_TIME_KEY) is None: + print("kernel time not captured in logcat") + else: + diffs.append((logcat_event_time[KERNEL_TIME_KEY], logcat_event_time[KERNEL_TIME_KEY])) + if logcat_event_time.get(BOOT_ANIM_END_TIME_KEY) and dmesg_event_time.get(BOOT_ANIM_END_TIME_KEY): diffs.append((logcat_event_time[BOOT_ANIM_END_TIME_KEY],\ logcat_event_time[BOOT_ANIM_END_TIME_KEY] -\ @@ -364,6 +380,7 @@ def iterate(args, search_events_pattern, timings_pattern, shutdown_events_patter if not dmesg_event_time.get(KERNEL_BOOT_COMPLETE): print("BootAnimEnd time or BootComplete-kernel not captured in both log" +\ ", cannot get time diff") + print("dmesg {} logcat {}".format(dmesg_event_time, logcat_event_time)) return None, None, None, None, None, None diffs.append((logcat_event_time[LOGCAT_BOOT_COMPLETE],\ logcat_event_time[LOGCAT_BOOT_COMPLETE] - dmesg_event_time[KERNEL_BOOT_COMPLETE])) @@ -631,56 +648,79 @@ def collect_logcat_for_shutdown(capture_log_on_error, shutdown_events_pattern,\ f.write('\n'.join(lines)) return events, timing_events +def log_timeout(time_left, stop_events, events, timing_events): + print("timeout waiting for event, continue", time_left) + print(" remaininig events {}, event {} timing events {}".\ + format(stop_events, events, timing_events)) def collect_events(search_events, command, timings, stop_events, disable_timing_after_zygote): events = collections.OrderedDict() timing_events = {} - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + data_available = stop_events is None zygote_pids = [] start_time = time.time() zygote_found = False - line = None - read_poll = select.poll() - read_poll.register(process.stdout, select.POLLIN) + print("remaining stop_events:", stop_events) + init = True while True: + if init: + process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + read_poll = select.poll() + read_poll.register(process.stdout, select.POLLIN) + init = False + if len(stop_events) == 0: + break time_left = start_time + max_wait_time - time.time() if time_left <= 0: - print("timeout waiting for event, continue", time_left) + log_timeout(time_left, stop_events, events, timing_events) break - read_r = read_poll.poll(time_left * 1000.0) - if len(read_r) > 0 and read_r[0][1] == select.POLLIN: - line = process.stdout.readline().decode('utf-8', 'ignore') - else: - print("poll timeout waiting for event, continue", time_left) + polled_events = read_poll.poll(time_left * 1000.0) + if len(polled_events) == 0: + log_timeout(time_left, stop_events, events, timing_events) break - if not data_available: - print("Collecting data samples from '%s'. Please wait...\n" % command) - data_available = True - event = get_boot_event(line, search_events) - if event: - debug("event[{0}] captured: {1}".format(event, line)) - if event == "starting_zygote": - events[event] = line - zygote_found = True - elif event.startswith("zygote"): - handle_zygote_event(zygote_pids, events, event, line) + for polled_event in polled_events: + if polled_event[1] == select.POLLIN: + line = process.stdout.readline().decode('utf-8', 'ignore') else: - new_event = update_name_if_already_exist(events, event) - events[new_event] = line - if event in stop_events: - stop_events.remove(event) - print("remaining stop_events:", stop_events) - if len(stop_events) == 0: + if polled_event[1] == select.POLLHUP: + if len(stop_events) == 0: + break; + # adb connection lost + print("poll error waiting for event, adb lost?") + if time_left > 0: + print("retry adb") + run_adb_cmd('wait-for-device') + print(" reconnected") + init = True + continue + else: break - - timing_event = get_boot_event(line, timings) - if timing_event and (not disable_timing_after_zygote or not zygote_found): - if timing_event not in timing_events: - timing_events[timing_event] = [] - timing_events[timing_event].append(line) - debug("timing_event[{0}] captured: {1}".format(timing_event, line)) + if not data_available: + print("Collecting data samples from '%s'. Please wait...\n" % command) + data_available = True + event = get_boot_event(line, search_events) + if event: + debug("event[{0}] captured: {1}".format(event, line)) + if event == "starting_zygote": + events[event] = line + zygote_found = True + elif event.startswith("zygote"): + handle_zygote_event(zygote_pids, events, event, line) + else: + new_event = update_name_if_already_exist(events, event) + events[new_event] = line + if event in stop_events: + stop_events.remove(event) + print("remaining stop_events:", stop_events) + + timing_event = get_boot_event(line, timings) + if timing_event and (not disable_timing_after_zygote or not zygote_found): + if timing_event not in timing_events: + timing_events[timing_event] = [] + timing_events[timing_event].append(line) + debug("timing_event[{0}] captured: {1}".format(timing_event, line)) process.terminate() return events, timing_events @@ -743,7 +783,10 @@ def extract_time(events, pattern, date_transform_function): def do_reboot(serial, use_adb_reboot): - original_devices = subprocess.check_output("adb devices", shell=True) + # do not update time + run_adb_cmd('shell settings put global auto_time 0') + run_adb_cmd('shell settings put global auto_time_zone 0') + original_devices = subprocess.check_output("adb devices", shell=True).decode('utf-8', 'ignore') if use_adb_reboot: print('Rebooting the device using adb reboot') run_adb_cmd('reboot') @@ -780,6 +823,7 @@ def reboot(serial, use_stressfs, permissive, use_adb_reboot, adb_buffersize=None print('Waiting the device') run_adb_cmd('wait-for-device') + print(' found a device') if adb_buffersize is not None: # increase the buffer size diff --git a/boottime_tools/bootanalyze/config.yaml b/boottime_tools/bootanalyze/config.yaml index d6590fdb..83c1bcd8 100644 --- a/boottime_tools/bootanalyze/config.yaml +++ b/boottime_tools/bootanalyze/config.yaml @@ -61,7 +61,7 @@ events: KeyguardShown: KeyguardServiceDelegate.*\*\*\*\* SHOWN CALLED \*\*\*\* BootComplete: Starting phase 1000 BootComplete_kernel: processing action \(sys\.boot_completed=1\) - LauncherStart: START.*HOME.*(NexusLauncherActivity|GEL|LensPickerTrampolineActivity|SetupWizard|CarLauncher) + LauncherStart: START.*HOME.*(NexusLauncherActivity|GEL|LensPickerTrampolineActivity|SetupWizard|CarLauncher|launcher.*Launcher) FsStat: fs_stat, partition:userdata stat:(0x\S+) shutdown_events: ShutdownStart: ShutdownThread:\sNotifying thread to start shutdown diff --git a/profcollectd/libprofcollectd/Android.bp b/profcollectd/libprofcollectd/Android.bp index 2e37af9e..7fb1b567 100644 --- a/profcollectd/libprofcollectd/Android.bp +++ b/profcollectd/libprofcollectd/Android.bp @@ -60,4 +60,7 @@ rust_library { "libsimpleperf_profcollect_rust", ], shared_libs: ["libsimpleperf_profcollect"], + + // Enable 'test' feature for more verbose logging and the logging trace provider. + // features: ["test"], } diff --git a/profcollectd/libprofcollectd/config.rs b/profcollectd/libprofcollectd/config.rs index e8afb37f..902b5b5e 100644 --- a/profcollectd/libprofcollectd/config.rs +++ b/profcollectd/libprofcollectd/config.rs @@ -22,6 +22,7 @@ use macaddr::MacAddr6; use rand::Rng; use serde::{Deserialize, Serialize}; use std::error::Error; +use std::fs::{read_dir, remove_file}; use std::path::Path; use std::str::FromStr; use std::time::Duration; @@ -31,6 +32,7 @@ const PROFCOLLECT_NODE_ID_PROPERTY: &str = "persist.profcollectd.node_id"; pub const REPORT_RETENTION_SECS: u64 = 14 * 24 * 60 * 60; // 14 days. +// Static configs that cannot be changed. lazy_static! { pub static ref TRACE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/trace/"); pub static ref PROFILE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/output/"); @@ -42,6 +44,7 @@ lazy_static! { Path::new("/data/misc/profcollectd/output/config.json"); } +/// Dynamic configs, stored in config.json. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct Config { /// Version of config file scheme, always equals to 1. @@ -56,6 +59,8 @@ pub struct Config { pub sampling_period: Duration, /// An optional filter to limit which binaries to or not to profile. pub binary_filter: String, + /// Maximum size of the trace directory. + pub max_trace_limit: u64, } impl Config { @@ -70,6 +75,10 @@ impl Config { )?), sampling_period: Duration::from_millis(get_device_config("sampling_period", 500)?), binary_filter: get_device_config("binary_filter", "".to_string())?, + max_trace_limit: get_device_config( + "max_trace_limit", + /* 512MB */ 512 * 1024 * 1024, + )?, }) } } @@ -138,3 +147,19 @@ fn generate_random_node_id() -> MacAddr6 { node_id[0] |= 0x1; MacAddr6::from(node_id) } + +pub fn clear_data() -> Result<()> { + fn remove_files(path: &Path) -> Result<()> { + read_dir(path)? + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .filter(|e| e.is_file()) + .try_for_each(remove_file)?; + Ok(()) + } + + remove_files(&TRACE_OUTPUT_DIR)?; + remove_files(&PROFILE_OUTPUT_DIR)?; + remove_files(&REPORT_OUTPUT_DIR)?; + Ok(()) +} diff --git a/profcollectd/libprofcollectd/lib.rs b/profcollectd/libprofcollectd/lib.rs index aacbf8e3..5892e259 100644 --- a/profcollectd/libprofcollectd/lib.rs +++ b/profcollectd/libprofcollectd/lib.rs @@ -23,6 +23,9 @@ mod service; mod simpleperf_etm_trace_provider; mod trace_provider; +#[cfg(feature = "test")] +mod logging_trace_provider; + use anyhow::{Context, Result}; use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::{ self, BnProfCollectd, @@ -88,11 +91,16 @@ pub fn report() -> Result<String> { Ok(get_profcollectd_service()?.report()?) } +/// Clear all local data. +pub fn reset() -> Result<()> { + config::clear_data()?; + Ok(()) +} + /// Inits logging for Android pub fn init_logging() { + let min_log_level = if cfg!(feature = "test") { log::Level::Info } else { log::Level::Error }; android_logger::init_once( - android_logger::Config::default() - .with_tag("profcollectd") - .with_min_level(log::Level::Error), + android_logger::Config::default().with_tag("profcollectd").with_min_level(min_log_level), ); } diff --git a/profcollectd/libprofcollectd/logging_trace_provider.rs b/profcollectd/libprofcollectd/logging_trace_provider.rs new file mode 100644 index 00000000..1325855d --- /dev/null +++ b/profcollectd/libprofcollectd/logging_trace_provider.rs @@ -0,0 +1,56 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +//! Logging trace provider for development and testing purposes. + +use anyhow::Result; +use std::path::Path; +use std::time::Duration; +use trace_provider::TraceProvider; + +use crate::trace_provider; + +static LOGGING_TRACEFILE_EXTENSION: &str = "loggingtrace"; + +pub struct LoggingTraceProvider {} + +impl TraceProvider for LoggingTraceProvider { + fn get_name(&self) -> &'static str { + "logging" + } + + fn trace(&self, trace_dir: &Path, tag: &str, sampling_period: &Duration) { + let trace_file = trace_provider::get_path(trace_dir, tag, LOGGING_TRACEFILE_EXTENSION); + + log::info!( + "Trace event triggered, tag {}, sampling for {}ms, saving to {}", + tag, + sampling_period.as_millis(), + trace_file.display() + ); + } + + fn process(&self, _trace_dir: &Path, _profile_dir: &Path) -> Result<()> { + log::info!("Process event triggered"); + Ok(()) + } +} + +impl LoggingTraceProvider { + pub fn supported() -> bool { + true + } +} diff --git a/profcollectd/libprofcollectd/scheduler.rs b/profcollectd/libprofcollectd/scheduler.rs index cfd0381f..b83bc457 100644 --- a/profcollectd/libprofcollectd/scheduler.rs +++ b/profcollectd/libprofcollectd/scheduler.rs @@ -16,6 +16,8 @@ //! ProfCollect tracing scheduler. +use std::fs; +use std::path::Path; use std::sync::mpsc::{sync_channel, SyncSender}; use std::sync::Arc; use std::sync::Mutex; @@ -59,11 +61,13 @@ impl Scheduler { Ok(_) => break, Err(_) => { // Did not receive a termination signal, initiate trace event. - trace_provider.lock().unwrap().trace( - &TRACE_OUTPUT_DIR, - "periodic", - &config.sampling_period, - ); + if check_space_limit(*TRACE_OUTPUT_DIR, &config).unwrap() { + trace_provider.lock().unwrap().trace( + &TRACE_OUTPUT_DIR, + "periodic", + &config.sampling_period, + ); + } } } } @@ -83,7 +87,9 @@ impl Scheduler { pub fn one_shot(&self, config: &Config, tag: &str) -> Result<()> { let trace_provider = self.trace_provider.clone(); - trace_provider.lock().unwrap().trace(&TRACE_OUTPUT_DIR, tag, &config.sampling_period); + if check_space_limit(*TRACE_OUTPUT_DIR, config)? { + trace_provider.lock().unwrap().trace(&TRACE_OUTPUT_DIR, tag, &config.sampling_period); + } Ok(()) } @@ -106,3 +112,21 @@ impl Scheduler { self.trace_provider.lock().unwrap().get_name() } } + +/// Run if space usage is under limit. +fn check_space_limit(path: &Path, config: &Config) -> Result<bool> { + let ret = dir_size(path)? <= config.max_trace_limit; + if !ret { + log::error!("trace storage exhausted."); + } + Ok(ret) +} + +/// Returns the size of a directory, non-recursive. +fn dir_size(path: &Path) -> Result<u64> { + fs::read_dir(path)?.try_fold(0, |acc, file| { + let metadata = file?.metadata()?; + let size = if metadata.is_file() { metadata.len() } else { 0 }; + Ok(acc + size) + }) +} diff --git a/profcollectd/libprofcollectd/service.rs b/profcollectd/libprofcollectd/service.rs index 04f30f89..a7fdce73 100644 --- a/profcollectd/libprofcollectd/service.rs +++ b/profcollectd/libprofcollectd/service.rs @@ -21,15 +21,15 @@ use binder::public_api::Result as BinderResult; use binder::Status; use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::IProfCollectd; use std::ffi::CString; -use std::fs::{copy, create_dir, read_dir, read_to_string, remove_dir_all, remove_file, write}; +use std::fs::{copy, read_dir, read_to_string, remove_file, write}; use std::path::PathBuf; use std::str::FromStr; use std::sync::{Mutex, MutexGuard}; use std::time::Duration; use crate::config::{ - Config, BETTERBUG_CACHE_DIR_PREFIX, BETTERBUG_CACHE_DIR_SUFFIX, CONFIG_FILE, - PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, REPORT_RETENTION_SECS, TRACE_OUTPUT_DIR, + clear_data, Config, BETTERBUG_CACHE_DIR_PREFIX, BETTERBUG_CACHE_DIR_SUFFIX, CONFIG_FILE, + PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, REPORT_RETENTION_SECS, }; use crate::report::{get_report_ts, pack_report}; use crate::scheduler::Scheduler; @@ -147,11 +147,8 @@ impl ProfcollectdBinderService { .is_none(); if config_changed { - log::info!("Config change detected, clearing traces."); - remove_dir_all(*PROFILE_OUTPUT_DIR)?; - remove_dir_all(*TRACE_OUTPUT_DIR)?; - create_dir(*PROFILE_OUTPUT_DIR)?; - create_dir(*TRACE_OUTPUT_DIR)?; + log::info!("Config change detected, resetting profcollect."); + clear_data()?; write(*CONFIG_FILE, &new_config.to_string())?; } diff --git a/profcollectd/libprofcollectd/simpleperf_etm_trace_provider.rs b/profcollectd/libprofcollectd/simpleperf_etm_trace_provider.rs index 2038a5be..d3baaa36 100644 --- a/profcollectd/libprofcollectd/simpleperf_etm_trace_provider.rs +++ b/profcollectd/libprofcollectd/simpleperf_etm_trace_provider.rs @@ -35,12 +35,10 @@ impl TraceProvider for SimpleperfEtmTraceProvider { } fn trace(&self, trace_dir: &Path, tag: &str, sampling_period: &Duration) { - let mut trace_file = PathBuf::from(trace_dir); - trace_file.push(trace_provider::construct_file_name(tag)); - trace_file.set_extension(ETM_TRACEFILE_EXTENSION); + let trace_file = trace_provider::get_path(trace_dir, tag, ETM_TRACEFILE_EXTENSION); simpleperf_profcollect::record( - &trace_file, + &*trace_file, sampling_period, simpleperf_profcollect::RecordScope::BOTH, ); diff --git a/profcollectd/libprofcollectd/trace_provider.rs b/profcollectd/libprofcollectd/trace_provider.rs index ed0d56f5..44d4cee9 100644 --- a/profcollectd/libprofcollectd/trace_provider.rs +++ b/profcollectd/libprofcollectd/trace_provider.rs @@ -18,12 +18,15 @@ use anyhow::{anyhow, Result}; use chrono::Utc; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::time::Duration; use crate::simpleperf_etm_trace_provider::SimpleperfEtmTraceProvider; +#[cfg(feature = "test")] +use crate::logging_trace_provider::LoggingTraceProvider; + pub trait TraceProvider { fn get_name(&self) -> &'static str; fn trace(&self, trace_dir: &Path, tag: &str, sampling_period: &Duration); @@ -36,9 +39,19 @@ pub fn get_trace_provider() -> Result<Arc<Mutex<dyn TraceProvider + Send>>> { return Ok(Arc::new(Mutex::new(SimpleperfEtmTraceProvider {}))); } + #[cfg(feature = "test")] + if LoggingTraceProvider::supported() { + log::info!("logging trace provider registered."); + return Ok(Arc::new(Mutex::new(LoggingTraceProvider {}))); + } + Err(anyhow!("No trace provider found for this device.")) } -pub fn construct_file_name(tag: &str) -> String { - format!("{}_{}", Utc::now().format("%Y%m%d-%H%M%S"), tag) +pub fn get_path(dir: &Path, tag: &str, ext: &str) -> Box<Path> { + let filename = format!("{}_{}", Utc::now().format("%Y%m%d-%H%M%S"), tag); + let mut trace_file = PathBuf::from(dir); + trace_file.push(filename); + trace_file.set_extension(ext); + trace_file.into_boxed_path() } diff --git a/profcollectd/profcollectctl.rs b/profcollectd/profcollectctl.rs index c825f550..6778465e 100644 --- a/profcollectd/profcollectctl.rs +++ b/profcollectd/profcollectctl.rs @@ -29,8 +29,9 @@ command: stop Terminate periodic collection. once Request an one-off trace. process Convert traces to perf profiles. - report Create a report containing all profiles. reconfig Refresh configuration. + report Create a report containing all profiles. + reset Clear all local data. help Print this message. "#; @@ -65,6 +66,10 @@ fn main() -> Result<()> { let path = libprofcollectd::report().context("Failed to create profile report.")?; println!("Report created at: {}", &path); } + "reset" => { + libprofcollectd::reset().context("Failed to reset.")?; + println!("Reset done."); + } "help" => println!("{}", &HELP_MSG), arg => bail!("Unknown argument: {}\n{}", &arg, &HELP_MSG), } diff --git a/profcollectd/profcollectd.rc b/profcollectd/profcollectd.rc index d1dbd9ef..b92fccba 100644 --- a/profcollectd/profcollectd.rc +++ b/profcollectd/profcollectd.rc @@ -6,15 +6,15 @@ service profcollectd /system/bin/profcollectd group root wakelock writepid /dev/cpuset/system-background/tasks -on property:persist.device_config.profcollect_native_boot.enabled=true - start profcollectd +on post-fs-data + # Create directory for profcollectd. + mkdir /data/misc/profcollectd 0770 shell shell + mkdir /data/misc/profcollectd/trace 0770 shell shell + mkdir /data/misc/profcollectd/output 0770 shell shell + mkdir /data/misc/profcollectd/report 0770 shell shell -on property:persist.profcollectd.enabled_override=true +on boot && property:persist.device_config.profcollect_native_boot.enabled=true start profcollectd -on post-fs-data - # Create directory for profcollectd. - mkdir /data/misc/profcollectd 0770 root system - mkdir /data/misc/profcollectd/trace 0770 root system - mkdir /data/misc/profcollectd/output 0770 root system - mkdir /data/misc/profcollectd/report 0770 root system +on boot && property:persist.device_config.profcollect_native_boot.enabled= + exec_background - root shell -- /system/bin/profcollectctl reset diff --git a/simpleperf/test_util.cpp b/simpleperf/test_util.cpp index d85294f5..fcbdf98f 100644 --- a/simpleperf/test_util.cpp +++ b/simpleperf/test_util.cpp @@ -78,6 +78,7 @@ bool HasHardwareCounter() { auto arch = GetBuildArch(); std::string fingerprint = android::base::GetProperty("ro.system.build.fingerprint", ""); bool is_emulator = android::base::StartsWith(fingerprint, "google/sdk_gphone") || + android::base::StartsWith(fingerprint, "google/sdk_gpc") || android::base::StartsWith(fingerprint, "generic/cf"); if (arch == ARCH_X86_64 || arch == ARCH_X86_32 || is_emulator) { |