mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 02:25:28 +00:00
Simplify context hacks
This commit is contained in:
parent
9ab7550970
commit
5c6a7ffa6f
@ -2,10 +2,8 @@
|
|||||||
|
|
||||||
package com.topjohnwu.magisk.core
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
@ -20,13 +18,9 @@ lateinit var AppApkPath: String
|
|||||||
|
|
||||||
fun Resources.addAssetPath(path: String) = StubApk.addAssetPath(this, path)
|
fun Resources.addAssetPath(path: String) = StubApk.addAssetPath(this, path)
|
||||||
|
|
||||||
fun Context.wrap(): Context = if (this is PatchedContext) this else PatchedContext(this)
|
fun Context.patch(): Context {
|
||||||
|
resources.patch()
|
||||||
private class PatchedContext(base: Context) : ContextWrapper(base) {
|
return this
|
||||||
init { base.resources.patch() }
|
|
||||||
override fun getClassLoader() = javaClass.classLoader!!
|
|
||||||
override fun createConfigurationContext(config: Configuration) =
|
|
||||||
super.createConfigurationContext(config).wrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Resources.patch(): Resources {
|
fun Resources.patch(): Resources {
|
||||||
@ -49,10 +43,6 @@ fun createNewResources(): Resources {
|
|||||||
fun Class<*>.cmp(pkg: String) =
|
fun Class<*>.cmp(pkg: String) =
|
||||||
ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
|
ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
|
||||||
|
|
||||||
inline fun <reified T> Activity.redirect() = Intent(intent)
|
|
||||||
.setComponent(T::class.java.cmp(packageName))
|
|
||||||
.setFlags(0)
|
|
||||||
|
|
||||||
inline fun <reified T> Context.intent() = Intent().setComponent(T::class.java.cmp(packageName))
|
inline fun <reified T> Context.intent() = Intent().setComponent(T::class.java.cmp(packageName))
|
||||||
|
|
||||||
// Keep a reference to these resources to prevent it from
|
// Keep a reference to these resources to prevent it from
|
||||||
|
@ -1,22 +1,14 @@
|
|||||||
package com.topjohnwu.magisk.core
|
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.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
import android.os.ParcelFileDescriptor.MODE_READ_ONLY
|
import android.os.ParcelFileDescriptor.MODE_READ_ONLY
|
||||||
|
import com.topjohnwu.magisk.core.base.BaseProvider
|
||||||
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Provider : ContentProvider() {
|
class Provider : BaseProvider() {
|
||||||
|
|
||||||
override fun attachInfo(context: Context, info: ProviderInfo) {
|
|
||||||
super.attachInfo(context.wrap(), info)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
|
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
|
||||||
SuCallbackHandler.run(context!!, method, extras)
|
SuCallbackHandler.run(context!!, method, extras)
|
||||||
@ -38,11 +30,4 @@ class Provider : ContentProvider() {
|
|||||||
fun PREFS_URI(pkg: String) =
|
fun PREFS_URI(pkg: String) =
|
||||||
Uri.Builder().scheme("content").authority("$pkg.provider").path("prefs_file").build()
|
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<out String>?) = 0
|
|
||||||
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
|
|
||||||
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? = null
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.core
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.ContextWrapper
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.core.base.BaseReceiver
|
import com.topjohnwu.magisk.core.base.BaseReceiver
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||||
@ -26,8 +26,9 @@ open class Receiver : BaseReceiver() {
|
|||||||
return if (uid == -1) null else uid
|
return if (uid == -1) null else uid
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReceive(context: ContextWrapper, intent: Intent?) {
|
override fun onReceive(context: Context, intent: Intent?) {
|
||||||
intent ?: return
|
intent ?: return
|
||||||
|
super.onReceive(context, intent)
|
||||||
|
|
||||||
fun rmPolicy(uid: Int) = GlobalScope.launch {
|
fun rmPolicy(uid: Int) = GlobalScope.launch {
|
||||||
policyDB.delete(uid)
|
policyDB.delete(uid)
|
||||||
|
@ -18,10 +18,9 @@ import androidx.annotation.WorkerThread
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
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.RequestInstall
|
||||||
import com.topjohnwu.magisk.core.utils.UninstallPackage
|
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.ktx.reflectField
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
@ -56,14 +55,12 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
uninstallLatch.countDown()
|
uninstallLatch.countDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyOverrideConfiguration(config: Configuration?) {
|
override fun attachBaseContext(base: Context) {
|
||||||
// Force applying our preferred local
|
super.attachBaseContext(base.patch())
|
||||||
config?.setLocale(currentLocale)
|
|
||||||
super.applyOverrideConfiguration(config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun createConfigurationContext(config: Configuration): Context {
|
||||||
super.attachBaseContext(base.wrap())
|
return super.createConfigurationContext(config).patch()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -2,10 +2,10 @@ package com.topjohnwu.magisk.core.base
|
|||||||
|
|
||||||
import android.app.job.JobService
|
import android.app.job.JobService
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.topjohnwu.magisk.core.wrap
|
import com.topjohnwu.magisk.core.patch
|
||||||
|
|
||||||
abstract class BaseJobService : JobService() {
|
abstract class BaseJobService : JobService() {
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base.wrap())
|
super.attachBaseContext(base.patch())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<out String>?) = 0
|
||||||
|
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
|
||||||
|
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? = null
|
||||||
|
}
|
@ -2,15 +2,13 @@ package com.topjohnwu.magisk.core.base
|
|||||||
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.topjohnwu.magisk.core.wrap
|
import androidx.annotation.CallSuper
|
||||||
|
import com.topjohnwu.magisk.core.patch
|
||||||
|
|
||||||
abstract class BaseReceiver : BroadcastReceiver() {
|
abstract class BaseReceiver : BroadcastReceiver() {
|
||||||
|
@CallSuper
|
||||||
final override fun onReceive(context: Context, intent: Intent?) {
|
override fun onReceive(context: Context, intent: Intent?) {
|
||||||
onReceive(context.wrap() as ContextWrapper, intent)
|
context.patch()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun onReceive(context: ContextWrapper, intent: Intent?)
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,13 @@ package com.topjohnwu.magisk.core.base
|
|||||||
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
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) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base.wrap())
|
super.attachBaseContext(base.patch())
|
||||||
}
|
}
|
||||||
|
override fun onBind(intent: Intent?): IBinder? = null
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.topjohnwu.magisk.core.download
|
|||||||
|
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.IBinder
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.base.BaseService
|
import com.topjohnwu.magisk.core.base.BaseService
|
||||||
@ -20,8 +19,6 @@ open class NotificationService : BaseService() {
|
|||||||
|
|
||||||
protected val service get() = ServiceLocator.networkService
|
protected val service get() = ServiceLocator.networkService
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? = null
|
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
super.onTaskRemoved(rootIntent)
|
super.onTaskRemoved(rootIntent)
|
||||||
notifications.forEach { Notifications.mgr.cancel(it.key) }
|
notifications.forEach { Notifications.mgr.cancel(it.key) }
|
||||||
|
@ -6,6 +6,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.ActivityTracker
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.createNewResources
|
import com.topjohnwu.magisk.core.createNewResources
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
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
|
// Create a completely new resource to prevent cross talk over active configs
|
||||||
val res = createNewResources()
|
val res = createNewResources()
|
||||||
|
|
||||||
|
fun changeLocale(locale: Locale) {
|
||||||
|
res.configuration.setLocale(locale)
|
||||||
|
res.updateConfiguration(res.configuration, res.displayMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
val locales = ArrayList<String>().apply {
|
val locales = ArrayList<String>().apply {
|
||||||
// Add default locale
|
// Add default locale
|
||||||
add("en")
|
add("en")
|
||||||
@ -40,13 +46,13 @@ withContext(Dispatchers.Default) {
|
|||||||
}.map {
|
}.map {
|
||||||
Locale.forLanguageTag(it)
|
Locale.forLanguageTag(it)
|
||||||
}.distinctBy {
|
}.distinctBy {
|
||||||
res.setLocale(it)
|
changeLocale(it)
|
||||||
res.getString(compareId)
|
res.getString(compareId)
|
||||||
}.sortedWith { a, b ->
|
}.sortedWith { a, b ->
|
||||||
a.getDisplayName(a).compareTo(b.getDisplayName(b), true)
|
a.getDisplayName(a).compareTo(b.getDisplayName(b), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setLocale(defaultLocale)
|
changeLocale(defaultLocale)
|
||||||
val defName = res.getString(R.string.system_default)
|
val defName = res.getString(R.string.system_default)
|
||||||
|
|
||||||
val names = ArrayList<String>(locales.size + 1)
|
val names = ArrayList<String>(locales.size + 1)
|
||||||
@ -70,11 +76,6 @@ fun Resources.setConfig(config: Configuration) {
|
|||||||
|
|
||||||
fun Resources.syncLocale() = setConfig(configuration)
|
fun Resources.syncLocale() = setConfig(configuration)
|
||||||
|
|
||||||
fun Resources.setLocale(locale: Locale) {
|
|
||||||
configuration.setLocale(locale)
|
|
||||||
updateConfiguration(configuration, displayMetrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refreshLocale() {
|
fun refreshLocale() {
|
||||||
val localeConfig = Config.locale
|
val localeConfig = Config.locale
|
||||||
currentLocale = when {
|
currentLocale = when {
|
||||||
@ -83,4 +84,5 @@ fun refreshLocale() {
|
|||||||
}
|
}
|
||||||
Locale.setDefault(currentLocale)
|
Locale.setDefault(currentLocale)
|
||||||
AppContext.resources.syncLocale()
|
AppContext.resources.syncLocale()
|
||||||
|
ActivityTracker.foreground?.recreate()
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,10 @@ object Customization : BaseSettingsItem.Section() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Language : BaseSettingsItem.Selector() {
|
object Language : BaseSettingsItem.Selector() {
|
||||||
override var value = -1
|
override var value
|
||||||
|
get() = index
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
index = value
|
||||||
Config.locale = entryValues[value]
|
Config.locale = entryValues[value]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ object Language : BaseSettingsItem.Selector() {
|
|||||||
|
|
||||||
private var entries = emptyArray<String>()
|
private var entries = emptyArray<String>()
|
||||||
private var entryValues = emptyArray<String>()
|
private var entryValues = emptyArray<String>()
|
||||||
|
private var index = -1
|
||||||
|
|
||||||
override fun entries(res: Resources) = entries
|
override fun entries(res: Resources) = entries
|
||||||
override fun descriptions(res: Resources) = entries
|
override fun descriptions(res: Resources) = entries
|
||||||
@ -62,7 +64,7 @@ object Language : BaseSettingsItem.Selector() {
|
|||||||
entries = names
|
entries = names
|
||||||
entryValues = values
|
entryValues = values
|
||||||
val selectedLocale = currentLocale.getDisplayName(currentLocale)
|
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)
|
notifyPropertyChanged(BR.description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import com.topjohnwu.magisk.core.tasks.HideAPK
|
|||||||
import com.topjohnwu.magisk.databinding.adapterOf
|
import com.topjohnwu.magisk.databinding.adapterOf
|
||||||
import com.topjohnwu.magisk.databinding.itemBindingOf
|
import com.topjohnwu.magisk.databinding.itemBindingOf
|
||||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||||
import com.topjohnwu.magisk.events.RecreateEvent
|
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||||
import com.topjohnwu.magisk.ktx.activity
|
import com.topjohnwu.magisk.ktx.activity
|
||||||
@ -108,7 +107,6 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
|
|
||||||
override fun onItemAction(view: View, item: BaseSettingsItem) {
|
override fun onItemAction(view: View, item: BaseSettingsItem) {
|
||||||
when (item) {
|
when (item) {
|
||||||
Language -> RecreateEvent().publish()
|
|
||||||
UpdateChannel -> openUrlIfNecessary(view)
|
UpdateChannel -> openUrlIfNecessary(view)
|
||||||
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
|
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
|
||||||
Restore -> viewModelScope.launch { HideAPK.restore(view.activity) }
|
Restore -> viewModelScope.launch { HideAPK.restore(view.activity) }
|
||||||
|
Loading…
Reference in New Issue
Block a user