Better stub launch flow

This commit is contained in:
topjohnwu 2022-06-05 19:15:43 -07:00
parent fa60daf9b5
commit 317153c53a
7 changed files with 55 additions and 38 deletions

View File

@ -27,8 +27,7 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
open val snackbarAnchorView: View? get() = null open val snackbarAnchorView: View? get() = null
init { init {
val theme = Config.darkTheme AppCompatDelegate.setDefaultNightMode(Config.darkTheme)
AppCompatDelegate.setDefaultNightMode(theme)
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -2,6 +2,7 @@ package com.topjohnwu.magisk.core.base
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -54,6 +55,18 @@ abstract class BaseActivity : AppCompatActivity() {
uninstallLatch.countDown() uninstallLatch.countDown()
} }
private val mReferrerField by lazy(LazyThreadSafetyMode.NONE) {
Activity::class.java.reflectField("mReferrer")
}
val realCallingPackage: String? get() {
callingPackage?.let { return it }
if (Build.VERSION.SDK_INT >= 22) {
mReferrerField.get(this)?.let { return it as String }
}
return null
}
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {
super.attachBaseContext(base.wrap()) super.attachBaseContext(base.wrap())
} }

View File

@ -99,8 +99,7 @@ object HideAPK {
val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
activity.grantUriPermission(pkg, Provider.preferencesUri(self), flag) activity.grantUriPermission(pkg, Provider.preferencesUri(self), flag)
intent.putExtra(Const.Key.PREV_PKG, self) intent.putExtra(Const.Key.PREV_PKG, self)
intent.flags = 0 activity.startActivity(intent)
activity.startActivityForResult(intent, Int.MAX_VALUE)
activity.finish() activity.finish()
} }

View File

@ -3,6 +3,7 @@ package com.topjohnwu.magisk.events.dialog
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
@ -33,6 +34,6 @@ class DarkThemeDialog : DialogEvent() {
private fun selectTheme(mode: Int, activity: Activity) { private fun selectTheme(mode: Int, activity: Activity) {
Config.darkTheme = mode Config.darkTheme = mode
activity.recreate() (activity as UIActivity<*>).delegate.localNightMode = mode
} }
} }

View File

@ -13,7 +13,6 @@ import androidx.core.view.isVisible
import androidx.navigation.NavDirections import androidx.navigation.NavDirections
import com.topjohnwu.magisk.MainDirections import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseMainActivity
import com.topjohnwu.magisk.arch.BaseViewModel import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.viewModel import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
@ -31,7 +30,7 @@ import java.io.File
class MainViewModel : BaseViewModel() class MainViewModel : BaseViewModel()
class MainActivity : BaseMainActivity<ActivityMainMd2Binding>() { class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
override val layoutRes = R.layout.activity_main_md2 override val layoutRes = R.layout.activity_main_md2
override val viewModel by viewModel<MainViewModel>() override val viewModel by viewModel<MainViewModel>()

View File

@ -1,4 +1,4 @@
package com.topjohnwu.magisk.arch package com.topjohnwu.magisk.ui
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
import android.annotation.SuppressLint import android.annotation.SuppressLint
@ -9,7 +9,7 @@ import androidx.databinding.ViewDataBinding
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.JobService import com.topjohnwu.magisk.core.JobService
@ -25,16 +25,17 @@ import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() { @SuppressLint("CustomSplashScreen")
abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() {
companion object { companion object {
private var doPreload = true private var skipSplash = false
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setTheme(Theme.selected.themeRes) setTheme(Theme.selected.themeRes)
if (isRunningAsStub && doPreload) { if (isRunningAsStub && !skipSplash) {
// Manually apply splash theme for stub // Manually apply splash theme for stub
theme.applyStyle(R.style.StubSplashTheme, true) theme.applyStyle(R.style.StubSplashTheme, true)
} }
@ -43,28 +44,19 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
if (!isRunningAsStub) { if (!isRunningAsStub) {
val splashScreen = installSplashScreen() val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { doPreload } splashScreen.setKeepOnScreenCondition { !skipSplash }
} }
if (doPreload) { if (skipSplash) {
showMainUI(savedInstanceState)
} else {
Shell.getShell(Shell.EXECUTOR) { Shell.getShell(Shell.EXECUTOR) {
if (isRunningAsStub && !it.isRoot) { if (isRunningAsStub && !it.isRoot) {
showInvalidStateMessage() showInvalidStateMessage()
return@getShell return@getShell
} }
preLoad() preLoad(savedInstanceState)
runOnUiThread {
doPreload = false
if (isRunningAsStub) {
// Re-launch main activity without splash theme
relaunch()
} else {
showMainUI(savedInstanceState)
}
}
} }
} else {
showMainUI(savedInstanceState)
} }
} }
@ -84,7 +76,7 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
showInvalidStateMessage() showInvalidStateMessage()
} else { } else {
lifecycleScope.launch { lifecycleScope.launch {
HideAPK.restore(this@BaseMainActivity) HideAPK.restore(this@SplashActivity)
} }
} }
} }
@ -95,10 +87,10 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
} }
} }
private fun preLoad() { private fun preLoad(savedState: Bundle?) {
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)?.let { val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)?.let {
// Make sure the calling package matches (prevent DoS) // Make sure the calling package matches (prevent DoS)
if (it == callingPackage) if (it == realCallingPackage)
it it
else else
null null
@ -106,9 +98,14 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
Config.load(prevPkg) Config.load(prevPkg)
handleRepackage(prevPkg) handleRepackage(prevPkg)
if (prevPkg != null) { if (prevPkg != null && !isRunningAsStub) {
StubApk.restartProcess(this) runOnUiThread {
// Might have new configuration loaded, relaunch the activity
relaunch()
}
return
} }
Notifications.setup(this) Notifications.setup(this)
JobService.schedule(this) JobService.schedule(this)
Shortcuts.setupDynamic(this) Shortcuts.setupDynamic(this)
@ -118,6 +115,16 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
// Wait for root service // Wait for root service
RootUtils.Connection.await() RootUtils.Connection.await()
runOnUiThread {
skipSplash = true
if (isRunningAsStub) {
// Re-launch main activity without splash theme
relaunch()
} else {
showMainUI(savedState)
}
}
} }
private fun handleRepackage(pkg: String?) { private fun handleRepackage(pkg: String?) {

View File

@ -1,6 +1,7 @@
package com.topjohnwu.magisk.ui.theme package com.topjohnwu.magisk.ui.theme
import com.topjohnwu.magisk.arch.BaseViewModel import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.events.RecreateEvent import com.topjohnwu.magisk.events.RecreateEvent
import com.topjohnwu.magisk.events.dialog.DarkThemeDialog import com.topjohnwu.magisk.events.dialog.DarkThemeDialog
import com.topjohnwu.magisk.view.TappableHeadlineItem import com.topjohnwu.magisk.view.TappableHeadlineItem
@ -10,15 +11,13 @@ class ThemeViewModel : BaseViewModel(), TappableHeadlineItem.Listener {
val themeHeadline = TappableHeadlineItem.ThemeMode val themeHeadline = TappableHeadlineItem.ThemeMode
override fun onItemPressed(item: TappableHeadlineItem) = when (item) { override fun onItemPressed(item: TappableHeadlineItem) = when (item) {
is TappableHeadlineItem.ThemeMode -> darkModePressed() is TappableHeadlineItem.ThemeMode -> DarkThemeDialog().publish()
else -> Unit
} }
fun saveTheme(theme: Theme) { fun saveTheme(theme: Theme) {
theme.select() if (!theme.isSelected) {
RecreateEvent().publish() Config.themeOrdinal = theme.ordinal
RecreateEvent().publish()
}
} }
private fun darkModePressed() = DarkThemeDialog().publish()
} }