diff --git a/app/src/main/java/app/revanced/manager/data/room/apps/installed/InstalledApp.kt b/app/src/main/java/app/revanced/manager/data/room/apps/installed/InstalledApp.kt index ad7033dd..290a226d 100644 --- a/app/src/main/java/app/revanced/manager/data/room/apps/installed/InstalledApp.kt +++ b/app/src/main/java/app/revanced/manager/data/room/apps/installed/InstalledApp.kt @@ -9,7 +9,7 @@ import kotlinx.parcelize.Parcelize enum class InstallType(val stringResource: Int) { DEFAULT(R.string.default_install), - ROOT(R.string.root_install) + MOUNT(R.string.mount_install) } @Parcelize diff --git a/app/src/main/java/app/revanced/manager/domain/installer/RootInstaller.kt b/app/src/main/java/app/revanced/manager/domain/installer/RootInstaller.kt index 9ca6cd9b..885f8ad1 100644 --- a/app/src/main/java/app/revanced/manager/domain/installer/RootInstaller.kt +++ b/app/src/main/java/app/revanced/manager/domain/installer/RootInstaller.kt @@ -43,7 +43,7 @@ class RootInstaller( } } - return withTimeoutOrNull(Duration.ofSeconds(120L)) { + return withTimeoutOrNull(Duration.ofSeconds(20L)) { remoteFS.await() } ?: throw RootServiceException() } @@ -58,6 +58,10 @@ class RootInstaller( fun hasRootAccess() = Shell.isAppGrantedRoot() ?: false + fun isDeviceRooted() = System.getenv("PATH")?.split(":")?.any { path -> + File(path, "su").canExecute() + } ?: false + suspend fun isAppInstalled(packageName: String) = awaitRemoteFS().getFile("$modulesPath/$packageName-revanced").exists() diff --git a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt index 0e779df7..a5c551a4 100644 --- a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt +++ b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt @@ -135,7 +135,7 @@ class PatcherWorker( return try { if (args.input is SelectedApp.Installed) { installedAppRepository.get(args.packageName)?.let { - if (it.installType == InstallType.ROOT) { + if (it.installType == InstallType.MOUNT) { rootInstaller.unmount(args.packageName) } } diff --git a/app/src/main/java/app/revanced/manager/ui/component/patcher/InstallPickerDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/patcher/InstallPickerDialog.kt index ec3cf979..e331db2e 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/patcher/InstallPickerDialog.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/patcher/InstallPickerDialog.kt @@ -7,6 +7,7 @@ import androidx.compose.material3.Button import androidx.compose.material3.ListItem import androidx.compose.material3.RadioButton import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -27,7 +28,7 @@ fun InstallPickerDialog( AlertDialog( onDismissRequest = onDismiss, dismissButton = { - Button(onClick = onDismiss) { + TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } }, diff --git a/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppInfoScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppInfoScreen.kt index 2727e290..239aebbf 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppInfoScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppInfoScreen.kt @@ -81,7 +81,7 @@ fun InstalledAppInfoScreen( AppInfo(viewModel.appInfo) { Text(viewModel.installedApp.version, color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyMedium) - if (viewModel.installedApp.installType == InstallType.ROOT) { + if (viewModel.installedApp.installType == InstallType.MOUNT) { Text( text = if (viewModel.isMounted) { stringResource(R.string.mounted) @@ -112,7 +112,7 @@ fun InstalledAppInfoScreen( onClick = viewModel::uninstall ) - InstallType.ROOT -> { + InstallType.MOUNT -> { SegmentedButton( icon = Icons.Outlined.SettingsBackupRestore, text = stringResource(R.string.unpatch), @@ -138,7 +138,7 @@ fun InstalledAppInfoScreen( onPatchClick(viewModel.installedApp.originalPackageName, it) } }, - enabled = viewModel.installedApp.installType != InstallType.ROOT || viewModel.rootInstaller.hasRootAccess() + enabled = viewModel.installedApp.installType != InstallType.MOUNT || viewModel.rootInstaller.hasRootAccess() ) } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt index 096bbf03..2c7792d0 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.revanced.manager.R +import app.revanced.manager.data.room.apps.installed.InstallType import app.revanced.manager.ui.component.AppScaffold import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.InstallerStatusDialog @@ -139,7 +140,8 @@ fun PatcherScreen( }, onClick = { if (vm.installedPackageName == null) - showInstallPicker = true + if (vm.isDeviceRooted()) showInstallPicker = true + else vm.install(InstallType.DEFAULT) else vm.open() } ) diff --git a/app/src/main/java/app/revanced/manager/ui/screen/VersionSelectorScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/VersionSelectorScreen.kt index 3a5fc3d7..2ca8baa6 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/VersionSelectorScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/VersionSelectorScreen.kt @@ -113,8 +113,8 @@ fun VersionSelectorScreen( onClick = { viewModel.select(it) }, patchCount = supportedVersions[it.version], enabled = - !(installedApp?.installType == InstallType.ROOT && !viewModel.rootInstaller.hasRootAccess()), - alreadyPatched = installedApp != null && installedApp.installType != InstallType.ROOT + !(installedApp?.installType == InstallType.MOUNT && !viewModel.rootInstaller.hasRootAccess()), + alreadyPatched = installedApp != null && installedApp.installType != InstallType.MOUNT ) } } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppInfoViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppInfoViewModel.kt index 7e610f55..93e2cb74 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppInfoViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppInfoViewModel.kt @@ -78,7 +78,7 @@ class InstalledAppInfoViewModel( when (installedApp.installType) { InstallType.DEFAULT -> pm.uninstallPackage(installedApp.currentPackageName) - InstallType.ROOT -> viewModelScope.launch { + InstallType.MOUNT -> viewModelScope.launch { rootInstaller.uninstall(installedApp.currentPackageName) installedAppRepository.delete(installedApp) onBackClick() diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppsViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppsViewModel.kt index 27bec4c4..42ad08c7 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppsViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/InstalledAppsViewModel.kt @@ -30,7 +30,7 @@ class InstalledAppsViewModel( packageInfoMap[installedApp.currentPackageName] = withContext(Dispatchers.IO) { try { if ( - installedApp.installType == InstallType.ROOT && !rootInstaller.isAppInstalled(installedApp.currentPackageName) + installedApp.installType == InstallType.MOUNT && !rootInstaller.isAppInstalled(installedApp.currentPackageName) ) { installedAppsRepository.delete(installedApp) return@withContext null @@ -39,7 +39,7 @@ class InstalledAppsViewModel( val packageInfo = pm.getPackageInfo(installedApp.currentPackageName) - if (packageInfo == null && installedApp.installType != InstallType.ROOT) { + if (packageInfo == null && installedApp.installType != InstallType.MOUNT) { installedAppsRepository.delete(installedApp) return@withContext null } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt index ae7f95b9..a63feed7 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt @@ -77,7 +77,7 @@ class PatcherViewModel( override fun install() { // Since this is a package installer status dialog, - // InstallType.ROOT is never used here. + // InstallType.MOUNT is never used here. install(InstallType.DEFAULT) } } @@ -230,7 +230,7 @@ class PatcherViewModel( app.unregisterReceiver(installerBroadcastReceiver) workManager.cancelWorkById(patcherWorkerId) - if (input.selectedApp is SelectedApp.Installed && installedApp?.installType == InstallType.ROOT) { + if (input.selectedApp is SelectedApp.Installed && installedApp?.installType == InstallType.MOUNT) { GlobalScope.launch(Dispatchers.Main) { uiSafe(app, R.string.failed_to_mount, "Failed to mount") { withTimeout(Duration.ofMinutes(1L)) { @@ -243,6 +243,8 @@ class PatcherViewModel( tempDir.deleteRecursively() } + fun isDeviceRooted() = rootInstaller.isDeviceRooted() + fun export(uri: Uri?) = viewModelScope.launch { uri?.let { withContext(Dispatchers.IO) { @@ -301,7 +303,7 @@ class PatcherViewModel( pmInstallStarted = true } - InstallType.ROOT -> { + InstallType.MOUNT -> { try { // Check for base APK, first check if the app is already installed if (existingPackageInfo == null) { @@ -332,7 +334,7 @@ class PatcherViewModel( packageName, packageName, input.selectedApp.version, - InstallType.ROOT, + InstallType.MOUNT, input.selectedPatches ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5b6c6d93..ffcfc9fd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -223,7 +223,7 @@ Applied patches View applied patches Default - Root + Mount Mounted Not mounted Mount