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