diff options
author | 2024-02-26 10:58:58 -0800 | |
---|---|---|
committer | 2024-04-02 09:49:52 -0700 | |
commit | 682a45b6d2bfed732b584be10d3deed6faae8c71 (patch) | |
tree | c7805d5c6f67ec1ce4cfeaefd46a2a028e6c2e29 /cmds/sfdo/sfdo.rs | |
parent | cf0a70f65730c0429dba2d78731e288fb037b5f8 (diff) |
[sfdo] Migrate sfdo over to Rust.
Test: build and run on device.
Bug: 329450914
Change-Id: I6a1cbba7eacc74d960f9eb854928bac1ad66d20a
Diffstat (limited to 'cmds/sfdo/sfdo.rs')
-rw-r--r-- | cmds/sfdo/sfdo.rs | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/cmds/sfdo/sfdo.rs b/cmds/sfdo/sfdo.rs new file mode 100644 index 0000000000..863df6b7a0 --- /dev/null +++ b/cmds/sfdo/sfdo.rs @@ -0,0 +1,155 @@ +// Copyright (C) 2024 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. + +//! sfdo: Make surface flinger do things +use android_gui::{aidl::android::gui::ISurfaceComposer::ISurfaceComposer, binder}; +use clap::{Parser, Subcommand}; +use std::fmt::Debug; + +const SERVICE_IDENTIFIER: &str = "SurfaceFlingerAIDL"; + +fn print_result<T, E>(function_name: &str, res: Result<T, E>) +where + E: Debug, +{ + match res { + Ok(_) => println!("{}: Operation successful!", function_name), + Err(err) => println!("{}: Operation failed: {:?}", function_name, err), + } +} + +fn parse_toggle(toggle_value: &str) -> Option<bool> { + let positive = ["1", "true", "y", "yes", "on", "enabled", "show"]; + let negative = ["0", "false", "n", "no", "off", "disabled", "hide"]; + + let word = toggle_value.to_lowercase(); // Case-insensitive comparison + + if positive.contains(&word.as_str()) { + Some(true) + } else if negative.contains(&word.as_str()) { + Some(false) + } else { + None + } +} + +#[derive(Parser)] +#[command(version = "0.1", about = "Execute SurfaceFlinger internal commands.")] +#[command(propagate_version = true)] +struct Cli { + #[command(subcommand)] + command: Option<Commands>, +} + +#[derive(Subcommand, Debug)] +enum Commands { + #[command(about = "[optional(--delay)] Perform a debug flash.")] + DebugFlash { + #[arg(short, long, default_value_t = 0)] + delay: i32, + }, + + #[command( + about = "state = [enabled | disabled] When enabled, it disables Hardware Overlays, \ + and routes all window composition to the GPU. This can help check if \ + there is a bug in HW Composer." + )] + ForceClientComposition { state: Option<String> }, + + #[command(about = "state = [hide | show], displays the framerate in the top left corner.")] + FrameRateIndicator { state: Option<String> }, + + #[command(about = "Force composite ahead of next VSYNC.")] + ScheduleComposite, + + #[command(about = "Force commit ahead of next VSYNC.")] + ScheduleCommit, +} + +/// sfdo command line tool +/// +/// sfdo allows you to call different functions from the SurfaceComposer using +/// the adb shell. +fn main() { + binder::ProcessState::start_thread_pool(); + let composer_service = match binder::get_interface::<dyn ISurfaceComposer>(SERVICE_IDENTIFIER) { + Ok(service) => service, + Err(err) => { + eprintln!("Unable to connect to ISurfaceComposer: {}", err); + return; + } + }; + + let cli = Cli::parse(); + + match &cli.command { + Some(Commands::FrameRateIndicator { state }) => { + if let Some(op_state) = state { + let toggle = parse_toggle(op_state); + match toggle { + Some(true) => { + let res = composer_service.enableRefreshRateOverlay(true); + print_result("enableRefreshRateOverlay", res); + } + Some(false) => { + let res = composer_service.enableRefreshRateOverlay(false); + print_result("enableRefreshRateOverlay", res); + } + None => { + eprintln!("Invalid state: {}, choices are [hide | show]", op_state); + } + } + } else { + eprintln!("No state, choices are [hide | show]"); + } + } + Some(Commands::DebugFlash { delay }) => { + let res = composer_service.setDebugFlash(*delay); + print_result("setDebugFlash", res); + } + Some(Commands::ScheduleComposite) => { + let res = composer_service.scheduleComposite(); + print_result("scheduleComposite", res); + } + Some(Commands::ScheduleCommit) => { + let res = composer_service.scheduleCommit(); + print_result("scheduleCommit", res); + } + Some(Commands::ForceClientComposition { state }) => { + if let Some(op_state) = state { + let toggle = parse_toggle(op_state); + match toggle { + Some(true) => { + let res = composer_service.forceClientComposition(true); + print_result("forceClientComposition", res); + } + Some(false) => { + let res = composer_service.forceClientComposition(false); + print_result("forceClientComposition", res); + } + None => { + eprintln!("Invalid state: {}, choices are [enabled | disabled]", op_state); + } + } + } else { + eprintln!("No state, choices are [enabled | disabled]"); + } + } + None => { + println!("Execute SurfaceFlinger internal commands."); + println!("run `adb shell sfdo help` for more to view the commands."); + println!("run `adb shell sfdo [COMMAND] --help` for more info on the command."); + } + } +} |