Compare commits

...

24 Commits

Author SHA1 Message Date
brosssh
7db4942bba fix: Make ShellCommandRunner run without root
Currently, every command run by a ShellCommandRunner will be run with su (root required). With this PR, root will only be required from a RootInstaller.
Also remove latest \n from shell output
2025-05-29 10:19:16 +02:00
semantic-release-bot
5df2bb81bf chore: Release v3.2.0-dev.1 [skip ci]
# [3.2.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.1.1-dev.1...v3.2.0-dev.1) (2025-05-27)

### Features

* Request the update ownership enforcement ([#71](https://github.com/ReVanced/revanced-library/issues/71)) ([be0f6bf](be0f6bf247))
2025-05-27 13:37:00 +00:00
Brosssh
be0f6bf247 feat: Request the update ownership enforcement (#71)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2025-05-27 15:31:09 +02:00
semantic-release-bot
9d060c188f chore: Release v3.1.1-dev.1 [skip ci]
## [3.1.1-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.1.0...v3.1.1-dev.1) (2025-05-02)

### Bug Fixes

* Interpret package name as a string instead of Regex when using grep  ([#68](https://github.com/ReVanced/revanced-library/issues/68)) ([254f36d](254f36d03c))
2025-05-02 13:07:51 +00:00
laur89
254f36d03c fix: Interpret package name as a string instead of Regex when using grep (#68) 2025-05-02 15:04:34 +02:00
semantic-release-bot
4065c87d5f chore: Release v3.1.0 [skip ci]
# [3.1.0](https://github.com/ReVanced/revanced-library/compare/v3.0.2...v3.1.0) (2024-11-27)

### Bug Fixes

* Detect if app is installed by fixing inversion ([649f06b](649f06b19d))

### Features

* Warn when option could not be set because the option does not exist ([7ec6504](7ec6504619))
2024-11-27 21:47:55 +00:00
oSumAtrIX
be8d7bf643 chore: Merge branch dev to main (#65) 2024-11-27 22:45:14 +01:00
semantic-release-bot
2328902b6b chore: Release v3.1.0-dev.1 [skip ci]
# [3.1.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.3-dev.1...v3.1.0-dev.1) (2024-11-25)

### Features

* Warn when option could not be set because the option does not exist ([7ec6504](7ec6504619))
2024-11-25 21:30:09 +00:00
oSumAtrIX
7ec6504619 feat: Warn when option could not be set because the option does not exist 2024-11-25 22:23:31 +01:00
semantic-release-bot
e7a98b5795 chore: Release v3.0.3-dev.1 [skip ci]
## [3.0.3-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.2...v3.0.3-dev.1) (2024-11-11)

### Bug Fixes

* Detect if app is installed by fixing inversion ([649f06b](649f06b19d))
2024-11-11 22:32:39 +00:00
oSumAtrIX
649f06b19d fix: Detect if app is installed by fixing inversion 2024-11-11 23:29:43 +01:00
semantic-release-bot
cace51700a chore: Release v3.0.2 [skip ci]
## [3.0.2](https://github.com/ReVanced/revanced-library/compare/v3.0.1...v3.0.2) (2024-11-05)
2024-11-05 18:44:21 +00:00
oSumAtrIX
91cefc8598 chore: Merge branch dev to main (#63) 2024-11-05 19:41:48 +01:00
semantic-release-bot
735c1e39cd chore: Release v3.0.2-dev.1 [skip ci]
## [3.0.2-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.1...v3.0.2-dev.1) (2024-11-05)
2024-11-05 18:39:39 +00:00
oSumAtrIX
84cc315541 build(Needs bump): Bump dependencies 2024-11-05 19:37:09 +01:00
semantic-release-bot
4fe9304570 chore: Release v3.0.1 [skip ci]
## [3.0.1](https://github.com/ReVanced/revanced-library/compare/v3.0.0...v3.0.1) (2024-10-13)

### Bug Fixes

* Serialize compatible packages as a map instead of a set of pairs. ([737e272](737e272481))
2024-10-13 01:55:25 +00:00
oSumAtrIX
8bb41be8fc chore: Merge branch dev to main (#62) 2024-10-13 03:52:36 +02:00
semantic-release-bot
4b8ac026c3 chore: Release v3.0.1-dev.3 [skip ci]
## [3.0.1-dev.3](https://github.com/ReVanced/revanced-library/compare/v3.0.1-dev.2...v3.0.1-dev.3) (2024-10-06)
2024-10-06 01:27:57 +00:00
oSumAtrIX
557b6035f8 build(Needs bump): Bump dependencies 2024-10-06 03:25:03 +02:00
oSumAtrIX
bfc5394b4e refactor: Indent code 2024-10-01 17:30:14 +02:00
semantic-release-bot
5b1cf1f190 chore: Release v3.0.1-dev.2 [skip ci]
## [3.0.1-dev.2](https://github.com/ReVanced/revanced-library/compare/v3.0.1-dev.1...v3.0.1-dev.2) (2024-10-01)
2024-10-01 15:09:29 +00:00
oSumAtrIX
dd5c37ddec ci: Use permissions and regular GitHub token instead of PAT 2024-10-01 17:07:05 +02:00
oSumAtrIX
9adccc04dd build(Needs bump): Update dependencies 2024-09-30 23:21:45 +02:00
oSumAtrIX
ed94d29461 ci: Adjust release commit message 2024-09-30 22:34:24 +02:00
16 changed files with 1977 additions and 1175 deletions

View File

@@ -10,6 +10,9 @@ on:
jobs: jobs:
release: release:
name: Release name: Release
permissions:
contents: write
packages: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
@@ -49,5 +52,5 @@ jobs:
- name: Release - name: Release
env: env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm exec semantic-release run: npm exec semantic-release

View File

@@ -23,7 +23,8 @@
"assets": [ "assets": [
"CHANGELOG.md", "CHANGELOG.md",
"gradle.properties" "gradle.properties"
] ],
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
} }
], ],
[ [

View File

@@ -1,3 +1,58 @@
# [3.2.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.1.1-dev.1...v3.2.0-dev.1) (2025-05-27)
### Features
* Request the update ownership enforcement ([#71](https://github.com/ReVanced/revanced-library/issues/71)) ([be0f6bf](https://github.com/ReVanced/revanced-library/commit/be0f6bf247461d16fbf649a9f2dc6facbb5b0c93))
## [3.1.1-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.1.0...v3.1.1-dev.1) (2025-05-02)
### Bug Fixes
* Interpret package name as a string instead of Regex when using grep ([#68](https://github.com/ReVanced/revanced-library/issues/68)) ([254f36d](https://github.com/ReVanced/revanced-library/commit/254f36d03cc8fd3e2508a5e8f69bb5c8e1eb9775))
# [3.1.0](https://github.com/ReVanced/revanced-library/compare/v3.0.2...v3.1.0) (2024-11-27)
### Bug Fixes
* Detect if app is installed by fixing inversion ([649f06b](https://github.com/ReVanced/revanced-library/commit/649f06b19dd4d2a3f3216a0b3ea947b9fe0d475f))
### Features
* Warn when option could not be set because the option does not exist ([7ec6504](https://github.com/ReVanced/revanced-library/commit/7ec650461935faf2a8fbb667db3cf137157b70b5))
# [3.1.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.3-dev.1...v3.1.0-dev.1) (2024-11-25)
### Features
* Warn when option could not be set because the option does not exist ([7ec6504](https://github.com/ReVanced/revanced-library/commit/7ec650461935faf2a8fbb667db3cf137157b70b5))
## [3.0.3-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.2...v3.0.3-dev.1) (2024-11-11)
### Bug Fixes
* Detect if app is installed by fixing inversion ([649f06b](https://github.com/ReVanced/revanced-library/commit/649f06b19dd4d2a3f3216a0b3ea947b9fe0d475f))
## [3.0.2](https://github.com/ReVanced/revanced-library/compare/v3.0.1...v3.0.2) (2024-11-05)
## [3.0.2-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.1...v3.0.2-dev.1) (2024-11-05)
## [3.0.1](https://github.com/ReVanced/revanced-library/compare/v3.0.0...v3.0.1) (2024-10-13)
### Bug Fixes
* Serialize compatible packages as a map instead of a set of pairs. ([737e272](https://github.com/ReVanced/revanced-library/commit/737e272481fe3b0b4c89233d139b5e657a0c1de4))
## [3.0.1-dev.3](https://github.com/ReVanced/revanced-library/compare/v3.0.1-dev.2...v3.0.1-dev.3) (2024-10-06)
## [3.0.1-dev.2](https://github.com/ReVanced/revanced-library/compare/v3.0.1-dev.1...v3.0.1-dev.2) (2024-10-01)
## [3.0.1-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.0...v3.0.1-dev.1) (2024-08-16) ## [3.0.1-dev.1](https://github.com/ReVanced/revanced-library/compare/v3.0.0...v3.0.1-dev.1) (2024-08-16)

View File

@@ -54,7 +54,7 @@ kotlin {
commonMain.dependencies { commonMain.dependencies {
implementation(libs.apksig) implementation(libs.apksig)
implementation(libs.apkzlib) implementation(libs.apkzlib)
implementation(libs.bcpkix.jdk15on) implementation(libs.bcpkix.jdk18on)
implementation(libs.guava) implementation(libs.guava)
implementation(libs.jadb) implementation(libs.jadb)
implementation(libs.kotlin.reflect) implementation(libs.kotlin.reflect)

View File

@@ -1,4 +1,4 @@
version = 3.0.1-dev.1 version = 3.2.0-dev.1
#Gradle #Gradle
org.gradle.jvmargs = -Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="-Xmx2048M" org.gradle.jvmargs = -Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="-Xmx2048M"
org.gradle.caching = true org.gradle.caching = true

View File

@@ -1,20 +1,20 @@
[versions] [versions]
android = "8.5.1" android = "8.5.2"
bcpkix-jdk15on = "1.70" bcpkix-jdk18on = "1.77"
binary-compatibility-validator = "0.15.1" binary-compatibility-validator = "0.15.1"
core-ktx = "1.13.1" core-ktx = "1.15.0"
guava = "33.0.0-jre" guava = "33.2.1-jre"
jadb = "1.2.1" jadb = "1.2.1.1"
kotlin = "2.0.0" kotlin = "2.0.20"
kotlinx-coroutines = "1.8.1" kotlinx-coroutines = "1.8.1"
kotlinx-serialization = "1.7.1" kotlinx-serialization = "1.7.1"
libsu = "5.2.2" libsu = "5.2.2"
revanced-patcher = "20.0.0" revanced-patcher = "21.0.0"
[libraries] [libraries]
apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "android" } apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "android" }
apksig = { module = "com.android.tools.build:apksig", version.ref = "android" } apksig = { module = "com.android.tools.build:apksig", version.ref = "android" }
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkix-jdk15on" } bcpkix-jdk18on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bcpkix-jdk18on" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
guava = { module = "com.google.guava:guava", version.ref = "guava" } guava = { module = "com.google.guava:guava", version.ref = "guava" }
jadb = { module = "app.revanced:jadb", version.ref = "jadb" } # Fork with Shell v2 support. jadb = { module = "app.revanced:jadb", version.ref = "jadb" } # Fork with Shell v2 support.

3002
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"@saithodev/semantic-release-backmerge": "^4.0.1", "@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.9.1", "gradle-semantic-release-plugin": "^1.10.1",
"semantic-release": "^23.0.2" "semantic-release": "^24.1.2"
} }
} }

View File

@@ -8,6 +8,7 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import app.revanced.library.installation.installer.Installer.Apk import app.revanced.library.installation.installer.Installer.Apk
import java.io.Closeable import java.io.Closeable
@@ -85,10 +86,13 @@ class LocalInstaller(
override fun close() = context.unregisterReceiver(broadcastReceiver) override fun close() = context.unregisterReceiver(broadcastReceiver)
@SuppressLint("MissingPermission")
companion object { companion object {
private val sessionParams = PackageInstaller.SessionParams( private val sessionParams = PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL, PackageInstaller.SessionParams.MODE_FULL_INSTALL,
).apply { ).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
setRequestUpdateOwnership(true)
setInstallReason(PackageManager.INSTALL_REASON_USER) setInstallReason(PackageManager.INSTALL_REASON_USER)
} }

View File

@@ -82,7 +82,7 @@ object ApkUtils {
// Delete resources that were staged for deletion. // Delete resources that were staged for deletion.
if (resources.deleteResources.isNotEmpty()) { if (resources.deleteResources.isNotEmpty()) {
targetApkZFile.entries().filter { entry -> targetApkZFile.entries().filter { entry ->
resources.deleteResources.any { shouldDelete -> shouldDelete(entry.centralDirectoryHeader.name) } entry.centralDirectoryHeader.name in resources.deleteResources
}.forEach(StoredEntry::delete) }.forEach(StoredEntry::delete)
} }
} }

View File

@@ -19,11 +19,16 @@ private val logger = Logger.getLogger("Options")
* @param options The options to set. The key is the patch name and the value is a map of option keys to option values. * @param options The options to set. The key is the patch name and the value is a map of option keys to option values.
*/ */
fun Set<Patch<*>>.setOptions(options: PatchesOptions) = filter { it.name != null }.forEach { patch -> fun Set<Patch<*>>.setOptions(options: PatchesOptions) = filter { it.name != null }.forEach { patch ->
val patchOptions = options[patch.name] ?: return@forEach options[patch.name]?.forEach setOption@{ (optionKey, optionValue) ->
if (optionKey !in patch.options) {
return@setOption logger.warning(
"Could not set option for the \"${patch.name}\" patch because " +
"option with key \"${optionKey}\" does not exist",
)
}
patch.options.forEach option@{ option ->
try { try {
patch.options[option.key] = patchOptions[option.key] ?: return@option patch.options[optionKey] = optionValue
} catch (e: OptionException) { } catch (e: OptionException) {
logger.warning("Could not set option value for the \"${patch.name}\" patch: ${e.message}") logger.warning("Could not set option value for the \"${patch.name}\" patch: ${e.message}")
} }

View File

@@ -35,7 +35,7 @@ class AdbShellCommandRunner : ShellCommandRunner {
override fun runCommand(command: String) = device.shellProcessBuilder(command).start().let { process -> override fun runCommand(command: String) = device.shellProcessBuilder(command).start().let { process ->
object : RunResult { object : RunResult {
override val exitCode by lazy { process.waitFor() } override val exitCode by lazy { process.waitFor() }
override val output by lazy { process.inputStream.bufferedReader().readText() } override val output by lazy { process.inputStream.bufferedReader().readText().removeSuffix("\n") }
override val error by lazy { process.errorStream.bufferedReader().readText() } override val error by lazy { process.errorStream.bufferedReader().readText() }
override fun waitFor() { override fun waitFor() {
@@ -44,7 +44,7 @@ class AdbShellCommandRunner : ShellCommandRunner {
} }
} }
override fun hasRootPermission(): Boolean = invoke("whoami").exitCode == 0 override fun hasRootPermission(): Boolean = invoke("su -c whoami").exitCode == 0
override fun write(content: InputStream, targetFilePath: String) = override fun write(content: InputStream, targetFilePath: String) =
device.push(content, System.currentTimeMillis(), 644, RemoteFile(targetFilePath)) device.push(content, System.currentTimeMillis(), 644, RemoteFile(targetFilePath))

View File

@@ -55,5 +55,5 @@ abstract class ShellCommandRunner internal constructor() {
*/ */
internal operator fun invoke( internal operator fun invoke(
command: String, command: String,
) = runCommand("su -c \'$command\'") ) = runCommand(command)
} }

View File

@@ -1,11 +1,13 @@
package app.revanced.library.installation.installer package app.revanced.library.installation.installer
import app.revanced.library.installation.command.AdbShellCommandRunner import app.revanced.library.installation.command.AdbShellCommandRunner
import app.revanced.library.installation.command.ShellCommandRunner
import app.revanced.library.installation.installer.Constants.GET_SDK_VERSION
import app.revanced.library.installation.installer.Constants.INSTALLED_APK_PATH import app.revanced.library.installation.installer.Constants.INSTALLED_APK_PATH
import app.revanced.library.installation.installer.Installer.Apk
import se.vidstige.jadb.JadbException import se.vidstige.jadb.JadbException
import se.vidstige.jadb.managers.Package import se.vidstige.jadb.managers.Package
import se.vidstige.jadb.managers.PackageManager import se.vidstige.jadb.managers.PackageManager
import se.vidstige.jadb.managers.PackageManager.UPDATE_OWNERSHIP
/** /**
* [AdbInstaller] for installing and uninstalling [Apk] files using ADB. * [AdbInstaller] for installing and uninstalling [Apk] files using ADB.
@@ -17,18 +19,23 @@ import se.vidstige.jadb.managers.PackageManager
class AdbInstaller( class AdbInstaller(
deviceSerial: String? = null, deviceSerial: String? = null,
) : Installer<AdbInstallerResult, Installation>() { ) : Installer<AdbInstallerResult, Installation>() {
private val device = getDevice(deviceSerial, logger) private val shellCommandRunner: ShellCommandRunner
private val adbShellCommandRunner = AdbShellCommandRunner(device) private val packageManager: PackageManager
private val packageManager = PackageManager(device)
init { init {
val device = getDevice(deviceSerial, logger)
shellCommandRunner = AdbShellCommandRunner(device)
packageManager = PackageManager(device)
logger.fine("Connected to $deviceSerial") logger.fine("Connected to $deviceSerial")
} }
override suspend fun install(apk: Apk): AdbInstallerResult { override suspend fun install(apk: Apk): AdbInstallerResult {
logger.info("Installing ${apk.file.name}") return runPackageManager {
val sdkVersion = shellCommandRunner(GET_SDK_VERSION).output.toInt()
return runPackageManager { install(apk.file) } if (sdkVersion < 34) install(apk.file)
else installWithOptions(apk.file, listOf(UPDATE_OWNERSHIP))
}
} }
override suspend fun uninstall(packageName: String): AdbInstallerResult { override suspend fun uninstall(packageName: String): AdbInstallerResult {
@@ -39,7 +46,7 @@ class AdbInstaller(
override suspend fun getInstallation(packageName: String): Installation? = packageManager.packages.find { override suspend fun getInstallation(packageName: String): Installation? = packageManager.packages.find {
it.toString() == packageName it.toString() == packageName
}?.let { Installation(adbShellCommandRunner(INSTALLED_APK_PATH).output) } }?.let { Installation(shellCommandRunner(INSTALLED_APK_PATH).output) }
private fun runPackageManager(block: PackageManager.() -> Unit) = try { private fun runPackageManager(block: PackageManager.() -> Unit) = try {
packageManager.run(block) packageManager.run(block)

View File

@@ -4,26 +4,28 @@ package app.revanced.library.installation.installer
internal object Constants { internal object Constants {
const val PLACEHOLDER = "PLACEHOLDER" const val PLACEHOLDER = "PLACEHOLDER"
const val SELINUX_CONTEXT = "u:object_r:apk_data_file:s0"
const val TMP_FILE_PATH = "/data/local/tmp/revanced.tmp" const val TMP_FILE_PATH = "/data/local/tmp/revanced.tmp"
const val MOUNT_PATH = "/data/adb/revanced/" const val MOUNT_PATH = "/data/adb/revanced/"
const val MOUNTED_APK_PATH = "$MOUNT_PATH$PLACEHOLDER.apk" const val MOUNTED_APK_PATH = "$MOUNT_PATH$PLACEHOLDER.apk"
const val MOUNT_SCRIPT_PATH = "/data/adb/service.d/mount_revanced_$PLACEHOLDER.sh" const val MOUNT_SCRIPT_PATH = "/data/adb/service.d/mount_revanced_$PLACEHOLDER.sh"
const val EXISTS = "[[ -f $PLACEHOLDER ]] || exit 1" const val EXISTS = "[[ -f $PLACEHOLDER ]] || exit 1"
const val MOUNT_GREP = "grep $PLACEHOLDER /proc/mounts" const val MOUNT_GREP = "grep -F $PLACEHOLDER /proc/mounts"
const val DELETE = "rm -rf $PLACEHOLDER" const val DELETE = "rm -rf $PLACEHOLDER"
const val CREATE_DIR = "mkdir -p" const val CREATE_DIR = "mkdir -p"
const val RESTART = "am start -S $PLACEHOLDER" const val RESTART = "am start -S $PLACEHOLDER"
const val KILL = "am force-stop $PLACEHOLDER" const val KILL = "am force-stop $PLACEHOLDER"
const val INSTALLED_APK_PATH = "pm path $PLACEHOLDER" const val INSTALLED_APK_PATH = "pm path $PLACEHOLDER"
const val CREATE_INSTALLATION_PATH = "$CREATE_DIR $MOUNT_PATH" const val CREATE_INSTALLATION_PATH = "$CREATE_DIR $MOUNT_PATH"
const val GET_SDK_VERSION = "getprop ro.build.version.sdk"
const val MOUNT_APK = const val MOUNT_APK =
"base_path=\"$MOUNTED_APK_PATH\" && " + "base_path=\"$MOUNTED_APK_PATH\" && " +
"mv $TMP_FILE_PATH \$base_path && " + "mv $TMP_FILE_PATH \$base_path && " +
"chmod 644 \$base_path && " + "chmod 644 \$base_path && " +
"chown system:system \$base_path && " + "chown system:system \$base_path && " +
"chcon u:object_r:apk_data_file:s0 \$base_path" "chcon $SELINUX_CONTEXT \$base_path"
const val UMOUNT = const val UMOUNT =
"grep $PLACEHOLDER /proc/mounts | " + "grep $PLACEHOLDER /proc/mounts | " +
@@ -52,7 +54,7 @@ internal object Constants {
base_path="$MOUNTED_APK_PATH" base_path="$MOUNTED_APK_PATH"
chcon u:object_r:apk_data_file:s0 ${'$'}base_path chcon $SELINUX_CONTEXT ${'$'}base_path
# Use Magisk mirror, if possible. # Use Magisk mirror, if possible.
if command -v magisk &> /dev/null; then if command -v magisk &> /dev/null; then

View File

@@ -100,7 +100,7 @@ abstract class RootInstaller internal constructor(
/** /**
* Runs a command on the device. * Runs a command on the device.
*/ */
protected operator fun String.invoke() = shellCommandRunner(this) protected operator fun String.invoke() = shellCommandRunner("su -c \'$this\'")
/** /**
* Moves the given file to the given [targetFilePath]. * Moves the given file to the given [targetFilePath].
@@ -122,13 +122,12 @@ abstract class RootInstaller internal constructor(
* @throws FailedToFindInstalledPackageException If the package is not installed. * @throws FailedToFindInstalledPackageException If the package is not installed.
*/ */
private fun String.assertInstalled() { private fun String.assertInstalled() {
if (INSTALLED_APK_PATH(this)().output.isNotEmpty()) { if (INSTALLED_APK_PATH(this)().output.isEmpty()) {
throw FailedToFindInstalledPackageException(this) throw FailedToFindInstalledPackageException(this)
} }
} }
internal class FailedToFindInstalledPackageException internal constructor(packageName: String) : internal class FailedToFindInstalledPackageException internal constructor(packageName: String) : Exception("Failed to find installed package \"$packageName\" because no activity was found")
Exception("Failed to find installed package \"$packageName\" because no activity was found")
internal class PackageNameRequiredException internal constructor() : Exception("Package name is required") internal class PackageNameRequiredException internal constructor() : Exception("Package name is required")
internal class NoRootPermissionException internal constructor() : Exception("No root permission") internal class NoRootPermissionException internal constructor() : Exception("No root permission")