diff --git a/app/apk/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt b/app/apk/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt index 80ecb8c32..4fe1dc366 100644 --- a/app/apk/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt +++ b/app/apk/src/main/java/com/topjohnwu/magisk/ui/SplashActivity.kt @@ -9,31 +9,16 @@ import androidx.databinding.ViewDataBinding import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.arch.NavigationActivity -import com.topjohnwu.magisk.core.BuildConfig -import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME -import com.topjohnwu.magisk.core.Config -import com.topjohnwu.magisk.core.Const -import com.topjohnwu.magisk.core.Info -import com.topjohnwu.magisk.core.JobService -import com.topjohnwu.magisk.core.base.launchPackage import com.topjohnwu.magisk.core.base.relaunch -import com.topjohnwu.magisk.core.di.ServiceLocator +import com.topjohnwu.magisk.core.initializeOnSplashScreen import com.topjohnwu.magisk.core.isRunningAsStub import com.topjohnwu.magisk.core.ktx.toast -import com.topjohnwu.magisk.core.ktx.writeTo import com.topjohnwu.magisk.core.tasks.HideAPK -import com.topjohnwu.magisk.core.utils.RootUtils import com.topjohnwu.magisk.ui.theme.Theme import com.topjohnwu.magisk.view.MagiskDialog -import com.topjohnwu.magisk.view.Shortcuts import com.topjohnwu.superuser.Shell -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import timber.log.Timber -import java.io.File -import java.io.IOException import com.topjohnwu.magisk.core.R as CoreR @SuppressLint("CustomSplashScreen") @@ -68,7 +53,19 @@ abstract class SplashActivity : NavigationActivity : NavigationActivity/dev/null 2>&1").exec() - } - } else { - if (Config.suManager.isNotEmpty()) { - Config.suManager = "" - } - if (isPackageMigration) { - Shell.cmd("(pm uninstall $prevPkg)& >/dev/null 2>&1").exec() - } - } - - if (isPackageMigration) { - runOnUiThread { - // Relaunch the process after package migration - StubApk.restartProcess(this) - } - return - } - - // Validate stub APK - if (isRunningAsStub && ( - // Version mismatch - Info.stub!!.version != BuildConfig.STUB_VERSION || - // Not properly patched - intent.component!!.className.contains(HideAPK.PLACEHOLDER) - )) { - withPermission(REQUEST_INSTALL_PACKAGES) { granted -> - if (granted) { - lifecycleScope.launch(Dispatchers.IO) { - val apk = File(cacheDir, "stub.apk") - try { - assets.open("stub.apk").writeTo(apk) - HideAPK.upgrade(this@SplashActivity, apk)?.let { - startActivity(it) - } - } catch (e: IOException) { - Timber.e(e) - } - } - } - } - return - } - - JobService.schedule(this) - Shortcuts.setupDynamic(this) - - // Pre-fetch network services - ServiceLocator.networkService - - // Wait for root service - RootUtils.Connection.await() - - runOnUiThread { - splashShown = true - if (isRunningAsStub) { - // Re-launch main activity without splash theme - relaunch() - } else { - if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { - doShowMainUI(savedState) - } else { - needShowMainUI = true - } - } - } - } } diff --git a/app/core/src/main/java/com/topjohnwu/magisk/core/AppContext.kt b/app/core/src/main/java/com/topjohnwu/magisk/core/AppContext.kt index 29e4c55ca..ff84f2dc4 100644 --- a/app/core/src/main/java/com/topjohnwu/magisk/core/AppContext.kt +++ b/app/core/src/main/java/com/topjohnwu/magisk/core/AppContext.kt @@ -1,5 +1,6 @@ package com.topjohnwu.magisk.core +import android.Manifest.permission.REQUEST_INSTALL_PACKAGES import android.app.Activity import android.app.Application import android.app.LocaleManager @@ -11,15 +12,24 @@ import android.os.Build import android.os.Build.VERSION.SDK_INT import android.os.Bundle import android.system.Os +import androidx.activity.ComponentActivity +import androidx.lifecycle.lifecycleScope import androidx.profileinstaller.ProfileInstaller import com.topjohnwu.magisk.StubApk +import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME +import com.topjohnwu.magisk.core.base.IActivityExtension import com.topjohnwu.magisk.core.base.UntrackedActivity +import com.topjohnwu.magisk.core.base.launchPackage +import com.topjohnwu.magisk.core.di.ServiceLocator +import com.topjohnwu.magisk.core.ktx.writeTo +import com.topjohnwu.magisk.core.tasks.HideAPK import com.topjohnwu.magisk.core.utils.LocaleSetting import com.topjohnwu.magisk.core.utils.NetworkObserver import com.topjohnwu.magisk.core.utils.ProcessLifecycle import com.topjohnwu.magisk.core.utils.RootUtils import com.topjohnwu.magisk.core.utils.ShellInit import com.topjohnwu.magisk.view.Notifications +import com.topjohnwu.magisk.view.Shortcuts import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.ipc.RootService @@ -28,6 +38,8 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.asExecutor import kotlinx.coroutines.launch import timber.log.Timber +import java.io.File +import java.io.IOException import java.lang.ref.WeakReference import kotlin.system.exitProcess @@ -39,7 +51,6 @@ object AppContext : ContextWrapper(null), val foregroundActivity: Activity? get() = ref.get() - @Volatile private var ref = WeakReference(null) private lateinit var application: Application @@ -130,3 +141,71 @@ object AppContext : ContextWrapper(null), override fun onLowMemory() {} override fun onTrimMemory(level: Int) {} } + +fun T.initializeOnSplashScreen(launchUi: Runnable) +where T : ComponentActivity, T : IActivityExtension { + val prevPkg = launchPackage + val prevConfig = intent.getBundleExtra(Const.Key.PREV_CONFIG) + val isPackageMigration = prevPkg != null && prevConfig != null + + Config.init(prevConfig) + + if (packageName != APP_PACKAGE_NAME) { + runCatching { + // Hidden, remove com.topjohnwu.magisk if exist as it could be malware + packageManager.getApplicationInfo(APP_PACKAGE_NAME, 0) + Shell.cmd("(pm uninstall $APP_PACKAGE_NAME)& >/dev/null 2>&1").exec() + } + } else { + if (Config.suManager.isNotEmpty()) { + Config.suManager = "" + } + if (isPackageMigration) { + Shell.cmd("(pm uninstall $prevPkg)& >/dev/null 2>&1").exec() + } + } + + if (isPackageMigration) { + runOnUiThread { + // Relaunch the process after package migration + StubApk.restartProcess(this) + } + return + } + + // Validate stub APK + if (isRunningAsStub && ( + // Version mismatch + Info.stub!!.version != BuildConfig.STUB_VERSION || + // Not properly patched + intent.component!!.className.contains(HideAPK.PLACEHOLDER)) + ) { + withPermission(REQUEST_INSTALL_PACKAGES) { granted -> + if (granted) { + lifecycleScope.launch(Dispatchers.IO) { + val apk = File(cacheDir, "stub.apk") + try { + assets.open("stub.apk").writeTo(apk) + HideAPK.upgrade(this@initializeOnSplashScreen, apk)?.let { + startActivity(it) + } + } catch (e: IOException) { + Timber.e(e) + } + } + } + } + return + } + + JobService.schedule(this) + Shortcuts.setupDynamic(this) + + // Pre-fetch network services + ServiceLocator.networkService + + // Wait for root service + RootUtils.Connection.await() + + runOnUiThread(launchUi) +}