From 6bd70b2d64a4163fc9280c793929d08029ce15ac Mon Sep 17 00:00:00 2001 From: Jman-Github <128645077+Jman-Github@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:59:04 -0400 Subject: [PATCH] fix(patcher): prevent ReVanced 21 and 22 process startup crashes --- api/DEV-CHANGELOG.md | 1 + .../manager/util/BuildProfileContextTest.kt | 39 +++++++++++++++++++ .../urv/manager/util/BuildProfileContext.kt | 10 +++-- 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 app/src/androidTest/java/app/urv/manager/util/BuildProfileContextTest.kt diff --git a/api/DEV-CHANGELOG.md b/api/DEV-CHANGELOG.md index 8e4d3a5f3..8d677c38b 100644 --- a/api/DEV-CHANGELOG.md +++ b/api/DEV-CHANGELOG.md @@ -28,6 +28,7 @@ - Fixed returning from a cancelled local APK patch leaving the app name and icon blank when the patcher's temporary input had already been deleted https://github.com/Jman-Github/Universal-ReVanced-Manager/issues/665 - Fixed issues with remote patch bundles when using GitHub or GitLab URLs sometimes not detecting prereleases correctly - Fixed incomplete patch bundle changelogs and missing history entries, including hidden release notes, overwritten descriptions, mixed release channels, and refresh errors not appearing when cached history is available +- Fixed ReVanced 21 and 22 patching failing before patches are applied when using process mode # CI diff --git a/app/src/androidTest/java/app/urv/manager/util/BuildProfileContextTest.kt b/app/src/androidTest/java/app/urv/manager/util/BuildProfileContextTest.kt new file mode 100644 index 000000000..6dc647ddf --- /dev/null +++ b/app/src/androidTest/java/app/urv/manager/util/BuildProfileContextTest.kt @@ -0,0 +1,39 @@ +package app.urv.manager.util + +import android.content.Context +import android.content.ContextWrapper +import androidx.test.platform.app.InstrumentationRegistry +import app.universal.revanced.manager.BuildConfig +import java.io.File +import org.junit.Assert.assertEquals +import org.junit.Assert.assertSame +import org.junit.Test + +class BuildProfileContextTest { + @Test + fun packageContextWithoutApplicationUsesSelectedStorage() { + val base = InstrumentationRegistry.getInstrumentation().targetContext + val packageContext = object : ContextWrapper(base) { + override fun getApplicationContext(): Context? = null + } + val selected = packageContext.managerStorageContext + val expected = if (BuildConfig.IS_PR_TEST_BUILD) { + File(base.codeCacheDir, "$PR_PROFILE_DIRECTORY/$PR_SCHEMA_DIRECTORY") + } else { + base.codeCacheDir + } + assertEquals(expected, selected.codeCacheDir) + assertSame(selected, selected.managerStorageContext) + assertSame(selected, BuildProfileContext.wrap(selected)) + } + + @Test + fun existingApplicationContextKeepsItsStorageProfile() { + val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext + val component = object : ContextWrapper(application) { + override fun getApplicationContext(): Context = application + override fun getCodeCacheDir(): File = error("Component storage must not be used") + } + assertSame(application, component.managerStorageContext) + } +} diff --git a/app/src/main/java/app/urv/manager/util/BuildProfileContext.kt b/app/src/main/java/app/urv/manager/util/BuildProfileContext.kt index a1bcfe12a..781659ad2 100644 --- a/app/src/main/java/app/urv/manager/util/BuildProfileContext.kt +++ b/app/src/main/java/app/urv/manager/util/BuildProfileContext.kt @@ -83,7 +83,7 @@ class BuildProfileContext(base: Context) : ContextWrapper(base) { companion object { fun wrap(context: Context): Context = - if (BuildConfig.IS_PR_TEST_BUILD) BuildProfileContext(context) else context + if (BuildConfig.IS_PR_TEST_BUILD && context !is BuildProfileContext) BuildProfileContext(context) else context } } @@ -91,8 +91,12 @@ internal const val PR_PROFILE_DIRECTORY = "pr_profile" internal val PR_SCHEMA_DIRECTORY = "schema-${BuildConfig.DATABASE_VERSION}" internal fun prPreferenceName(name: String): String = "pr_profile_${BuildConfig.DATABASE_VERSION}_$name" -/** Contexts belonging to activities/providers still have the platform's unscoped paths. */ -val Context.managerStorageContext: Context get() = applicationContext +/** + * Activities/providers use the Application's selected storage profile. Standalone app_process + * package contexts have no Application, so select the profile directly for those contexts. + */ +val Context.managerStorageContext: Context + get() = applicationContext ?: BuildProfileContext.wrap(this) /** Used by the storage screen instead of applicationInfo.dataDir, which is always package-wide. */ val Context.managerStorageRoot: File get() =