Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.matrix.vector.daemon.data

import android.os.Process

/** Pure process matching rules shared by the daemon policy and local unit tests. */
object InlineHookProcessPolicy {
fun matchesSystemUiVirtualPackage(
configuredPackages: Set<String>,
processName: String,
uid: Int
): Boolean =
SYSTEM_UI_VIRTUAL_PACKAGE in configuredPackages &&
uid == Process.SYSTEM_UID &&
processName == SYSTEM_UI_PROCESS

fun matchesPackage(
expectedUid: Int,
actualUid: Int,
processName: String,
applicationProcessName: String?,
componentProcesses: Set<String>
): Boolean =
expectedUid == actualUid &&
(processName == applicationProcessName || processName in componentProcesses)

fun mayInvalidate(processName: String, uid: Int): Boolean =
uid != Process.SYSTEM_UID || processName != "system"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package org.matrix.vector.daemon.data
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase
import org.apache.commons.lang3.SerializationUtilsX
import org.matrix.vector.daemon.system.*

private const val TAG = "VectorPreferenceStore"
private const val INVALIDATE_ART_INLINE_HOOKS_KEY_PREFIX = "invalidate_art_inline_hooks:"
const val SYSTEM_UI_VIRTUAL_PACKAGE = "system"
const val SYSTEM_UI_PROCESS = "system:ui"

object PreferenceStore {

Expand Down Expand Up @@ -100,4 +104,56 @@ object PreferenceStore {
fun isScopeRequestBlocked(pkg: String): Boolean =
(getModulePrefs("lspd", 0, "config")["scope_request_blocked"] as? Set<*>)?.contains(pkg) ==
true

fun getInvalidateArtInlineHookPackages(): Set<String> {
return getModulePrefs("lspd", 0, "config")
.asSequence()
.filter { (key, value) ->
key.startsWith(INVALIDATE_ART_INLINE_HOOKS_KEY_PREFIX) && value == true
}
.map { (key, _) -> key.removePrefix(INVALIDATE_ART_INLINE_HOOKS_KEY_PREFIX) }
.filter { it.isNotBlank() }
.toSet()
}

/** Updates one package without replacing another Manager client's choices. */
fun setInvalidateArtInlineHooks(packageName: String, enabled: Boolean): Boolean {
val normalized = packageName.trim()
if (normalized.isEmpty()) return false
updateModulePref(
"lspd",
0,
"config",
INVALIDATE_ART_INLINE_HOOKS_KEY_PREFIX + normalized,
if (enabled) true else null)
return true
}

/**
* Resolves the configured package list against the actual process topology for this user.
* This deliberately avoids assuming that every Android process name starts with its package name.
*/
fun shouldInvalidateArtInlineHooks(processName: String, uid: Int): Boolean {
val configured = getInvalidateArtInlineHookPackages()
if (configured.isEmpty()) return false

if (InlineHookProcessPolicy.matchesSystemUiVirtualPackage(configured, processName, uid)) {
return true
}

val userId = uid / PER_USER_RANGE
return configured.any { packageName ->
if (packageName == SYSTEM_UI_VIRTUAL_PACKAGE) return@any false
val info =
packageManager?.getPackageInfoWithComponents(packageName, MATCH_ALL_FLAGS, userId)
?: return@any false
val applicationInfo = info.applicationInfo ?: return@any false
InlineHookProcessPolicy.matchesPackage(
expectedUid = applicationInfo.uid,
actualUid = uid,
processName = processName,
applicationProcessName = applicationInfo.processName,
componentProcesses = info.fetchProcesses())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import org.matrix.vector.ipc.IProcessChannel
import org.matrix.vector.ipc.IFrameworkService
import org.matrix.vector.daemon.data.ConfigCache
import org.matrix.vector.daemon.data.FileSystem
import org.matrix.vector.daemon.data.InlineHookProcessPolicy
import org.matrix.vector.daemon.data.PreferenceStore
import org.matrix.vector.daemon.system.FIRST_APPLICATION_UID
import org.matrix.vector.daemon.system.PER_USER_RANGE
import org.matrix.vector.daemon.utils.InstallerVerifier
Expand All @@ -29,6 +31,8 @@ const val DEX_TRANSACTION_CODE =
('_'.code shl 24) or ('D'.code shl 16) or ('E'.code shl 8) or 'X'.code
const val OBFUSCATION_MAP_TRANSACTION_CODE =
('_'.code shl 24) or ('O'.code shl 16) or ('B'.code shl 8) or 'F'.code
const val INVALIDATE_ART_INLINE_HOOKS_TRANSACTION_CODE =
('_'.code shl 24) or ('I'.code shl 16) or ('N'.code shl 8) or 'L'.code

/**
* What an injected process asks the framework for — this project's `IFrameworkService`.
Expand Down Expand Up @@ -241,6 +245,15 @@ object FrameworkService : IFrameworkService.Stub() {
}
return true
}
INVALIDATE_ART_INLINE_HOOKS_TRANSACTION_CODE -> {
val info = ensureRegistered()
val invalidate =
InlineHookProcessPolicy.mayInvalidate(info.processName, info.key.uid) &&
PreferenceStore.shouldInvalidateArtInlineHooks(info.processName, info.key.uid)
reply?.writeNoException()
reply?.writeInt(if (invalidate) 1 else 0)
return true
}
}
return super.onTransact(code, data, reply, flags)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ object ManagerService : IManagerService.Stub() {
if (isVerboseLogEnabled()) LogcatMonitor.startVerbose() else LogcatMonitor.stopVerbose()
}

override fun getInvalidateArtInlineHookPackages(): MutableList<String> =
PreferenceStore.getInvalidateArtInlineHookPackages().sorted().toMutableList()

override fun setInvalidateArtInlineHooks(packageName: String, enabled: Boolean): Boolean =
PreferenceStore.setInvalidateArtInlineHooks(packageName, enabled)

override fun getLogParts(verbose: Boolean): List<String> = FileSystem.listLogParts(verbose)

override fun getLogPart(verbose: Boolean, name: String): ParcelFileDescriptor? =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ class FakeManagerService(
real?.setVerboseLogEnabled(enabled)
}

override fun getInvalidateArtInlineHookPackages(): MutableList<String> =
real?.invalidateArtInlineHookPackages.orEmpty().sorted().toMutableList()

override fun setInvalidateArtInlineHooks(packageName: String, enabled: Boolean): Boolean =
real?.setInvalidateArtInlineHooks(packageName, enabled) ?: false

override fun getLiveLogPart(verbose: Boolean): ParcelFileDescriptor? =
real?.getLiveLogPart(verbose)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,25 @@ class DaemonClient(private val serviceState: StateFlow<IManagerService?>) {
suspend fun setVerboseLogEnabled(enabled: Boolean): Result<Unit> = runIpc { it.setVerboseLogEnabled(enabled)
}

/**
* Every package opted into ART inline-hook invalidation, sorted.
*
* Empty against a daemon too old to answer the call, in which case the manager shows none.
*/
suspend fun getInvalidateArtInlineHookPackages(): Result<List<String>> = runIpc {
it.invalidateArtInlineHookPackages.orEmpty()
}

/**
* Sets whether a package invalidates Vector's native ART inline hooks after injection.
*
* [Result] carries the daemon's own answer: it stores the choice and reports whether the write
* landed, so a blank package name or a refused write reaches the caller rather than reading as a
* silent success.
*/
suspend fun setInvalidateArtInlineHooks(packageName: String, enabled: Boolean): Result<Boolean> =
runIpc { it.setInvalidateArtInlineHooks(packageName, enabled) }

/**
* The rotated parts the daemon still holds for one of the two logs, oldest first.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import android.text.format.Formatter
import androidx.compose.material.icons.rounded.ArrowCircleUp
import androidx.compose.material.icons.rounded.CloudDownload
import androidx.compose.material.icons.rounded.CloudOff
import androidx.compose.material.icons.rounded.FlashOff
import androidx.compose.material.icons.rounded.NotificationsOff
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -363,6 +364,50 @@ LocalizedOverlay {
}
}

// The inverse of re-optimizing, also only for a hook target. Where re-optimizing clears
// the inlined-away hooks ART has baked in, this stops Vector from installing ART inline
// hooks in the first place — the same silence, but a compatibility escape hatch rather
// than a fix: it trades the hooks of every module against an app that otherwise breaks or
// crashes. Read and written per package through the daemon, so the switch starts as the
// stored value and flips only as far as the daemon agrees.
if (!isModule) {
var invalidateInlineHooks by remember(packageName) { mutableStateOf<Boolean?>(null) }
LaunchedEffect(packageName) {
invalidateInlineHooks =
daemon.getInvalidateArtInlineHookPackages().getOrNull()?.contains(packageName)
}
ActionToggleRow(
icon = Icons.Rounded.FlashOff,
title = stringResource(R.string.action_invalidate_art_inline_hooks),
subtitle = stringResource(R.string.action_invalidate_art_inline_hooks_summary),
checked = invalidateInlineHooks == true,
onCheckedChange = { enabled ->
finish {
val ok =
daemon
.setInvalidateArtInlineHooks(packageName, enabled)
.onFailure { e ->
logE(
"actions: set ART inline hook invalidation for " +
"$packageName failed",
e,
)
}
.getOrDefault(false)
PackageActionResult(
when {
!ok -> R.string.action_invalidate_art_inline_hooks_failed
enabled -> R.string.action_invalidate_art_inline_hooks_enabled
else -> R.string.action_invalidate_art_inline_hooks_disabled
},
appName,
tone = if (ok) SnackbarTone.Success else SnackbarTone.Failure,
)
}
},
)
}

if (isModule) {
HorizontalDivider(Modifier.padding(horizontal = 24.dp, vertical = 4.dp))
ActionDrawerItem(
Expand Down
5 changes: 5 additions & 0 deletions manager/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -464,4 +464,9 @@
<string name="launcher_prompt_title">ليس لـ Vector أيقونة بعد</string>
<string name="launcher_prompt_body">يعمل Vector داخل عملية أخرى بدل أن يكون مثبَّتًا، فلا يظهر شيء في المشغّل ولا توجد طريقة واضحة للعودة إليه. امنحه اختصارًا على الشاشة الرئيسية، أو ثبِّته كتطبيق عادي.</string>
<string name="launcher_prompt_never">عدم السؤال مجددًا</string>
<string name="action_invalidate_art_inline_hooks">وضع توافق ربط ART المضمّن</string>
<string name="action_invalidate_art_inline_hooks_summary">تعطيل ربط ART المضمّن الخاص بـ Vector في هذا التطبيق لتحسين التوافق. قد تتوقف بعض الوحدات عن العمل هنا، وقد يتعطل التطبيق أو ينهار. يُطبّق عند تشغيل التطبيق في المرة القادمة.</string>
<string name="action_invalidate_art_inline_hooks_enabled">تم تفعيل توافق ربط ART المضمّن لـ %1$s.</string>
<string name="action_invalidate_art_inline_hooks_disabled">تم تعطيل توافق ربط ART المضمّن لـ %1$s.</string>
<string name="action_invalidate_art_inline_hooks_failed">تعذّر تغيير توافق ربط ART المضمّن لـ %1$s.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@
<string name="launcher_prompt_title">Vector hat noch kein Symbol</string>
<string name="launcher_prompt_body">Vector läuft in einem fremden Prozess, statt installiert zu sein — im Launcher erscheint also nichts, und es gibt keinen offensichtlichen Weg zurück. Gib ihm eine Verknüpfung auf dem Startbildschirm, oder installiere es als gewöhnliche App.</string>
<string name="launcher_prompt_never">Nicht mehr fragen</string>
<string name="action_invalidate_art_inline_hooks">ART-Inline-Hook-Kompatibilitätsmodus</string>
<string name="action_invalidate_art_inline_hooks_summary">Deaktiviere Vector\'s ART-Inline-Hooks in dieser App, um die Kompatibilität zu verbessern. Einige Module funktionieren hier möglicherweise nicht mehr, und die App kann sich fehlverhalten oder abstürzen. Wirkt beim nächsten Start der App.</string>
<string name="action_invalidate_art_inline_hooks_enabled">ART-Inline-Hook-Kompatibilität für %1$s aktiviert.</string>
<string name="action_invalidate_art_inline_hooks_disabled">ART-Inline-Hook-Kompatibilität für %1$s deaktiviert.</string>
<string name="action_invalidate_art_inline_hooks_failed">ART-Inline-Hook-Kompatibilität für %1$s konnte nicht geändert werden.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@
<string name="launcher_prompt_title">Vector todavía no tiene icono</string>
<string name="launcher_prompt_body">Vector se ejecuta dentro de otro proceso en lugar de estar instalado, así que no aparece nada en tu launcher y no hay una forma evidente de volver. Dale un acceso directo en la pantalla de inicio, o instálalo como una app normal.</string>
<string name="launcher_prompt_never">No volver a preguntar</string>
<string name="action_invalidate_art_inline_hooks">Modo de compatibilidad de hooks inline de ART</string>
<string name="action_invalidate_art_inline_hooks_summary">Desactiva los hooks inline de ART de Vector en esta app para mejorar la compatibilidad. Algunos módulos pueden dejar de funcionar aquí, y la app puede comportarse mal o bloquearse. Se aplica la próxima vez que se inicie la app.</string>
<string name="action_invalidate_art_inline_hooks_enabled">Compatibilidad de hooks inline de ART habilitada para %1$s.</string>
<string name="action_invalidate_art_inline_hooks_disabled">Compatibilidad de hooks inline de ART deshabilitada para %1$s.</string>
<string name="action_invalidate_art_inline_hooks_failed">No se pudo cambiar la compatibilidad de hooks inline de ART para %1$s.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-fa/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@
<string name="launcher_prompt_title">Vector هنوز نمادی ندارد</string>
<string name="launcher_prompt_body">Vector به‌جای آنکه نصب شده باشد درون فرایندی دیگر اجرا می‌شود، پس چیزی در لانچر پیدا نمی‌شود و راه روشنی برای بازگشت به آن نیست. به آن میان‌بری در صفحهٔ اصلی بدهید، یا آن را مانند برنامه‌ای معمولی نصب کنید.</string>
<string name="launcher_prompt_never">دیگر پرسیده نشود</string>
<string name="action_invalidate_art_inline_hooks">حالت سازگاری هوک درون‌خطی ART</string>
<string name="action_invalidate_art_inline_hooks_summary">غیرفعال کردن هوک‌های درون‌خطی ART ویکتور در این برنامه برای بهبود سازگاری. برخی ماژول‌ها ممکن است در اینجا از کار بیفتند و برنامه ممکن است دچار مشکل یا کرش شود. در راه‌اندازی بعدی برنامه اعمال می‌شود.</string>
<string name="action_invalidate_art_inline_hooks_enabled">حالت سازگاری هوک درون‌خطی ART برای %1$s فعال شد.</string>
<string name="action_invalidate_art_inline_hooks_disabled">حالت سازگاری هوک درون‌خطی ART برای %1$s غیرفعال شد.</string>
<string name="action_invalidate_art_inline_hooks_failed">تغییر حالت سازگاری هوک درون‌خطی ART برای %1$s ممکن نبود.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@
<string name="launcher_prompt_title">Vector n\'a pas encore d\'icône</string>
<string name="launcher_prompt_body">Vector s\'exécute dans un autre processus au lieu d\'être installé : rien n\'apparaît dans votre lanceur et il n\'y a pas de moyen évident d\'y revenir. Donnez-lui un raccourci sur l\'écran d\'accueil, ou installez-le comme une application ordinaire.</string>
<string name="launcher_prompt_never">Ne plus demander</string>
<string name="action_invalidate_art_inline_hooks">Mode de compatibilité des hooks inline ART</string>
<string name="action_invalidate_art_inline_hooks_summary">Désactive les hooks inline ART de Vector dans cette application pour améliorer la compatibilité. Certains modules peuvent cesser de fonctionner ici et l\'application peut mal se comporter ou planter. S\'applique au prochain démarrage de l\'application.</string>
<string name="action_invalidate_art_inline_hooks_enabled">Compatibilité des hooks inline ART activée pour %1$s.</string>
<string name="action_invalidate_art_inline_hooks_disabled">Compatibilité des hooks inline ART désactivée pour %1$s.</string>
<string name="action_invalidate_art_inline_hooks_failed">Impossible de modifier la compatibilité des hooks inline ART pour %1$s.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-in/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -413,4 +413,9 @@
<string name="launcher_prompt_title">Vector belum punya ikon</string>
<string name="launcher_prompt_body">Vector berjalan di dalam proses lain alih-alih dipasang, jadi tidak ada yang muncul di launcher Anda dan tidak ada jalan kembali yang jelas. Beri dia pintasan di layar utama, atau pasang sebagai aplikasi biasa.</string>
<string name="launcher_prompt_never">Jangan tanya lagi</string>
<string name="action_invalidate_art_inline_hooks">Mode kompatibilitas hook inline ART</string>
<string name="action_invalidate_art_inline_hooks_summary">Menonaktifkan hook inline ART Vector di aplikasi ini untuk meningkatkan kompatibilitas. Beberapa modul mungkin berhenti bekerja di sini, dan aplikasi mungkin berperilaku tidak normal atau mogok. Berlaku saat aplikasi dimulai berikutnya.</string>
<string name="action_invalidate_art_inline_hooks_enabled">Kompatibilitas hook inline ART diaktifkan untuk %1$s.</string>
<string name="action_invalidate_art_inline_hooks_disabled">Kompatibilitas hook inline ART dinonaktifkan untuk %1$s.</string>
<string name="action_invalidate_art_inline_hooks_failed">Tidak dapat mengubah kompatibilitas hook inline ART untuk %1$s.</string>
</resources>
5 changes: 5 additions & 0 deletions manager/src/main/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@
<string name="launcher_prompt_title">Vector non ha ancora un\'icona</string>
<string name="launcher_prompt_body">Vector gira dentro un altro processo invece di essere installato, quindi nel launcher non compare nulla e non c\'è un modo evidente per tornarci. Dagli una scorciatoia nella schermata Home, oppure installalo come una normale app.</string>
<string name="launcher_prompt_never">Non chiedere più</string>
<string name="action_invalidate_art_inline_hooks">Modalità di compatibilità degli hook inline ART</string>
<string name="action_invalidate_art_inline_hooks_summary">Disattiva gli hook inline ART di Vector in questa app per migliorare la compatibilità. Alcuni moduli potrebbero smettere di funzionare qui e l\'app potrebbe comportarsi in modo anomalo o bloccarsi. Ha effetto al prossimo avvio dell\'app.</string>
<string name="action_invalidate_art_inline_hooks_enabled">Compatibilità hook inline ART abilitata per %1$s.</string>
<string name="action_invalidate_art_inline_hooks_disabled">Compatibilità hook inline ART disabilitata per %1$s.</string>
<string name="action_invalidate_art_inline_hooks_failed">Impossibile modificare la compatibilità degli hook inline ART per %1$s.</string>
</resources>
Loading