From c3d858a5613a133352f6b140916d05de7f752771 Mon Sep 17 00:00:00 2001 From: NGB-Was-Taken <76197326+NGB-Was-Taken@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:01:38 +0545 Subject: [PATCH] Fix shizuku installer not updating installed extensions (#2697) Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> --- CHANGELOG.md | 1 + .../java/mihon/app/shizuku/ShellInterface.kt | 47 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eceff7cf5..a2904f814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co ## [Unreleased] ### Fixed - Fix reader tap zones triggering after scrolling is stopped by tapping ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#2680](https://github.com/mihonapp/mihon/pull/2680)) +- Fix shizuku installer not updating installed extensions ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#2697](https://github.com/mihonapp/mihon/pull/2697)) ## [v0.19.3] - 2025-11-07 ### Improved diff --git a/app/src/main/java/mihon/app/shizuku/ShellInterface.kt b/app/src/main/java/mihon/app/shizuku/ShellInterface.kt index 3326ff270..216f82b30 100644 --- a/app/src/main/java/mihon/app/shizuku/ShellInterface.kt +++ b/app/src/main/java/mihon/app/shizuku/ShellInterface.kt @@ -75,6 +75,12 @@ class ShellInterface : IShellInterface.Stub() { .invoke(pmInterface) val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL).apply { + val installFlags = this::class.java.getField("installFlags") + installFlags.set( + this, + installFlags.getInt(this) or REPLACE_EXISTING_INSTALL_FLAG, + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { setPackageSource(PackageInstaller.PACKAGE_SOURCE_STORE) } @@ -105,26 +111,27 @@ class ShellInterface : IShellInterface.Stub() { .getMethod("openSession", Int::class.java) .invoke(packageInstaller, sessionId) - ( - session::class.java.getMethod( - "openWrite", - String::class.java, - Long::class.java, - Long::class.java, - ).invoke(session, "extension", 0L, apk.length) as ParcelFileDescriptor - ).let { fd -> - val revocable = Class.forName("android.os.SystemProperties") - .getMethod("getBoolean", String::class.java, Boolean::class.java) - .invoke(null, "fw.revocable_fd", false) as Boolean + session::class.java.getMethod( + "openWrite", + String::class.java, + Long::class.java, + Long::class.java, + ) + .invoke(session, "extension", 0L, apk.length) + .let { it as ParcelFileDescriptor } + .let { fd -> + val revocable = Class.forName("android.os.SystemProperties") + .getMethod("getBoolean", String::class.java, Boolean::class.java) + .invoke(null, "fw.revocable_fd", false) as Boolean - if (revocable) { - ParcelFileDescriptor.AutoCloseOutputStream(fd) - } else { - Class.forName($$"android.os.FileBridge$FileBridgeOutputStream") - .getConstructor(ParcelFileDescriptor::class.java) - .newInstance(fd) as OutputStream + if (revocable) { + ParcelFileDescriptor.AutoCloseOutputStream(fd) + } else { + Class.forName($$"android.os.FileBridge$FileBridgeOutputStream") + .getConstructor(ParcelFileDescriptor::class.java) + .newInstance(fd) as OutputStream + } } - } .use { output -> apk.createInputStream().use { input -> input.copyTo(output) } } @@ -174,3 +181,7 @@ class ShellInterface : IShellInterface.Stub() { return shellContext.createPackageContext("com.android.shell", 0) } } + +// Constant hidden from the SDK +// https://cs.android.com/android/platform/superproject/main/+/512046e84bcc51cc241bc6599f83ab345e93ab12:frameworks/base/core/java/android/content/pm/PackageManager.java;l=1682-1689 +private const val REPLACE_EXISTING_INSTALL_FLAG = 0x00000002