xref: /aosp_15_r20/tools/asuite/adevice/src/restart_chooser.rs (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker //! Crate to provide the AppClass for an installed file.
2*c2e18aaaSAndroid Build Coastguard Worker /// The current implementation parses module info and creates
3*c2e18aaaSAndroid Build Coastguard Worker /// a map from installed file to its highest ranking "class".
4*c2e18aaaSAndroid Build Coastguard Worker /// Later the AppClass will be mapped to a restart level.
5*c2e18aaaSAndroid Build Coastguard Worker use serde::{Deserialize, Serialize};
6*c2e18aaaSAndroid Build Coastguard Worker use std::ffi::OsStr;
7*c2e18aaaSAndroid Build Coastguard Worker use std::path::Path;
8*c2e18aaaSAndroid Build Coastguard Worker 
9*c2e18aaaSAndroid Build Coastguard Worker use crate::cli::RestartChoice;
10*c2e18aaaSAndroid Build Coastguard Worker 
11*c2e18aaaSAndroid Build Coastguard Worker pub struct RestartChooser {
12*c2e18aaaSAndroid Build Coastguard Worker     // Users override for restarting.
13*c2e18aaaSAndroid Build Coastguard Worker     restart_choice: RestartChoice,
14*c2e18aaaSAndroid Build Coastguard Worker }
15*c2e18aaaSAndroid Build Coastguard Worker 
16*c2e18aaaSAndroid Build Coastguard Worker impl RestartChooser {
new(restart_choice: &RestartChoice) -> Self17*c2e18aaaSAndroid Build Coastguard Worker     pub fn new(restart_choice: &RestartChoice) -> Self {
18*c2e18aaaSAndroid Build Coastguard Worker         RestartChooser { restart_choice: restart_choice.clone() }
19*c2e18aaaSAndroid Build Coastguard Worker     }
20*c2e18aaaSAndroid Build Coastguard Worker 
21*c2e18aaaSAndroid Build Coastguard Worker     // Given a file in ANDROID_PRODUCT_OUT tree, return the restart type for it.
restart_type(&self, installed_file: &str) -> RestartType22*c2e18aaaSAndroid Build Coastguard Worker     pub fn restart_type(&self, installed_file: &str) -> RestartType {
23*c2e18aaaSAndroid Build Coastguard Worker         match self.restart_choice {
24*c2e18aaaSAndroid Build Coastguard Worker             RestartChoice::Auto => {
25*c2e18aaaSAndroid Build Coastguard Worker                 if can_soft_restart_based_on_filename(installed_file) {
26*c2e18aaaSAndroid Build Coastguard Worker                     RestartType::SoftRestart
27*c2e18aaaSAndroid Build Coastguard Worker                 } else {
28*c2e18aaaSAndroid Build Coastguard Worker                     RestartType::Reboot
29*c2e18aaaSAndroid Build Coastguard Worker                 }
30*c2e18aaaSAndroid Build Coastguard Worker             }
31*c2e18aaaSAndroid Build Coastguard Worker             RestartChoice::None => RestartType::None,
32*c2e18aaaSAndroid Build Coastguard Worker             RestartChoice::Reboot => RestartType::Reboot,
33*c2e18aaaSAndroid Build Coastguard Worker             RestartChoice::Restart => RestartType::SoftRestart,
34*c2e18aaaSAndroid Build Coastguard Worker         }
35*c2e18aaaSAndroid Build Coastguard Worker     }
36*c2e18aaaSAndroid Build Coastguard Worker }
37*c2e18aaaSAndroid Build Coastguard Worker 
38*c2e18aaaSAndroid Build Coastguard Worker // Some file extensions only need a SoftRestart due to being
39*c2e18aaaSAndroid Build Coastguard Worker // reloaded when zygote restarts on `adb shell start`
40*c2e18aaaSAndroid Build Coastguard Worker // Extensions like xml, prof, bprof come up with .jar files (i.e. framework-minus-apex),
41*c2e18aaaSAndroid Build Coastguard Worker // so we list them here too.
42*c2e18aaaSAndroid Build Coastguard Worker const SOFT_RESTART_FILE_EXTS: &[&str] =
43*c2e18aaaSAndroid Build Coastguard Worker     &["art", "oat", "vdex", "odex", "fsv_meta", "apk", "jar", "xml", "prof", "bprof", "idsig"];
can_soft_restart_based_on_filename(filename: &str) -> bool44*c2e18aaaSAndroid Build Coastguard Worker fn can_soft_restart_based_on_filename(filename: &str) -> bool {
45*c2e18aaaSAndroid Build Coastguard Worker     let ext = Path::new(filename).extension().and_then(OsStr::to_str).unwrap_or("");
46*c2e18aaaSAndroid Build Coastguard Worker     SOFT_RESTART_FILE_EXTS.contains(&ext)
47*c2e18aaaSAndroid Build Coastguard Worker }
48*c2e18aaaSAndroid Build Coastguard Worker 
49*c2e18aaaSAndroid Build Coastguard Worker #[derive(Debug, Clone, Serialize, Deserialize)]
50*c2e18aaaSAndroid Build Coastguard Worker pub struct Module {
51*c2e18aaaSAndroid Build Coastguard Worker     pub class: Vec<String>,
52*c2e18aaaSAndroid Build Coastguard Worker     pub installed: Vec<String>,
53*c2e18aaaSAndroid Build Coastguard Worker }
54*c2e18aaaSAndroid Build Coastguard Worker 
55*c2e18aaaSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq)]
56*c2e18aaaSAndroid Build Coastguard Worker pub enum RestartType {
57*c2e18aaaSAndroid Build Coastguard Worker     /// The device needs to be rebooted
58*c2e18aaaSAndroid Build Coastguard Worker     Reboot,
59*c2e18aaaSAndroid Build Coastguard Worker     /// Adb shell restart will suffice
60*c2e18aaaSAndroid Build Coastguard Worker     SoftRestart,
61*c2e18aaaSAndroid Build Coastguard Worker     /// No restarts needed.
62*c2e18aaaSAndroid Build Coastguard Worker     None,
63*c2e18aaaSAndroid Build Coastguard Worker     // A force kill command will be enough.
64*c2e18aaaSAndroid Build Coastguard Worker     // RestartBinary,
65*c2e18aaaSAndroid Build Coastguard Worker }
66*c2e18aaaSAndroid Build Coastguard Worker 
67*c2e18aaaSAndroid Build Coastguard Worker #[cfg(test)]
68*c2e18aaaSAndroid Build Coastguard Worker mod tests {
69*c2e18aaaSAndroid Build Coastguard Worker 
70*c2e18aaaSAndroid Build Coastguard Worker     use super::*;
auto_restart() -> RestartChooser71*c2e18aaaSAndroid Build Coastguard Worker     fn auto_restart() -> RestartChooser {
72*c2e18aaaSAndroid Build Coastguard Worker         RestartChooser::new(&RestartChoice::Auto)
73*c2e18aaaSAndroid Build Coastguard Worker     }
74*c2e18aaaSAndroid Build Coastguard Worker 
75*c2e18aaaSAndroid Build Coastguard Worker     #[test]
reboot_for_module_with_shared_and_static_lib()76*c2e18aaaSAndroid Build Coastguard Worker     fn reboot_for_module_with_shared_and_static_lib() {
77*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(
78*c2e18aaaSAndroid Build Coastguard Worker             RestartType::Reboot,
79*c2e18aaaSAndroid Build Coastguard Worker             auto_restart().restart_type("vendor/lib64/DefaultVehicleHal.so")
80*c2e18aaaSAndroid Build Coastguard Worker         );
81*c2e18aaaSAndroid Build Coastguard Worker     }
82*c2e18aaaSAndroid Build Coastguard Worker 
83*c2e18aaaSAndroid Build Coastguard Worker     #[test]
test_so_rebooots()84*c2e18aaaSAndroid Build Coastguard Worker     fn test_so_rebooots() {
85*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(RestartType::Reboot, auto_restart().restart_type("vendor/lib64/Weird.so"));
86*c2e18aaaSAndroid Build Coastguard Worker     }
87*c2e18aaaSAndroid Build Coastguard Worker     #[test]
test_bogus_file_rebooots()88*c2e18aaaSAndroid Build Coastguard Worker     fn test_bogus_file_rebooots() {
89*c2e18aaaSAndroid Build Coastguard Worker         // It doesn't matter if the file exists or not, if the extension doesn't match, it is a reboot.
90*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(RestartType::Reboot, auto_restart().restart_type("bad/file/path"));
91*c2e18aaaSAndroid Build Coastguard Worker     }
92*c2e18aaaSAndroid Build Coastguard Worker 
93*c2e18aaaSAndroid Build Coastguard Worker     #[test]
soft_restart_for_certain_file_extensions()94*c2e18aaaSAndroid Build Coastguard Worker     fn soft_restart_for_certain_file_extensions() {
95*c2e18aaaSAndroid Build Coastguard Worker         // Have extensions in SOFT_RESET_FILE_EXTS
96*c2e18aaaSAndroid Build Coastguard Worker         for installed_file in &[
97*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.art",
98*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.oat",
99*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.vdex",
100*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.fsv_meta",
101*c2e18aaaSAndroid Build Coastguard Worker         ] {
102*c2e18aaaSAndroid Build Coastguard Worker             assert_eq!(
103*c2e18aaaSAndroid Build Coastguard Worker                 RestartType::SoftRestart,
104*c2e18aaaSAndroid Build Coastguard Worker                 auto_restart().restart_type(installed_file),
105*c2e18aaaSAndroid Build Coastguard Worker                 "Wrong class for {}",
106*c2e18aaaSAndroid Build Coastguard Worker                 installed_file
107*c2e18aaaSAndroid Build Coastguard Worker             );
108*c2e18aaaSAndroid Build Coastguard Worker         }
109*c2e18aaaSAndroid Build Coastguard Worker 
110*c2e18aaaSAndroid Build Coastguard Worker         // Do NOT have extensions in SOFT_RESET_FILE_EXTS (REBOOT due to module class)
111*c2e18aaaSAndroid Build Coastguard Worker         for installed_file in &[
112*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.extraart",
113*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path.artextra",
114*c2e18aaaSAndroid Build Coastguard Worker             "vendor/good/file/path",
115*c2e18aaaSAndroid Build Coastguard Worker         ] {
116*c2e18aaaSAndroid Build Coastguard Worker             assert_eq!(
117*c2e18aaaSAndroid Build Coastguard Worker                 RestartType::Reboot,
118*c2e18aaaSAndroid Build Coastguard Worker                 auto_restart().restart_type(installed_file),
119*c2e18aaaSAndroid Build Coastguard Worker                 "Wrong class for {}",
120*c2e18aaaSAndroid Build Coastguard Worker                 installed_file
121*c2e18aaaSAndroid Build Coastguard Worker             );
122*c2e18aaaSAndroid Build Coastguard Worker         }
123*c2e18aaaSAndroid Build Coastguard Worker     }
124*c2e18aaaSAndroid Build Coastguard Worker 
125*c2e18aaaSAndroid Build Coastguard Worker     #[test]
binary_with_rc_file_reboots_for_rc()126*c2e18aaaSAndroid Build Coastguard Worker     fn binary_with_rc_file_reboots_for_rc() {
127*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(
128*c2e18aaaSAndroid Build Coastguard Worker             RestartType::Reboot,
129*c2e18aaaSAndroid Build Coastguard Worker             auto_restart().restart_type("system/bin/surfaceflinger.rc")
130*c2e18aaaSAndroid Build Coastguard Worker         );
131*c2e18aaaSAndroid Build Coastguard Worker         // This fails after our choice to reboot based on extension.
132*c2e18aaaSAndroid Build Coastguard Worker         // assert_eq!(
133*c2e18aaaSAndroid Build Coastguard Worker         //     RestartType::SoftRestart,
134*c2e18aaaSAndroid Build Coastguard Worker         //     auto_restart().restart_type("system/bin/surfaceflinger")
135*c2e18aaaSAndroid Build Coastguard Worker         // );
136*c2e18aaaSAndroid Build Coastguard Worker     }
137*c2e18aaaSAndroid Build Coastguard Worker 
138*c2e18aaaSAndroid Build Coastguard Worker     #[test]
restart_choice_is_used()139*c2e18aaaSAndroid Build Coastguard Worker     fn restart_choice_is_used() {
140*c2e18aaaSAndroid Build Coastguard Worker         let restart_chooser = RestartChooser::new(&RestartChoice::None);
141*c2e18aaaSAndroid Build Coastguard Worker         assert_eq!(RestartType::None, restart_chooser.restart_type("system/bin/surfaceflinger.rc"));
142*c2e18aaaSAndroid Build Coastguard Worker     }
143*c2e18aaaSAndroid Build Coastguard Worker }
144