diff --git a/src/main/kotlin/com/looker/droidify/installer/DefaultInstaller.kt b/src/main/kotlin/com/looker/droidify/installer/DefaultInstaller.kt index 821ab599..00819462 100644 --- a/src/main/kotlin/com/looker/droidify/installer/DefaultInstaller.kt +++ b/src/main/kotlin/com/looker/droidify/installer/DefaultInstaller.kt @@ -13,6 +13,18 @@ import java.io.File class DefaultInstaller(context: Context) : BaseInstaller(context) { private val sessionInstaller = context.packageManager.packageInstaller + private val intent = Intent(context, InstallerService::class.java) + + companion object { + val flags = if (Android.sdk(31)) PendingIntent.FLAG_MUTABLE else 0 + val sessionParams = SessionParams(SessionParams.MODE_FULL_INSTALL) + } + + init { + if (Android.sdk(31)) { + sessionParams.setRequireUserAction(SessionParams.USER_ACTION_NOT_REQUIRED) + } + } override suspend fun install(cacheFileName: String) { val cacheFile = Cache.getReleaseFile(context, cacheFileName) @@ -30,11 +42,6 @@ class DefaultInstaller(context: Context) : BaseInstaller(context) { override suspend fun uninstall(packageName: String) = mDefaultUninstaller(packageName) private fun mDefaultInstaller(cacheFile: File) { - val sessionParams = SessionParams(SessionParams.MODE_FULL_INSTALL) - - if (Android.sdk(31)) { - sessionParams.setRequireUserAction(SessionParams.USER_ACTION_NOT_REQUIRED) - } val id = sessionInstaller.createSession(sessionParams) @@ -47,10 +54,6 @@ class DefaultInstaller(context: Context) : BaseInstaller(context) { } } - val intent = Intent(context, InstallerService::class.java) - - val flags = if (Android.sdk(31)) PendingIntent.FLAG_MUTABLE else 0 - val pendingIntent = PendingIntent.getService(context, id, intent, flags) session.commit(pendingIntent.intentSender) @@ -59,11 +62,8 @@ class DefaultInstaller(context: Context) : BaseInstaller(context) { } private suspend fun mDefaultUninstaller(packageName: String) { - val intent = Intent(context, InstallerService::class.java) intent.putExtra(InstallerService.KEY_ACTION, InstallerService.ACTION_UNINSTALL) - val flags = if (Android.sdk(31)) PendingIntent.FLAG_MUTABLE else 0 - val pendingIntent = PendingIntent.getService(context, -1, intent, flags) withContext(Dispatchers.Default) { diff --git a/src/main/kotlin/com/looker/droidify/installer/RootInstaller.kt b/src/main/kotlin/com/looker/droidify/installer/RootInstaller.kt index fe1cd1b9..0587554b 100644 --- a/src/main/kotlin/com/looker/droidify/installer/RootInstaller.kt +++ b/src/main/kotlin/com/looker/droidify/installer/RootInstaller.kt @@ -8,6 +8,51 @@ import kotlinx.coroutines.withContext import java.io.File class RootInstaller(context: Context) : BaseInstaller(context) { + + companion object { + private val getCurrentUserState: String = + Shell.su("dumpsys activity | grep -E \"mUserLru\"") + .exec().out[0].trim() + .removePrefix("mUserLru: [").removeSuffix("]") + + private val String.quote + get() = "\"${this.replace(Regex("""[\\$"`]""")) { c -> "\\${c.value}" }}\"" + + private val getUtilBoxPath: String + get() { + listOf("toybox", "busybox").forEach { + val shellResult = Shell.su("which $it").exec() + if (shellResult.out.isNotEmpty()) { + val utilBoxPath = shellResult.out.joinToString("") + if (utilBoxPath.isNotEmpty()) return utilBoxPath.quote + } + } + return "" + } + + val File.install + get() = String.format( + ROOT_INSTALL_PACKAGE, + absolutePath, + getCurrentUserState, + length() + ) + + val String.uninstall + get() = String.format( + ROOT_UNINSTALL_PACKAGE, + getCurrentUserState, + this + ) + + val File.deletePackage + get() = String.format( + DELETE_PACKAGE, + getUtilBoxPath, + absolutePath.quote + ) + } + override suspend fun install(cacheFileName: String) { val cacheFile = Cache.getReleaseFile(context, cacheFileName) mRootInstaller(cacheFile) @@ -23,47 +68,15 @@ class RootInstaller(context: Context) : BaseInstaller(context) { override suspend fun uninstall(packageName: String) = mRootUninstaller(packageName) private suspend fun mRootInstaller(cacheFile: File) { - val installCommand = - String.format( - ROOT_INSTALL_PACKAGE, - cacheFile.absolutePath, - getCurrentUserState, - cacheFile.length() - ) - val deleteCommand = - String.format( - DELETE_PACKAGE, - getUtilBoxPath, - cacheFile.absolutePath.quote - ) withContext(Dispatchers.Default) { - Shell.su(installCommand).submit { if (it.isSuccess) Shell.su(deleteCommand).submit() } + Shell.su(cacheFile.install) + .submit { if (it.isSuccess) Shell.su(cacheFile.deletePackage).submit() } } } private suspend fun mRootUninstaller(packageName: String) { - val uninstallCommand = - String.format(ROOT_UNINSTALL_PACKAGE, getCurrentUserState, packageName) - withContext(Dispatchers.Default) { Shell.su(uninstallCommand).submit() } - } - - private val getCurrentUserState: String = - Shell.su("dumpsys activity | grep -E \"mUserLru\"") - .exec().out[0].trim() - .removePrefix("mUserLru: [").removeSuffix("]") - - private val String.quote - get() = "\"${this.replace(Regex("""[\\$"`]""")) { c -> "\\${c.value}" }}\"" - - private val getUtilBoxPath: String - get() { - listOf("toybox", "busybox").forEach { - val shellResult = Shell.su("which $it").exec() - if (shellResult.out.isNotEmpty()) { - val utilBoxPath = shellResult.out.joinToString("") - if (utilBoxPath.isNotEmpty()) return utilBoxPath.quote - } - } - return "" + withContext(Dispatchers.Default) { + Shell.su(packageName.uninstall).submit() } + } } \ No newline at end of file