xref: /aosp_15_r20/frameworks/native/cmds/sfdo/sfdo.rs (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker // Copyright (C) 2024 The Android Open Source Project
2*38e8c45fSAndroid Build Coastguard Worker //
3*38e8c45fSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*38e8c45fSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*38e8c45fSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*38e8c45fSAndroid Build Coastguard Worker //
7*38e8c45fSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*38e8c45fSAndroid Build Coastguard Worker //
9*38e8c45fSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*38e8c45fSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*38e8c45fSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*38e8c45fSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*38e8c45fSAndroid Build Coastguard Worker // limitations under the License.
14*38e8c45fSAndroid Build Coastguard Worker 
15*38e8c45fSAndroid Build Coastguard Worker //! sfdo: Make surface flinger do things
16*38e8c45fSAndroid Build Coastguard Worker use android_gui::{aidl::android::gui::ISurfaceComposer::ISurfaceComposer, binder};
17*38e8c45fSAndroid Build Coastguard Worker use clap::{Parser, Subcommand};
18*38e8c45fSAndroid Build Coastguard Worker use std::fmt::Debug;
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker const SERVICE_IDENTIFIER: &str = "SurfaceFlingerAIDL";
21*38e8c45fSAndroid Build Coastguard Worker 
print_result<T, E>(function_name: &str, res: Result<T, E>) where E: Debug,22*38e8c45fSAndroid Build Coastguard Worker fn print_result<T, E>(function_name: &str, res: Result<T, E>)
23*38e8c45fSAndroid Build Coastguard Worker where
24*38e8c45fSAndroid Build Coastguard Worker     E: Debug,
25*38e8c45fSAndroid Build Coastguard Worker {
26*38e8c45fSAndroid Build Coastguard Worker     match res {
27*38e8c45fSAndroid Build Coastguard Worker         Ok(_) => println!("{}: Operation successful!", function_name),
28*38e8c45fSAndroid Build Coastguard Worker         Err(err) => println!("{}: Operation failed: {:?}", function_name, err),
29*38e8c45fSAndroid Build Coastguard Worker     }
30*38e8c45fSAndroid Build Coastguard Worker }
31*38e8c45fSAndroid Build Coastguard Worker 
parse_toggle(toggle_value: &str) -> Option<bool>32*38e8c45fSAndroid Build Coastguard Worker fn parse_toggle(toggle_value: &str) -> Option<bool> {
33*38e8c45fSAndroid Build Coastguard Worker     let positive = ["1", "true", "y", "yes", "on", "enabled", "show"];
34*38e8c45fSAndroid Build Coastguard Worker     let negative = ["0", "false", "n", "no", "off", "disabled", "hide"];
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker     let word = toggle_value.to_lowercase(); // Case-insensitive comparison
37*38e8c45fSAndroid Build Coastguard Worker 
38*38e8c45fSAndroid Build Coastguard Worker     if positive.contains(&word.as_str()) {
39*38e8c45fSAndroid Build Coastguard Worker         Some(true)
40*38e8c45fSAndroid Build Coastguard Worker     } else if negative.contains(&word.as_str()) {
41*38e8c45fSAndroid Build Coastguard Worker         Some(false)
42*38e8c45fSAndroid Build Coastguard Worker     } else {
43*38e8c45fSAndroid Build Coastguard Worker         None
44*38e8c45fSAndroid Build Coastguard Worker     }
45*38e8c45fSAndroid Build Coastguard Worker }
46*38e8c45fSAndroid Build Coastguard Worker 
47*38e8c45fSAndroid Build Coastguard Worker #[derive(Parser)]
48*38e8c45fSAndroid Build Coastguard Worker #[command(version = "0.1", about = "Execute SurfaceFlinger internal commands.")]
49*38e8c45fSAndroid Build Coastguard Worker #[command(propagate_version = true)]
50*38e8c45fSAndroid Build Coastguard Worker struct Cli {
51*38e8c45fSAndroid Build Coastguard Worker     #[command(subcommand)]
52*38e8c45fSAndroid Build Coastguard Worker     command: Option<Commands>,
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker 
55*38e8c45fSAndroid Build Coastguard Worker #[derive(Subcommand, Debug)]
56*38e8c45fSAndroid Build Coastguard Worker enum Commands {
57*38e8c45fSAndroid Build Coastguard Worker     #[command(about = "[optional(--delay)] Perform a debug flash.")]
58*38e8c45fSAndroid Build Coastguard Worker     DebugFlash {
59*38e8c45fSAndroid Build Coastguard Worker         #[arg(short, long, default_value_t = 0)]
60*38e8c45fSAndroid Build Coastguard Worker         delay: i32,
61*38e8c45fSAndroid Build Coastguard Worker     },
62*38e8c45fSAndroid Build Coastguard Worker 
63*38e8c45fSAndroid Build Coastguard Worker     #[command(
64*38e8c45fSAndroid Build Coastguard Worker         about = "state = [enabled | disabled] When enabled, it disables Hardware Overlays, \
65*38e8c45fSAndroid Build Coastguard Worker                       and routes all window composition to the GPU. This can help check if \
66*38e8c45fSAndroid Build Coastguard Worker                       there is a bug in HW Composer."
67*38e8c45fSAndroid Build Coastguard Worker     )]
68*38e8c45fSAndroid Build Coastguard Worker     ForceClientComposition { state: Option<String> },
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker     #[command(about = "state = [hide | show], displays the framerate in the top left corner.")]
71*38e8c45fSAndroid Build Coastguard Worker     FrameRateIndicator { state: Option<String> },
72*38e8c45fSAndroid Build Coastguard Worker 
73*38e8c45fSAndroid Build Coastguard Worker     #[command(about = "Force composite ahead of next VSYNC.")]
74*38e8c45fSAndroid Build Coastguard Worker     ScheduleComposite,
75*38e8c45fSAndroid Build Coastguard Worker 
76*38e8c45fSAndroid Build Coastguard Worker     #[command(about = "Force commit ahead of next VSYNC.")]
77*38e8c45fSAndroid Build Coastguard Worker     ScheduleCommit,
78*38e8c45fSAndroid Build Coastguard Worker }
79*38e8c45fSAndroid Build Coastguard Worker 
80*38e8c45fSAndroid Build Coastguard Worker /// sfdo command line tool
81*38e8c45fSAndroid Build Coastguard Worker ///
82*38e8c45fSAndroid Build Coastguard Worker /// sfdo allows you to call different functions from the SurfaceComposer using
83*38e8c45fSAndroid Build Coastguard Worker /// the adb shell.
main()84*38e8c45fSAndroid Build Coastguard Worker fn main() {
85*38e8c45fSAndroid Build Coastguard Worker     binder::ProcessState::start_thread_pool();
86*38e8c45fSAndroid Build Coastguard Worker     let composer_service = match binder::get_interface::<dyn ISurfaceComposer>(SERVICE_IDENTIFIER) {
87*38e8c45fSAndroid Build Coastguard Worker         Ok(service) => service,
88*38e8c45fSAndroid Build Coastguard Worker         Err(err) => {
89*38e8c45fSAndroid Build Coastguard Worker             eprintln!("Unable to connect to ISurfaceComposer: {}", err);
90*38e8c45fSAndroid Build Coastguard Worker             return;
91*38e8c45fSAndroid Build Coastguard Worker         }
92*38e8c45fSAndroid Build Coastguard Worker     };
93*38e8c45fSAndroid Build Coastguard Worker 
94*38e8c45fSAndroid Build Coastguard Worker     let cli = Cli::parse();
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker     match &cli.command {
97*38e8c45fSAndroid Build Coastguard Worker         Some(Commands::FrameRateIndicator { state }) => {
98*38e8c45fSAndroid Build Coastguard Worker             if let Some(op_state) = state {
99*38e8c45fSAndroid Build Coastguard Worker                 let toggle = parse_toggle(op_state);
100*38e8c45fSAndroid Build Coastguard Worker                 match toggle {
101*38e8c45fSAndroid Build Coastguard Worker                     Some(true) => {
102*38e8c45fSAndroid Build Coastguard Worker                         let res = composer_service.enableRefreshRateOverlay(true);
103*38e8c45fSAndroid Build Coastguard Worker                         print_result("enableRefreshRateOverlay", res);
104*38e8c45fSAndroid Build Coastguard Worker                     }
105*38e8c45fSAndroid Build Coastguard Worker                     Some(false) => {
106*38e8c45fSAndroid Build Coastguard Worker                         let res = composer_service.enableRefreshRateOverlay(false);
107*38e8c45fSAndroid Build Coastguard Worker                         print_result("enableRefreshRateOverlay", res);
108*38e8c45fSAndroid Build Coastguard Worker                     }
109*38e8c45fSAndroid Build Coastguard Worker                     None => {
110*38e8c45fSAndroid Build Coastguard Worker                         eprintln!("Invalid state: {}, choices are [hide | show]", op_state);
111*38e8c45fSAndroid Build Coastguard Worker                     }
112*38e8c45fSAndroid Build Coastguard Worker                 }
113*38e8c45fSAndroid Build Coastguard Worker             } else {
114*38e8c45fSAndroid Build Coastguard Worker                 eprintln!("No state, choices are [hide | show]");
115*38e8c45fSAndroid Build Coastguard Worker             }
116*38e8c45fSAndroid Build Coastguard Worker         }
117*38e8c45fSAndroid Build Coastguard Worker         Some(Commands::DebugFlash { delay }) => {
118*38e8c45fSAndroid Build Coastguard Worker             let res = composer_service.setDebugFlash(*delay);
119*38e8c45fSAndroid Build Coastguard Worker             print_result("setDebugFlash", res);
120*38e8c45fSAndroid Build Coastguard Worker         }
121*38e8c45fSAndroid Build Coastguard Worker         Some(Commands::ScheduleComposite) => {
122*38e8c45fSAndroid Build Coastguard Worker             let res = composer_service.scheduleComposite();
123*38e8c45fSAndroid Build Coastguard Worker             print_result("scheduleComposite", res);
124*38e8c45fSAndroid Build Coastguard Worker         }
125*38e8c45fSAndroid Build Coastguard Worker         Some(Commands::ScheduleCommit) => {
126*38e8c45fSAndroid Build Coastguard Worker             let res = composer_service.scheduleCommit();
127*38e8c45fSAndroid Build Coastguard Worker             print_result("scheduleCommit", res);
128*38e8c45fSAndroid Build Coastguard Worker         }
129*38e8c45fSAndroid Build Coastguard Worker         Some(Commands::ForceClientComposition { state }) => {
130*38e8c45fSAndroid Build Coastguard Worker             if let Some(op_state) = state {
131*38e8c45fSAndroid Build Coastguard Worker                 let toggle = parse_toggle(op_state);
132*38e8c45fSAndroid Build Coastguard Worker                 match toggle {
133*38e8c45fSAndroid Build Coastguard Worker                     Some(true) => {
134*38e8c45fSAndroid Build Coastguard Worker                         let res = composer_service.forceClientComposition(true);
135*38e8c45fSAndroid Build Coastguard Worker                         print_result("forceClientComposition", res);
136*38e8c45fSAndroid Build Coastguard Worker                     }
137*38e8c45fSAndroid Build Coastguard Worker                     Some(false) => {
138*38e8c45fSAndroid Build Coastguard Worker                         let res = composer_service.forceClientComposition(false);
139*38e8c45fSAndroid Build Coastguard Worker                         print_result("forceClientComposition", res);
140*38e8c45fSAndroid Build Coastguard Worker                     }
141*38e8c45fSAndroid Build Coastguard Worker                     None => {
142*38e8c45fSAndroid Build Coastguard Worker                         eprintln!("Invalid state: {}, choices are [enabled | disabled]", op_state);
143*38e8c45fSAndroid Build Coastguard Worker                     }
144*38e8c45fSAndroid Build Coastguard Worker                 }
145*38e8c45fSAndroid Build Coastguard Worker             } else {
146*38e8c45fSAndroid Build Coastguard Worker                 eprintln!("No state, choices are [enabled | disabled]");
147*38e8c45fSAndroid Build Coastguard Worker             }
148*38e8c45fSAndroid Build Coastguard Worker         }
149*38e8c45fSAndroid Build Coastguard Worker         None => {
150*38e8c45fSAndroid Build Coastguard Worker             println!("Execute SurfaceFlinger internal commands.");
151*38e8c45fSAndroid Build Coastguard Worker             println!("run `adb shell sfdo help` for more to view the commands.");
152*38e8c45fSAndroid Build Coastguard Worker             println!("run `adb shell sfdo [COMMAND] --help` for more info on the command.");
153*38e8c45fSAndroid Build Coastguard Worker         }
154*38e8c45fSAndroid Build Coastguard Worker     }
155*38e8c45fSAndroid Build Coastguard Worker }
156