blob: 46cd7f2514f088458c3b3b15c846925297da9824 [file] [log] [blame]
Yi Konge3aab142021-03-02 13:58:25 +08001//
2// Copyright (C) 2021 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
17//! ProfCollect configurations.
18
19use anyhow::Result;
20use lazy_static::lazy_static;
Yi Kong037bde82021-03-23 14:25:38 +080021use macaddr::MacAddr6;
22use rand::Rng;
Yi Konge3aab142021-03-02 13:58:25 +080023use serde::{Deserialize, Serialize};
24use std::error::Error;
Yi Kong34ebf872021-11-29 19:57:55 +080025use std::fs::{read_dir, remove_file};
Yi Konge3aab142021-03-02 13:58:25 +080026use std::path::Path;
27use std::str::FromStr;
28use std::time::Duration;
29
30const PROFCOLLECT_CONFIG_NAMESPACE: &str = "profcollect_native_boot";
Yi Kong037bde82021-03-23 14:25:38 +080031const PROFCOLLECT_NODE_ID_PROPERTY: &str = "persist.profcollectd.node_id";
Yi Konge3aab142021-03-02 13:58:25 +080032
Yi Kong87d0a172021-12-09 01:37:57 +080033const DEFAULT_BINARY_FILTER: &str = "^/(system|apex/.+)/(bin|lib|lib64)/.+";
Yi Kong8dffc122021-07-20 16:55:39 +080034pub const REPORT_RETENTION_SECS: u64 = 14 * 24 * 60 * 60; // 14 days.
35
Yi Kong34ebf872021-11-29 19:57:55 +080036// Static configs that cannot be changed.
Yi Konge3aab142021-03-02 13:58:25 +080037lazy_static! {
38 pub static ref TRACE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/trace/");
39 pub static ref PROFILE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/output/");
40 pub static ref REPORT_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/report/");
Yi Konge3aab142021-03-02 13:58:25 +080041 pub static ref CONFIG_FILE: &'static Path =
42 Path::new("/data/misc/profcollectd/output/config.json");
Yabin Cuif1d91d22023-04-27 12:50:59 -070043 pub static ref LOG_FILE: &'static Path = Path::new("/data/misc/profcollectd/output/trace.log");
Yi Konge3aab142021-03-02 13:58:25 +080044}
45
Yi Kong34ebf872021-11-29 19:57:55 +080046/// Dynamic configs, stored in config.json.
Yi Konge3aab142021-03-02 13:58:25 +080047#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
48pub struct Config {
49 /// Version of config file scheme, always equals to 1.
50 version: u32,
Yi Kong037bde82021-03-23 14:25:38 +080051 /// Application specific node ID.
52 pub node_id: MacAddr6,
Yi Konge3aab142021-03-02 13:58:25 +080053 /// Device build fingerprint.
54 pub build_fingerprint: String,
55 /// Interval between collections.
56 pub collection_interval: Duration,
57 /// Length of time each collection lasts for.
58 pub sampling_period: Duration,
59 /// An optional filter to limit which binaries to or not to profile.
60 pub binary_filter: String,
Yi Kong581aa3a2021-11-24 00:19:30 +080061 /// Maximum size of the trace directory.
62 pub max_trace_limit: u64,
Yi Konge3aab142021-03-02 13:58:25 +080063}
64
65impl Config {
66 pub fn from_env() -> Result<Self> {
67 Ok(Config {
68 version: 1,
Yi Kong037bde82021-03-23 14:25:38 +080069 node_id: get_or_initialise_node_id()?,
70 build_fingerprint: get_build_fingerprint()?,
Yi Konge3aab142021-03-02 13:58:25 +080071 collection_interval: Duration::from_secs(get_device_config(
72 "collection_interval",
73 600,
74 )?),
75 sampling_period: Duration::from_millis(get_device_config("sampling_period", 500)?),
Yi Kong87d0a172021-12-09 01:37:57 +080076 binary_filter: get_device_config("binary_filter", DEFAULT_BINARY_FILTER.to_string())?,
Yi Kong581aa3a2021-11-24 00:19:30 +080077 max_trace_limit: get_device_config(
78 "max_trace_limit",
79 /* 512MB */ 512 * 1024 * 1024,
80 )?,
Yi Konge3aab142021-03-02 13:58:25 +080081 })
82 }
83}
84
85impl ToString for Config {
86 fn to_string(&self) -> String {
87 serde_json::to_string(self).expect("Failed to deserialise configuration.")
88 }
89}
90
91impl FromStr for Config {
92 type Err = serde_json::Error;
93 fn from_str(s: &str) -> Result<Self, Self::Err> {
94 serde_json::from_str::<Config>(s)
95 }
96}
97
Yi Kong037bde82021-03-23 14:25:38 +080098fn get_or_initialise_node_id() -> Result<MacAddr6> {
Chris Wailes8f571e12021-07-27 16:04:09 -070099 let mut node_id = get_property(PROFCOLLECT_NODE_ID_PROPERTY, MacAddr6::nil())?;
Yi Kong037bde82021-03-23 14:25:38 +0800100 if node_id.is_nil() {
101 node_id = generate_random_node_id();
Chris Wailes8f571e12021-07-27 16:04:09 -0700102 set_property(PROFCOLLECT_NODE_ID_PROPERTY, node_id)?;
Yi Kong037bde82021-03-23 14:25:38 +0800103 }
104
105 Ok(node_id)
Yi Konge3aab142021-03-02 13:58:25 +0800106}
107
Yi Kong037bde82021-03-23 14:25:38 +0800108fn get_build_fingerprint() -> Result<String> {
109 get_property("ro.build.fingerprint", "unknown".to_string())
110}
111
112fn get_device_config<T>(key: &str, default_value: T) -> Result<T>
Yi Konge3aab142021-03-02 13:58:25 +0800113where
114 T: FromStr + ToString,
115 T::Err: Error + Send + Sync + 'static,
116{
Yi Kong037bde82021-03-23 14:25:38 +0800117 let default_value = default_value.to_string();
Dennis Shenf4195452023-05-30 14:55:44 +0000118 let config = flags_rust::GetServerConfigurableFlag(
Chris Wailes8f571e12021-07-27 16:04:09 -0700119 PROFCOLLECT_CONFIG_NAMESPACE,
120 key,
Yi Kong037bde82021-03-23 14:25:38 +0800121 &default_value,
Yi Konge3aab142021-03-02 13:58:25 +0800122 );
123 Ok(T::from_str(&config)?)
124}
Yi Kong037bde82021-03-23 14:25:38 +0800125
126fn get_property<T>(key: &str, default_value: T) -> Result<T>
127where
128 T: FromStr + ToString,
129 T::Err: Error + Send + Sync + 'static,
130{
131 let default_value = default_value.to_string();
Andrew Walbran0aaa3a22022-02-07 12:36:22 +0000132 let value = rustutils::system_properties::read(key).unwrap_or(None).unwrap_or(default_value);
Yi Kong037bde82021-03-23 14:25:38 +0800133 Ok(T::from_str(&value)?)
134}
135
Joel Galenson0ab91112021-07-20 14:51:42 -0700136fn set_property<T>(key: &str, value: T) -> Result<()>
Yi Kong037bde82021-03-23 14:25:38 +0800137where
138 T: ToString,
139{
140 let value = value.to_string();
Andrew Walbran0aaa3a22022-02-07 12:36:22 +0000141 Ok(rustutils::system_properties::write(key, &value)?)
Yi Kong037bde82021-03-23 14:25:38 +0800142}
143
144fn generate_random_node_id() -> MacAddr6 {
145 let mut node_id = rand::thread_rng().gen::<[u8; 6]>();
146 node_id[0] |= 0x1;
147 MacAddr6::from(node_id)
148}
Yi Kong34ebf872021-11-29 19:57:55 +0800149
150pub fn clear_data() -> Result<()> {
151 fn remove_files(path: &Path) -> Result<()> {
152 read_dir(path)?
153 .filter_map(|e| e.ok())
154 .map(|e| e.path())
Yabin Cuif1d91d22023-04-27 12:50:59 -0700155 .filter(|e| e.is_file() && e != *LOG_FILE)
Yi Kong34ebf872021-11-29 19:57:55 +0800156 .try_for_each(remove_file)?;
157 Ok(())
158 }
159
160 remove_files(&TRACE_OUTPUT_DIR)?;
161 remove_files(&PROFILE_OUTPUT_DIR)?;
162 remove_files(&REPORT_OUTPUT_DIR)?;
163 Ok(())
164}