Skip to content

Commit

Permalink
Asynchronous + multi-threaded ADB commands (closes #65) 🚀
Browse files Browse the repository at this point in the history
Smarter use of iced::Command to run as many tasks as possible concurrently/in parallel

- ADB commands no longer block the interaction with the UI.
- The UI now reacts in real-time to ADB actions (no longer waits for all actions to finish)
- Some refactoring along the way
  • Loading branch information
0x192 committed Dec 20, 2021
1 parent c93e722 commit 608c05a
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 156 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ and `Removed`.

### Added
- [[#52](https://github.com/0x192/universal-android-debloater/issues/52)] `uk.co.ee.myee` to the debloat lists (thanks [@lawson58](https://github.com/lawson85)).
- [[#58](https://github.com/0x192/universal-android-debloater/issues/52)] `android` to the debloat lists with the tag `Unsafe`.
- [[#49](https://github.com/0x192/universal-android-debloater/issues/49)] Multi-device support: You are now able to select a device among the list of all ADB connected devices/emulators.
- [[#44](https://github.com/0x192/universal-android-debloater/issues/44)] Persistent settings: Settings (only `theme` for now) are saved to a config file. Its location follows [the standards of the different platforms](https://github.com/dirs-dev/dirs-rs#example).

### Changed
- Review of the package lists recommendations. The `Recommended` debloat list is now safer (less likely to remove something you'd want to keep).
- [[#65](https://github.com/0x192/universal-android-debloater/issues/65)] ADB commands now run in parallel and asynchronously! This means no more UI freeze when performing long/many actions! :rocket:
- UI now updates itself in real time when performing ADB actions (thanks to async & multithreading). Before, it waited for the end of all actions.

### Fixed
- Miscellaneous minor issues in some package descriptions.
- Several bad recommendations.
- [[#50](https://github.com/0x192/universal-android-debloater/issues/50)] Resync button flipping theme back to `Lupin`.

## [0.3] - 2021-10-10
Expand Down
47 changes: 20 additions & 27 deletions src/core/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use std::process::Command;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;

#[dynamic]
static RE: Regex = Regex::new(r"\n([[:ascii:]]+)\s+device").unwrap();

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Phone {
pub model: String,
Expand Down Expand Up @@ -121,31 +124,40 @@ pub fn action_handler(
package: &PackageRow,
phone: &Phone,
settings: &SettingsPhone,
) -> Result<bool, bool> {
let actions: Vec<String> = match package.state {
) -> Vec<String> {
// https://github.com/0x192/universal-android-debloater/wiki/ADB-reference
match package.state {
PackageState::Enabled => match settings.disable_mode {
true => {
if phone.android_sdk < 21 {
// < Android Ice Cream Sandwich (4.0)
if phone.android_sdk < 14 {
vec![
format!("pm disable {}", package.name),
format!("pm clear {}", package.name),
]
}
// < Android Lollipop (5.0)
else if phone.android_sdk < 17 {
vec![
format!("am force-stop {}", package.name),
format!("pm disable-user {}", package.name),
format!("pm clear {}", package.name),
format!("pm hide {}", package.name),
]
} else if settings.multi_user_mode {
phone
.user_list
.iter()
.flat_map(|u| {
[
format!("am force-stop --user {} {}", u.id, package.name),
format!("pm disable-user --user {} {}", u.id, package.name),
format!("am force-stop --user {} {}", u.id, package.name),
format!("pm clear --user {} {}", u.id, package.name),
//format!("pm hide --user {} {}", u.id, package.name),
]
})
.collect()
} else {
vec![
format!("am force-stop --user {} {}", selected_user.id, package.name),
format!(
"pm disable-user --user {} {}",
selected_user.id, package.name
Expand Down Expand Up @@ -209,23 +221,7 @@ pub fn action_handler(
}
}
PackageState::All => vec![], // This can't happen (like... never)
};

for action in actions {
match adb_shell_command(true, &action) {
Ok(_) => {
info!("[{}] {}", package.removal, action);
}
Err(err) => {
if err.contains("[not installed for") {
} else {
error!("[{}] {} -> {}", package.removal, action, err);
return Err(false);
}
}
}
}
Ok(true)
}

pub fn get_phone_model() -> String {
Expand Down Expand Up @@ -276,15 +272,12 @@ pub fn get_user_list() -> Vec<User> {
}

// getprop ro.serialno
pub fn get_device_list() -> Vec<Phone> {
#[dynamic]
static RE: Regex = Regex::new(r"\n([[:ascii:]]+)\s+device").unwrap();

pub async fn get_device_list() -> Vec<Phone> {
match adb_shell_command(false, "devices") {
Ok(devices) => {
let mut device_list: Vec<Phone> = vec![];
for device in RE.captures_iter(&devices) {
env::set_var("ANDROID_SERIAL", device[1].to_string());
env::set_var("ANDROID_SERIAL", &device[1]);

device_list.push(Phone {
model: get_phone_brand(),
Expand Down
70 changes: 37 additions & 33 deletions src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ pub enum Message {
AppsAction(AppsMessage),
SettingsAction(SettingsMessage),
RefreshButtonPressed,
Init,
LoadDeviceList(Vec<Phone>),
Init(Vec<Phone>),
}

impl Application for UadGui {
Expand All @@ -73,21 +74,24 @@ impl Application for UadGui {
fn new(_flags: ()) -> (Self, Command<Message>) {
(
Self::default(),
Command::perform(Self::init(), |_| Message::Init),
Command::perform(get_device_list(), Message::Init),
)
}

fn title(&self) -> String {
String::from("UadGui")
String::from("Universal Android Debloater")
}

fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Init => {
Message::Init(device_list) => {
self.device_list = device_list;
self.selected_device = Some(Phone::default());
Command::perform(Self::refresh(10), Message::LoadDevices)
}
Message::RefreshButtonPressed => {
Message::LoadDeviceList(device_list) => {
self.device_list = device_list;

// Save the current selected device
let i = self
.device_list
Expand All @@ -97,9 +101,15 @@ impl Application for UadGui {
self.selected_device = Some(Phone::default());
Command::perform(Self::refresh(i), Message::LoadDevices)
}
Message::RefreshButtonPressed => {
self.apps_view.ready = false;
Command::batch([
Command::perform(Self::please_wait(), Message::AppsAction),
Command::perform(Self::device_lists(), Message::LoadDeviceList),
])
}
Message::LoadDevices(last_selected_device) => {
self.settings_view.phone = SettingsPhone::default();
self.device_list = get_device_list();

// Try to reload last selected phone
if !self.device_list.is_empty() {
Expand All @@ -110,19 +120,12 @@ impl Application for UadGui {
None => Some(Phone::default()),
},
};
env::set_var(
"ANDROID_SERIAL",
self.selected_device.clone().unwrap().adb_id,
);
info!("{:-^65}", "-");
info!(
"ANDROID_SDK: {} | PHONE: {}",
self.selected_device.as_ref().unwrap().android_sdk,
self.selected_device.as_ref().unwrap().model
);
self.apps_view = AppsView::default();
self.view = View::List;
Command::perform(Self::load_phone_packages(), Message::AppsAction)
Command::perform(
Self::load_phone_packages(self.selected_device.clone().unwrap()),
Message::AppsAction,
)
} else {
self.selected_device = None;
Command::none()
Expand Down Expand Up @@ -154,19 +157,12 @@ impl Application for UadGui {
}
Message::DeviceSelected(device) => {
self.selected_device = Some(device);
env::set_var(
"ANDROID_SERIAL",
self.selected_device.clone().unwrap().adb_id,
);
info!("{:-^65}", "-");
info!(
"ANDROID_SDK: {} | PHONE: {}",
self.selected_device.as_ref().unwrap().android_sdk,
self.selected_device.as_ref().unwrap().model
);
self.apps_view = AppsView::default();
self.view = View::List;
Command::perform(Self::load_phone_packages(), Message::AppsAction)
Command::perform(
Self::load_phone_packages(self.selected_device.clone().unwrap()),
Message::AppsAction,
)
}
}
}
Expand Down Expand Up @@ -267,17 +263,25 @@ impl UadGui {
Self::run(settings).unwrap_err();
}

pub async fn load_phone_packages() -> AppsMessage {
pub async fn load_phone_packages(phone: Phone) -> AppsMessage {
env::set_var("ANDROID_SERIAL", phone.adb_id);
info!("{:-^65}", "-");
info!(
"ANDROID_SDK: {} | PHONE: {}",
phone.android_sdk, phone.model
);
AppsMessage::LoadPackages
}

pub async fn init() -> Message {
Message::Init
}

pub async fn refresh(i: usize) -> usize {
i
}
pub async fn device_lists() -> Vec<Phone> {
get_device_list().await
}
pub async fn please_wait() -> AppsMessage {
AppsMessage::Nothing
}
}

fn refresh_icon() -> Text {
Expand Down
Loading

0 comments on commit 608c05a

Please sign in to comment.