From 5c6a7ffa6f24a2499d89b8ac089feec1e190c971 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 2 Jun 2022 04:22:25 -0700 Subject: [PATCH] Simplify context hacks --- .../java/com/topjohnwu/magisk/core/Hacks.kt | 16 +++----------- .../com/topjohnwu/magisk/core/Provider.kt | 19 ++--------------- .../com/topjohnwu/magisk/core/Receiver.kt | 5 +++-- .../magisk/core/base/BaseActivity.kt | 13 +++++------- .../magisk/core/base/BaseJobService.kt | 4 ++-- .../magisk/core/base/BaseProvider.kt | 21 +++++++++++++++++++ .../magisk/core/base/BaseReceiver.kt | 12 +++++------ .../topjohnwu/magisk/core/base/BaseService.kt | 9 +++++--- .../core/download/NotificationService.kt | 3 --- .../topjohnwu/magisk/core/utils/Locales.kt | 16 +++++++------- .../magisk/ui/settings/SettingsItems.kt | 8 ++++--- .../magisk/ui/settings/SettingsViewModel.kt | 2 -- 12 files changed, 61 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/core/base/BaseProvider.kt diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Hacks.kt b/app/src/main/java/com/topjohnwu/magisk/core/Hacks.kt index c7bc685b4..279be90ce 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Hacks.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Hacks.kt @@ -2,10 +2,8 @@ package com.topjohnwu.magisk.core -import android.app.Activity import android.content.ComponentName import android.content.Context -import android.content.ContextWrapper import android.content.Intent import android.content.res.AssetManager import android.content.res.Configuration @@ -20,13 +18,9 @@ lateinit var AppApkPath: String fun Resources.addAssetPath(path: String) = StubApk.addAssetPath(this, path) -fun Context.wrap(): Context = if (this is PatchedContext) this else PatchedContext(this) - -private class PatchedContext(base: Context) : ContextWrapper(base) { - init { base.resources.patch() } - override fun getClassLoader() = javaClass.classLoader!! - override fun createConfigurationContext(config: Configuration) = - super.createConfigurationContext(config).wrap() +fun Context.patch(): Context { + resources.patch() + return this } fun Resources.patch(): Resources { @@ -49,10 +43,6 @@ fun createNewResources(): Resources { fun Class<*>.cmp(pkg: String) = ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name) -inline fun Activity.redirect() = Intent(intent) - .setComponent(T::class.java.cmp(packageName)) - .setFlags(0) - inline fun Context.intent() = Intent().setComponent(T::class.java.cmp(packageName)) // Keep a reference to these resources to prevent it from diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt b/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt index 74fd63954..2117268c0 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt @@ -1,22 +1,14 @@ package com.topjohnwu.magisk.core -import android.content.ContentProvider -import android.content.ContentValues -import android.content.Context -import android.content.pm.ProviderInfo -import android.database.Cursor import android.net.Uri import android.os.Bundle import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor.MODE_READ_ONLY +import com.topjohnwu.magisk.core.base.BaseProvider import com.topjohnwu.magisk.core.su.SuCallbackHandler import java.io.File -class Provider : ContentProvider() { - - override fun attachInfo(context: Context, info: ProviderInfo) { - super.attachInfo(context.wrap(), info) - } +class Provider : BaseProvider() { override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { SuCallbackHandler.run(context!!, method, extras) @@ -38,11 +30,4 @@ class Provider : ContentProvider() { fun PREFS_URI(pkg: String) = Uri.Builder().scheme("content").authority("$pkg.provider").path("prefs_file").build() } - - override fun onCreate() = true - override fun getType(uri: Uri): String? = null - override fun insert(uri: Uri, values: ContentValues?): Uri? = null - override fun delete(uri: Uri, selection: String?, selectionArgs: Array?) = 0 - override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?) = 0 - override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? = null } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Receiver.kt b/app/src/main/java/com/topjohnwu/magisk/core/Receiver.kt index c016ddde3..c3736f307 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Receiver.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Receiver.kt @@ -1,7 +1,7 @@ package com.topjohnwu.magisk.core import android.annotation.SuppressLint -import android.content.ContextWrapper +import android.content.Context import android.content.Intent import com.topjohnwu.magisk.core.base.BaseReceiver import com.topjohnwu.magisk.core.di.ServiceLocator @@ -26,8 +26,9 @@ open class Receiver : BaseReceiver() { return if (uid == -1) null else uid } - override fun onReceive(context: ContextWrapper, intent: Intent?) { + override fun onReceive(context: Context, intent: Intent?) { intent ?: return + super.onReceive(context, intent) fun rmPolicy(uid: Int) = GlobalScope.launch { policyDB.delete(uid) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt index d18e220ad..a38903633 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt @@ -18,10 +18,9 @@ import androidx.annotation.WorkerThread import androidx.appcompat.app.AppCompatActivity import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.isRunningAsStub +import com.topjohnwu.magisk.core.patch import com.topjohnwu.magisk.core.utils.RequestInstall import com.topjohnwu.magisk.core.utils.UninstallPackage -import com.topjohnwu.magisk.core.utils.currentLocale -import com.topjohnwu.magisk.core.wrap import com.topjohnwu.magisk.ktx.reflectField import com.topjohnwu.magisk.utils.Utils import java.util.concurrent.CountDownLatch @@ -56,14 +55,12 @@ abstract class BaseActivity : AppCompatActivity() { uninstallLatch.countDown() } - override fun applyOverrideConfiguration(config: Configuration?) { - // Force applying our preferred local - config?.setLocale(currentLocale) - super.applyOverrideConfiguration(config) + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base.patch()) } - override fun attachBaseContext(base: Context) { - super.attachBaseContext(base.wrap()) + override fun createConfigurationContext(config: Configuration): Context { + return super.createConfigurationContext(config).patch() } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt index 3208be75c..b178f6c9c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt @@ -2,10 +2,10 @@ package com.topjohnwu.magisk.core.base import android.app.job.JobService import android.content.Context -import com.topjohnwu.magisk.core.wrap +import com.topjohnwu.magisk.core.patch abstract class BaseJobService : JobService() { override fun attachBaseContext(base: Context) { - super.attachBaseContext(base.wrap()) + super.attachBaseContext(base.patch()) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseProvider.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseProvider.kt new file mode 100644 index 000000000..8295bd0e9 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseProvider.kt @@ -0,0 +1,21 @@ +package com.topjohnwu.magisk.core.base + +import android.content.ContentProvider +import android.content.ContentValues +import android.content.Context +import android.content.pm.ProviderInfo +import android.database.Cursor +import android.net.Uri +import com.topjohnwu.magisk.core.patch + +open class BaseProvider : ContentProvider() { + override fun attachInfo(context: Context, info: ProviderInfo) { + super.attachInfo(context.patch(), info) + } + override fun onCreate() = true + override fun getType(uri: Uri): String? = null + override fun insert(uri: Uri, values: ContentValues?): Uri? = null + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?) = 0 + override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?) = 0 + override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? = null +} diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseReceiver.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseReceiver.kt index 50f79539d..e29a991e8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseReceiver.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseReceiver.kt @@ -2,15 +2,13 @@ package com.topjohnwu.magisk.core.base import android.content.BroadcastReceiver import android.content.Context -import android.content.ContextWrapper import android.content.Intent -import com.topjohnwu.magisk.core.wrap +import androidx.annotation.CallSuper +import com.topjohnwu.magisk.core.patch abstract class BaseReceiver : BroadcastReceiver() { - - final override fun onReceive(context: Context, intent: Intent?) { - onReceive(context.wrap() as ContextWrapper, intent) + @CallSuper + override fun onReceive(context: Context, intent: Intent?) { + context.patch() } - - abstract fun onReceive(context: ContextWrapper, intent: Intent?) } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseService.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseService.kt index db9ab53e4..bc1e7418b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseService.kt @@ -2,10 +2,13 @@ package com.topjohnwu.magisk.core.base import android.app.Service import android.content.Context -import com.topjohnwu.magisk.core.wrap +import android.content.Intent +import android.os.IBinder +import com.topjohnwu.magisk.core.patch -abstract class BaseService : Service() { +open class BaseService : Service() { override fun attachBaseContext(base: Context) { - super.attachBaseContext(base.wrap()) + super.attachBaseContext(base.patch()) } + override fun onBind(intent: Intent?): IBinder? = null } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/download/NotificationService.kt b/app/src/main/java/com/topjohnwu/magisk/core/download/NotificationService.kt index 3e2cfac8d..e163f74cf 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/download/NotificationService.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/download/NotificationService.kt @@ -2,7 +2,6 @@ package com.topjohnwu.magisk.core.download import android.app.Notification import android.content.Intent -import android.os.IBinder import androidx.lifecycle.MutableLiveData import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.base.BaseService @@ -20,8 +19,6 @@ open class NotificationService : BaseService() { protected val service get() = ServiceLocator.networkService - override fun onBind(intent: Intent?): IBinder? = null - override fun onTaskRemoved(rootIntent: Intent?) { super.onTaskRemoved(rootIntent) notifications.forEach { Notifications.mgr.cancel(it.key) } diff --git a/app/src/main/java/com/topjohnwu/magisk/core/utils/Locales.kt b/app/src/main/java/com/topjohnwu/magisk/core/utils/Locales.kt index a9c92a04c..83a4a61ae 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/utils/Locales.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/Locales.kt @@ -6,6 +6,7 @@ import android.annotation.SuppressLint import android.content.res.Configuration import android.content.res.Resources import com.topjohnwu.magisk.R +import com.topjohnwu.magisk.core.ActivityTracker import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.createNewResources import com.topjohnwu.magisk.core.di.AppContext @@ -27,6 +28,11 @@ withContext(Dispatchers.Default) { // Create a completely new resource to prevent cross talk over active configs val res = createNewResources() + fun changeLocale(locale: Locale) { + res.configuration.setLocale(locale) + res.updateConfiguration(res.configuration, res.displayMetrics) + } + val locales = ArrayList().apply { // Add default locale add("en") @@ -40,13 +46,13 @@ withContext(Dispatchers.Default) { }.map { Locale.forLanguageTag(it) }.distinctBy { - res.setLocale(it) + changeLocale(it) res.getString(compareId) }.sortedWith { a, b -> a.getDisplayName(a).compareTo(b.getDisplayName(b), true) } - res.setLocale(defaultLocale) + changeLocale(defaultLocale) val defName = res.getString(R.string.system_default) val names = ArrayList(locales.size + 1) @@ -70,11 +76,6 @@ fun Resources.setConfig(config: Configuration) { fun Resources.syncLocale() = setConfig(configuration) -fun Resources.setLocale(locale: Locale) { - configuration.setLocale(locale) - updateConfiguration(configuration, displayMetrics) -} - fun refreshLocale() { val localeConfig = Config.locale currentLocale = when { @@ -83,4 +84,5 @@ fun refreshLocale() { } Locale.setDefault(currentLocale) AppContext.resources.syncLocale() + ActivityTracker.foreground?.recreate() } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt index 2538249df..daf9ca5d9 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt @@ -37,9 +37,10 @@ object Customization : BaseSettingsItem.Section() { } object Language : BaseSettingsItem.Selector() { - override var value = -1 + override var value + get() = index set(value) { - field = value + index = value Config.locale = entryValues[value] } @@ -47,6 +48,7 @@ object Language : BaseSettingsItem.Selector() { private var entries = emptyArray() private var entryValues = emptyArray() + private var index = -1 override fun entries(res: Resources) = entries override fun descriptions(res: Resources) = entries @@ -62,7 +64,7 @@ object Language : BaseSettingsItem.Selector() { entries = names entryValues = values val selectedLocale = currentLocale.getDisplayName(currentLocale) - value = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it } + index = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it } notifyPropertyChanged(BR.description) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt index 6e0c1e5af..4cbab993a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt @@ -17,7 +17,6 @@ import com.topjohnwu.magisk.core.tasks.HideAPK import com.topjohnwu.magisk.databinding.adapterOf import com.topjohnwu.magisk.databinding.itemBindingOf import com.topjohnwu.magisk.events.AddHomeIconEvent -import com.topjohnwu.magisk.events.RecreateEvent import com.topjohnwu.magisk.events.SnackbarEvent import com.topjohnwu.magisk.events.dialog.BiometricEvent import com.topjohnwu.magisk.ktx.activity @@ -108,7 +107,6 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler { override fun onItemAction(view: View, item: BaseSettingsItem) { when (item) { - Language -> RecreateEvent().publish() UpdateChannel -> openUrlIfNecessary(view) is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) } Restore -> viewModelScope.launch { HideAPK.restore(view.activity) }