use async_trait::async_trait;
use smix_simctl::{SimctlClient, SimctlError, SimctlPermission};
use std::path::Path;
pub use crate::PermissionAction;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Permission {
Camera,
Microphone,
PhotoLibrary,
Location,
LocationAlways,
Notifications,
Contacts,
Calendar,
Reminders,
Bluetooth,
Motion,
Media,
Health,
FaceId,
HomeKit,
Storage,
PostNotifications,
}
impl Permission {
#[must_use]
pub fn to_simctl(self) -> Option<SimctlPermission> {
match self {
Permission::Camera => Some(SimctlPermission::Camera),
Permission::Microphone => Some(SimctlPermission::Microphone),
Permission::PhotoLibrary => Some(SimctlPermission::Photos),
Permission::Location => Some(SimctlPermission::Location),
Permission::LocationAlways => Some(SimctlPermission::LocationAlways),
Permission::Notifications | Permission::PostNotifications => {
Some(SimctlPermission::Notifications)
}
Permission::Contacts => Some(SimctlPermission::Contacts),
Permission::Calendar => Some(SimctlPermission::Calendar),
Permission::Reminders => Some(SimctlPermission::Reminders),
Permission::Bluetooth => Some(SimctlPermission::Bluetooth),
Permission::Motion => Some(SimctlPermission::Motion),
Permission::Media => Some(SimctlPermission::Media),
Permission::Health => Some(SimctlPermission::Health),
Permission::FaceId => Some(SimctlPermission::Faceid),
Permission::HomeKit => Some(SimctlPermission::HomeKit),
Permission::Storage => None,
}
}
#[must_use]
pub fn from_simctl(perm: SimctlPermission) -> Self {
match perm {
SimctlPermission::Camera => Permission::Camera,
SimctlPermission::Microphone => Permission::Microphone,
SimctlPermission::Photos => Permission::PhotoLibrary,
SimctlPermission::Location => Permission::Location,
SimctlPermission::LocationAlways => Permission::LocationAlways,
SimctlPermission::Notifications => Permission::Notifications,
SimctlPermission::Contacts => Permission::Contacts,
SimctlPermission::Calendar => Permission::Calendar,
SimctlPermission::Reminders => Permission::Reminders,
SimctlPermission::Bluetooth => Permission::Bluetooth,
SimctlPermission::Motion => Permission::Motion,
SimctlPermission::Media => Permission::Media,
SimctlPermission::Health => Permission::Health,
SimctlPermission::Faceid => Permission::FaceId,
SimctlPermission::HomeKit => Permission::HomeKit,
SimctlPermission::AddressBook => Permission::Contacts,
}
}
#[must_use]
pub fn to_android(self) -> Option<&'static str> {
match self {
Permission::Camera => Some("android.permission.CAMERA"),
Permission::Microphone => Some("android.permission.RECORD_AUDIO"),
Permission::PhotoLibrary => Some("android.permission.READ_MEDIA_IMAGES"),
Permission::Location => Some("android.permission.ACCESS_FINE_LOCATION"),
Permission::LocationAlways => Some("android.permission.ACCESS_BACKGROUND_LOCATION"),
Permission::Notifications | Permission::PostNotifications => {
Some("android.permission.POST_NOTIFICATIONS")
}
Permission::Contacts => Some("android.permission.READ_CONTACTS"),
Permission::Calendar => Some("android.permission.READ_CALENDAR"),
Permission::Bluetooth => Some("android.permission.BLUETOOTH_CONNECT"),
Permission::Motion => Some("android.permission.ACTIVITY_RECOGNITION"),
Permission::Media => Some("android.permission.READ_MEDIA_AUDIO"),
Permission::Storage => Some("android.permission.WRITE_EXTERNAL_STORAGE"),
Permission::Reminders
| Permission::Health
| Permission::FaceId
| Permission::HomeKit => None,
}
}
}
#[async_trait]
pub trait DeviceControl: Send + Sync {
fn platform(&self) -> smix_driver::Platform;
fn as_ios_simctl(&self) -> Option<&SimctlClient> {
None
}
async fn launch(&self, udid: &str, bundle_id: &str) -> Result<u32, SimctlError>;
async fn launch_with_args(
&self,
udid: &str,
bundle_id: &str,
args: &[String],
) -> Result<u32, SimctlError>;
async fn terminate(&self, udid: &str, bundle_id: &str) -> Result<(), SimctlError>;
async fn install(&self, udid: &str, app_path: &str) -> Result<(), SimctlError>;
async fn uninstall(&self, udid: &str, bundle_id: &str) -> Result<(), SimctlError>;
async fn keychain_reset(&self, udid: &str) -> Result<(), SimctlError>;
async fn open_url(&self, udid: &str, url: &str) -> Result<(), SimctlError>;
async fn send_push(
&self,
udid: &str,
bundle_id: &str,
apns_json_path: &str,
) -> Result<(), SimctlError>;
async fn screenshot(&self, udid: &str) -> Result<Vec<u8>, SimctlError>;
async fn pasteboard_set(&self, udid: &str, text: &str) -> Result<(), SimctlError>;
async fn pasteboard_get(&self, udid: &str) -> Result<String, SimctlError>;
async fn add_media(&self, udid: &str, paths: &[String]) -> Result<(), SimctlError>;
async fn location_set(&self, udid: &str, lat: f64, lon: f64) -> Result<(), SimctlError>;
async fn location_start(
&self,
udid: &str,
points: &[(f64, f64)],
speed_mps: Option<f64>,
) -> Result<(), SimctlError>;
async fn set_permission(
&self,
udid: &str,
bundle_id: &str,
permission: Permission,
action: PermissionAction,
) -> Result<(), SimctlError>;
async fn start_recording(&self, udid: &str, output_path: &Path) -> Result<(), SimctlError>;
async fn stop_recording(&self) -> Result<(), SimctlError>;
}