mirror of
https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation.git
synced 2026-08-09 23:29:11 +02:00
refactor: avoid set_var by specifying serial
This commit is contained in:
parent
cf054c8808
commit
fed1580e20
6 changed files with 144 additions and 117 deletions
|
|
@ -1,8 +1,5 @@
|
|||
use crate::core::utils::DisplayablePath;
|
||||
use crate::core::{
|
||||
sync::{get_android_sdk, User},
|
||||
theme::Theme,
|
||||
};
|
||||
use crate::core::{sync::User, theme::Theme};
|
||||
use crate::gui::views::settings::Settings;
|
||||
use crate::CACHE_DIR;
|
||||
use crate::CONFIG_DIR;
|
||||
|
|
@ -36,6 +33,7 @@ pub struct BackupSettings {
|
|||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct DeviceSettings {
|
||||
/// Unique serial identifier
|
||||
pub device_id: String,
|
||||
pub disable_mode: bool,
|
||||
pub multi_user_mode: bool,
|
||||
|
|
@ -57,7 +55,7 @@ impl Default for DeviceSettings {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
device_id: String::default(),
|
||||
multi_user_mode: get_android_sdk() > 21,
|
||||
multi_user_mode: false,
|
||||
disable_mode: false,
|
||||
backup: BackupSettings::default(),
|
||||
}
|
||||
|
|
|
|||
160
src/core/sync.rs
160
src/core/sync.rs
|
|
@ -1,5 +1,4 @@
|
|||
use crate::core::uad_lists::PackageState;
|
||||
use crate::core::utils::set_adb_serial;
|
||||
use crate::gui::views::list::PackageInfo;
|
||||
use crate::gui::widgets::package_row::PackageRow;
|
||||
use regex::Regex;
|
||||
|
|
@ -62,35 +61,37 @@ impl std::fmt::Display for User {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn adb_shell_command(shell: bool, args: &str) -> Result<String, String> {
|
||||
let adb_command = if shell {
|
||||
vec!["shell", args]
|
||||
} else {
|
||||
vec![args]
|
||||
pub fn adb_shell_command(shell: bool, serial: Option<&str>, args: &str) -> Result<String, String> {
|
||||
// this could be a `tinyvec` or `arrayvec`
|
||||
let mut adb_args = Vec::with_capacity(4);
|
||||
if let Some(s) = serial {
|
||||
adb_args.extend(["-s", s]);
|
||||
};
|
||||
if shell {
|
||||
adb_args.push("shell");
|
||||
}
|
||||
// the rest
|
||||
adb_args.push(args);
|
||||
|
||||
let mut command = Command::new("adb");
|
||||
command.args(adb_command);
|
||||
command.args(adb_args);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let command = command.creation_flags(0x08000000); // do not open a cmd window
|
||||
let command = command.creation_flags(0x0800_0000); // do not open a cmd window
|
||||
|
||||
match command.output() {
|
||||
Err(e) => {
|
||||
error!("ADB: {}", e);
|
||||
Err("ADB was not found".to_string())
|
||||
Err("Cannot run ADB, likely not found".to_string())
|
||||
}
|
||||
Ok(o) => {
|
||||
let stdout = String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
.to_string();
|
||||
if o.status.success() {
|
||||
Ok(String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
.to_string())
|
||||
Ok(stdout)
|
||||
} else {
|
||||
let stdout = String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
.to_string();
|
||||
let stderr = String::from_utf8(o.stderr)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
|
|
@ -116,7 +117,9 @@ pub enum AdbError {
|
|||
Generic(String),
|
||||
}
|
||||
|
||||
pub async fn perform_adb_commands(
|
||||
/// Runs a shell command on the device.
|
||||
pub async fn android_sh_cmd<S: AsRef<str>>(
|
||||
device_serial: S,
|
||||
action: String,
|
||||
command_type: CommandType,
|
||||
) -> Result<CommandType, AdbError> {
|
||||
|
|
@ -125,7 +128,7 @@ pub async fn perform_adb_commands(
|
|||
CommandType::Shell => "Shell",
|
||||
};
|
||||
|
||||
match adb_shell_command(true, &action) {
|
||||
match adb_shell_command(true, Some(device_serial.as_ref()), &action) {
|
||||
Ok(o) => {
|
||||
// On old devices, adb commands can return the `0` exit code even if there
|
||||
// is an error. On Android 4.4, ADB doesn't check if the package exists.
|
||||
|
|
@ -155,15 +158,20 @@ pub fn user_flag(user_id: Option<&User>) -> String {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn list_all_system_packages(user_id: Option<&User>) -> String {
|
||||
/// installed and uninstalled packages
|
||||
pub fn list_all_system_packages(device_serial: &str, user_id: Option<&User>) -> String {
|
||||
let action = format!("{PM_LIST_PACKS} -s -u{}", user_flag(user_id));
|
||||
|
||||
adb_shell_command(true, &action)
|
||||
adb_shell_command(true, Some(device_serial), &action)
|
||||
.unwrap_or_default()
|
||||
.replace("package:", "")
|
||||
}
|
||||
|
||||
pub fn hashset_system_packages(state: PackageState, user_id: Option<&User>) -> HashSet<String> {
|
||||
pub fn hashset_system_packages(
|
||||
state: PackageState,
|
||||
device_serial: &str,
|
||||
user_id: Option<&User>,
|
||||
) -> HashSet<String> {
|
||||
let user = user_flag(user_id);
|
||||
let action = match state {
|
||||
PackageState::Enabled => format!("{PM_LIST_PACKS} -s -e{user}"),
|
||||
|
|
@ -171,7 +179,7 @@ pub fn hashset_system_packages(state: PackageState, user_id: Option<&User>) -> H
|
|||
_ => String::default(), // You probably don't need to use this function for anything else
|
||||
};
|
||||
|
||||
adb_shell_command(true, &action)
|
||||
adb_shell_command(true, Some(device_serial), &action)
|
||||
.unwrap_or_default()
|
||||
.replace("package:", "")
|
||||
.lines()
|
||||
|
|
@ -216,45 +224,44 @@ pub fn apply_pkg_state_commands(
|
|||
package: &CorePackage,
|
||||
wanted_state: PackageState,
|
||||
selected_user: &User,
|
||||
phone: &Device,
|
||||
dev: &Device,
|
||||
) -> Vec<String> {
|
||||
// https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/ADB-reference
|
||||
// ALWAYS PUT THE COMMAND THAT CHANGES THE PACKAGE STATE FIRST!
|
||||
let commands = match wanted_state {
|
||||
PackageState::Enabled => {
|
||||
match package.state {
|
||||
PackageState::Disabled => match phone.android_sdk {
|
||||
i if i >= 23 => vec!["pm enable"],
|
||||
_ => vec!["pm enable"],
|
||||
},
|
||||
PackageState::Uninstalled => match phone.android_sdk {
|
||||
i if i >= 23 => vec!["cmd package install-existing"],
|
||||
21 | 22 => vec!["pm unhide"],
|
||||
19 | 20 => vec!["pm unblock", PM_CLEAR_PACK],
|
||||
_ => vec![], // Impossible action already prevented by the GUI
|
||||
},
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
PackageState::Enabled => match package.state {
|
||||
PackageState::Disabled => match dev.android_sdk {
|
||||
i if i >= 23 => vec!["pm enable"],
|
||||
_ => vec!["pm enable"],
|
||||
},
|
||||
PackageState::Uninstalled => match dev.android_sdk {
|
||||
i if i >= 23 => vec!["cmd package install-existing"],
|
||||
21 | 22 => vec!["pm unhide"],
|
||||
19 | 20 => vec!["pm unblock", PM_CLEAR_PACK],
|
||||
_ => unreachable!("already prevented by the GUI"),
|
||||
},
|
||||
_ => vec![],
|
||||
},
|
||||
PackageState::Disabled => match package.state {
|
||||
PackageState::Uninstalled | PackageState::Enabled => match phone.android_sdk {
|
||||
PackageState::Uninstalled | PackageState::Enabled => match dev.android_sdk {
|
||||
sdk if sdk >= 23 => vec!["pm disable-user", "am force-stop", PM_CLEAR_PACK],
|
||||
_ => vec![],
|
||||
},
|
||||
_ => vec![],
|
||||
},
|
||||
PackageState::Uninstalled => match package.state {
|
||||
PackageState::Enabled | PackageState::Disabled => match phone.android_sdk {
|
||||
PackageState::Enabled | PackageState::Disabled => match dev.android_sdk {
|
||||
sdk if sdk >= 23 => vec!["pm uninstall"], // > Android Marshmallow (6.0)
|
||||
21 | 22 => vec!["pm hide", PM_CLEAR_PACK], // Android Lollipop (5.x)
|
||||
19 | 20 => vec!["pm block", PM_CLEAR_PACK], // Android KitKat (4.4/4.4W)
|
||||
19 | 20 => vec!["pm block", PM_CLEAR_PACK], // Android KitKat (4.4/4.4W) and older
|
||||
_ => vec!["pm block", PM_CLEAR_PACK], // Disable mode is unavailable on older devices because the specific ADB commands need root
|
||||
},
|
||||
_ => vec![],
|
||||
},
|
||||
PackageState::All => vec![],
|
||||
};
|
||||
let user = (phone.android_sdk >= 21).then_some(selected_user);
|
||||
}; // this should be a `tinyvec`, as `len <= 4`
|
||||
|
||||
let user = supports_multi_user(dev).then_some(selected_user);
|
||||
request_builder(&commands, &package.name, user)
|
||||
}
|
||||
|
||||
|
|
@ -269,9 +276,9 @@ pub fn request_builder(commands: &[&str], package: &str, user: Option<&User>) ->
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Get the current device model by querying the `ro.product.model` property.
|
||||
pub fn get_phone_model() -> String {
|
||||
adb_shell_command(true, "getprop ro.product.model").unwrap_or_else(|err| {
|
||||
/// Get the model by querying the `ro.product.model` property.
|
||||
pub fn get_device_model(serial: &str) -> String {
|
||||
adb_shell_command(true, Some(serial), "getprop ro.product.model").unwrap_or_else(|err| {
|
||||
println!("ERROR: {err}");
|
||||
if err.contains("adb: no devices/emulators found") {
|
||||
"no devices/emulators found".to_string()
|
||||
|
|
@ -281,40 +288,58 @@ pub fn get_phone_model() -> String {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get the current device Android SDK version by querying the
|
||||
/// Get Android SDK version by querying the
|
||||
// `ro.build.version.sdk` property or defaulting to 0.
|
||||
pub fn get_android_sdk() -> u8 {
|
||||
adb_shell_command(true, "getprop ro.build.version.sdk").map_or(0, |sdk| sdk.parse().unwrap())
|
||||
pub fn get_android_sdk(device_serial: &str) -> u8 {
|
||||
adb_shell_command(true, Some(device_serial), "getprop ro.build.version.sdk").map_or(0, |sdk| {
|
||||
sdk.parse().expect("SDK version numeral must be valid")
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the current device brand by querying the `ro.product.brand` property.
|
||||
pub fn get_phone_brand() -> String {
|
||||
/// Get the brand by querying the `ro.product.brand` property.
|
||||
pub fn get_device_brand(serial: &str) -> String {
|
||||
format!(
|
||||
"{} {}",
|
||||
adb_shell_command(true, "getprop ro.product.brand")
|
||||
adb_shell_command(true, Some(serial), "getprop ro.product.brand")
|
||||
.map(|s| s.trim().to_string())
|
||||
.unwrap_or_default(),
|
||||
get_phone_model()
|
||||
get_device_model(serial)
|
||||
)
|
||||
}
|
||||
|
||||
/// Minimum inclusive Android SDK version
|
||||
/// that supports multi-user mode.
|
||||
/// Lollipop 5.0
|
||||
pub const MULTI_USER_SDK: u8 = 21;
|
||||
|
||||
/// Check if it supports multi-user mode, by comparing SDK version.
|
||||
#[must_use]
|
||||
pub const fn supports_multi_user(dev: &Device) -> bool {
|
||||
dev.android_sdk >= MULTI_USER_SDK
|
||||
}
|
||||
|
||||
/// Check if a `user_id` is protected on a device by trying
|
||||
/// to list associated packages.
|
||||
pub fn is_protected_user(user_id: &str) -> bool {
|
||||
adb_shell_command(true, &format!("{PM_LIST_PACKS} -s --user {user_id}")).is_err()
|
||||
pub fn is_protected_user(user_id: &str, device_serial: &str) -> bool {
|
||||
adb_shell_command(
|
||||
true,
|
||||
Some(device_serial),
|
||||
&format!("{PM_LIST_PACKS} -s --user {user_id}"),
|
||||
)
|
||||
.is_err()
|
||||
}
|
||||
|
||||
pub fn get_user_list() -> Vec<User> {
|
||||
pub fn get_user_list(device_serial: &str) -> Vec<User> {
|
||||
#[dynamic]
|
||||
static RE: Regex = Regex::new(r"\{([0-9]+)").unwrap_or_else(|_| unreachable!());
|
||||
adb_shell_command(true, "pm list users")
|
||||
adb_shell_command(true, Some(device_serial), "pm list users")
|
||||
.map(|users| {
|
||||
RE.find_iter(&users)
|
||||
.enumerate()
|
||||
.map(|(i, u)| User {
|
||||
id: u.as_str()[1..].parse().unwrap(),
|
||||
index: i,
|
||||
protected: is_protected_user(&u.as_str()[1..]),
|
||||
protected: is_protected_user(&u.as_str()[1..], device_serial),
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
|
@ -325,22 +350,19 @@ pub fn get_user_list() -> Vec<User> {
|
|||
pub async fn get_devices_list() -> Vec<Device> {
|
||||
retry(
|
||||
Fixed::from_millis(500).take(120),
|
||||
|| match adb_shell_command(false, "devices") {
|
||||
|| match adb_shell_command(false, None, "devices") {
|
||||
Ok(devices) => {
|
||||
let mut device_list: Vec<Device> = vec![];
|
||||
if !RE.is_match(&devices) {
|
||||
return OperationResult::Retry(vec![]);
|
||||
}
|
||||
for device in RE.captures_iter(&devices) {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
set_adb_serial(&device[1])
|
||||
};
|
||||
let serial = &device[1];
|
||||
device_list.push(Device {
|
||||
model: get_phone_brand(),
|
||||
android_sdk: get_android_sdk(),
|
||||
user_list: get_user_list(),
|
||||
adb_id: device[1].to_string(),
|
||||
model: get_device_brand(serial),
|
||||
android_sdk: get_android_sdk(serial),
|
||||
user_list: get_user_list(serial),
|
||||
adb_id: serial.to_string(),
|
||||
});
|
||||
}
|
||||
OperationResult::Ok(device_list)
|
||||
|
|
@ -356,7 +378,7 @@ pub async fn get_devices_list() -> Vec<Device> {
|
|||
}
|
||||
|
||||
pub async fn initial_load() -> bool {
|
||||
match adb_shell_command(false, "devices") {
|
||||
match adb_shell_command(false, None, "devices") {
|
||||
Ok(_devices) => true,
|
||||
Err(_err) => false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use crate::gui::widgets::package_row::PackageRow;
|
|||
use chrono::offset::Utc;
|
||||
use chrono::{DateTime, Local};
|
||||
use csv::Writer;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::{fmt, fs};
|
||||
|
|
@ -20,20 +19,16 @@ pub enum Error {
|
|||
DialogClosed,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
#[allow(
|
||||
clippy::semicolon_if_nothing_returned,
|
||||
reason = "fn must return whatever `set_var` returns"
|
||||
)]
|
||||
pub unsafe fn set_adb_serial<D: AsRef<OsStr>>(device_serial: D) {
|
||||
// https://developer.android.com/tools/variables#adb
|
||||
std::env::set_var("ANDROID_SERIAL", device_serial)
|
||||
}
|
||||
|
||||
pub fn fetch_packages(uad_lists: &PackageHashMap, user_id: Option<&User>) -> Vec<PackageRow> {
|
||||
let all_system_packages = list_all_system_packages(user_id); // installed and uninstalled packages
|
||||
let enabled_system_packages = hashset_system_packages(PackageState::Enabled, user_id);
|
||||
let disabled_system_packages = hashset_system_packages(PackageState::Disabled, user_id);
|
||||
pub fn fetch_packages(
|
||||
uad_lists: &PackageHashMap,
|
||||
device_serial: &str,
|
||||
user_id: Option<&User>,
|
||||
) -> Vec<PackageRow> {
|
||||
let all_system_packages = list_all_system_packages(device_serial, user_id);
|
||||
let enabled_system_packages =
|
||||
hashset_system_packages(PackageState::Enabled, device_serial, user_id);
|
||||
let disabled_system_packages =
|
||||
hashset_system_packages(PackageState::Disabled, device_serial, user_id);
|
||||
let mut description;
|
||||
let mut uad_list;
|
||||
let mut state;
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@ pub mod style;
|
|||
pub mod views;
|
||||
pub mod widgets;
|
||||
|
||||
use crate::core::sync::{
|
||||
get_devices_list, initial_load, perform_adb_commands, CommandType, Device,
|
||||
};
|
||||
use crate::core::sync::{android_sh_cmd, get_devices_list, initial_load, CommandType, Device};
|
||||
use crate::core::theme::Theme;
|
||||
use crate::core::uad_lists::UadListState;
|
||||
use crate::core::update::{get_latest_release, Release, SelfUpdateState, SelfUpdateStatus};
|
||||
use crate::core::utils::{set_adb_serial, string_to_theme, NAME};
|
||||
use crate::core::utils::{string_to_theme, NAME};
|
||||
|
||||
use iced::advanced::graphics::image::image_rs::ImageFormat;
|
||||
use iced::font;
|
||||
|
|
@ -161,10 +159,15 @@ impl Application for UadGui {
|
|||
}
|
||||
Message::RebootButtonPressed => {
|
||||
self.apps_view = AppsView::default();
|
||||
let serial = match &self.selected_device {
|
||||
Some(d) => d.adb_id.clone(),
|
||||
_ => String::default(),
|
||||
};
|
||||
self.selected_device = None;
|
||||
self.devices_list = vec![];
|
||||
Command::perform(
|
||||
perform_adb_commands("reboot".to_string(), CommandType::Shell),
|
||||
// https://android.stackexchange.com/questions/230256/adb-reboot-vs-adb-shell-reboot
|
||||
android_sh_cmd(serial, "reboot".to_string(), CommandType::Shell),
|
||||
|_| Message::Nothing,
|
||||
)
|
||||
}
|
||||
|
|
@ -256,10 +259,6 @@ impl Application for UadGui {
|
|||
Message::DeviceSelected(s_device) => {
|
||||
self.selected_device = Some(s_device.clone());
|
||||
self.view = View::List;
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
set_adb_serial(s_device.adb_id)
|
||||
};
|
||||
info!("{:-^65}", "-");
|
||||
info!(
|
||||
"ANDROID_SDK: {} | DEVICE: {}",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
use crate::core::config::DeviceSettings;
|
||||
use crate::core::helpers::button_primary;
|
||||
use crate::core::sync::{
|
||||
apply_pkg_state_commands, perform_adb_commands, AdbError, CommandType, Device, User,
|
||||
android_sh_cmd, apply_pkg_state_commands, AdbError, CommandType, Device, User,
|
||||
};
|
||||
use crate::core::theme::Theme;
|
||||
use crate::core::uad_lists::{
|
||||
load_debloat_lists, Opposite, PackageHashMap, PackageState, Removal, UadList, UadListState,
|
||||
};
|
||||
use crate::core::utils::{
|
||||
export_selection, fetch_packages, open_url, set_adb_serial, EXPORT_FILE_NAME, NAME,
|
||||
};
|
||||
use crate::core::utils::{export_selection, fetch_packages, open_url, EXPORT_FILE_NAME, NAME};
|
||||
use crate::gui::style;
|
||||
use crate::gui::widgets::navigation_menu::ICONS;
|
||||
use std::path::PathBuf;
|
||||
|
|
@ -174,7 +172,11 @@ impl List {
|
|||
self.uad_lists.clone_from(&uad_list);
|
||||
*list_update_state = list_state;
|
||||
Command::perform(
|
||||
Self::load_packages(uad_list, selected_device.user_list.clone()),
|
||||
Self::load_packages(
|
||||
uad_list,
|
||||
selected_device.adb_id.clone(),
|
||||
selected_device.user_list.clone(),
|
||||
),
|
||||
Message::ApplyFilters,
|
||||
)
|
||||
}
|
||||
|
|
@ -851,13 +853,18 @@ impl List {
|
|||
.collect();
|
||||
}
|
||||
#[expect(clippy::unused_async, reason = "1 call-site")]
|
||||
async fn load_packages(uad_list: PackageHashMap, user_list: Vec<User>) -> Vec<Vec<PackageRow>> {
|
||||
async fn load_packages<S: AsRef<str>>(
|
||||
uad_list: PackageHashMap,
|
||||
device_serial: S,
|
||||
user_list: Vec<User>,
|
||||
) -> Vec<Vec<PackageRow>> {
|
||||
let serial = device_serial.as_ref();
|
||||
if user_list.len() <= 1 {
|
||||
vec![fetch_packages(&uad_list, None)]
|
||||
vec![fetch_packages(&uad_list, serial, None)]
|
||||
} else {
|
||||
user_list
|
||||
.iter()
|
||||
.map(|user| fetch_packages(&uad_list, Some(user)))
|
||||
.map(|user| fetch_packages(&uad_list, serial, Some(user)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
@ -867,10 +874,6 @@ impl List {
|
|||
let uad_lists = load_debloat_lists(remote);
|
||||
match uad_lists {
|
||||
Ok(list) => {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
set_adb_serial(device.adb_id.clone())
|
||||
};
|
||||
if device.adb_id.is_empty() {
|
||||
error!("AppsView ready but no phone found");
|
||||
}
|
||||
|
|
@ -950,7 +953,9 @@ fn build_action_pkg_commands(
|
|||
let pkg = &packages[selection.0][selection.1];
|
||||
let wanted_state = pkg.state.opposite(settings.disable_mode);
|
||||
|
||||
let mut commands = vec![];
|
||||
// assume 2 actions per user
|
||||
let mut commands = Vec::with_capacity(device.user_list.len() * 2);
|
||||
|
||||
for u in device.user_list.iter().filter(|&&u| {
|
||||
!u.protected && (packages[u.index][selection.1].selected || settings.multi_user_mode)
|
||||
}) {
|
||||
|
|
@ -971,7 +976,13 @@ fn build_action_pkg_commands(
|
|||
// In the end there is only one package state change
|
||||
// even if we run multiple adb commands
|
||||
commands.push(Command::perform(
|
||||
perform_adb_commands(action, CommandType::PackageManager(p_info)),
|
||||
android_sh_cmd(
|
||||
// this is typically small,
|
||||
// so it's fine.
|
||||
device.adb_id.clone(),
|
||||
action,
|
||||
CommandType::PackageManager(p_info),
|
||||
),
|
||||
if j == 0 {
|
||||
Message::ChangePackageState
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use crate::core::helpers::button_primary;
|
||||
use crate::core::sync::AdbError;
|
||||
|
||||
use crate::core::config::{BackupSettings, Config, DeviceSettings, GeneralSettings};
|
||||
use crate::core::save::{
|
||||
backup_phone, list_available_backup_user, list_available_backups, restore_backup,
|
||||
};
|
||||
use crate::core::sync::{get_android_sdk, perform_adb_commands, CommandType, Device, User};
|
||||
use crate::core::sync::{
|
||||
get_android_sdk, android_sh_cmd, supports_multi_user, AdbError, CommandType, Device, User,
|
||||
};
|
||||
use crate::core::theme::Theme;
|
||||
use crate::core::utils::{
|
||||
export_packages, open_folder, open_url, string_to_theme, DisplayablePath,
|
||||
|
|
@ -137,7 +138,7 @@ impl Settings {
|
|||
None => {
|
||||
self.device = DeviceSettings {
|
||||
device_id: phone.adb_id.clone(),
|
||||
multi_user_mode: phone.android_sdk > 21,
|
||||
multi_user_mode: supports_multi_user(phone),
|
||||
disable_mode: false,
|
||||
backup,
|
||||
}
|
||||
|
|
@ -186,7 +187,8 @@ impl Settings {
|
|||
for command in p.commands.clone() {
|
||||
*nb_running_async_adb_commands += 1;
|
||||
commands.push(Command::perform(
|
||||
perform_adb_commands(
|
||||
android_sh_cmd(
|
||||
phone.adb_id.clone(),
|
||||
command,
|
||||
CommandType::PackageManager(p_info.clone()),
|
||||
),
|
||||
|
|
@ -195,7 +197,7 @@ impl Settings {
|
|||
}
|
||||
}
|
||||
if r_packages.is_empty() {
|
||||
if get_android_sdk() == 0 {
|
||||
if get_android_sdk(&phone.adb_id) == 0 {
|
||||
self.device.backup.backup_state = "Device is not connected".to_string();
|
||||
} else {
|
||||
self.device.backup.backup_state =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue