mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 03:47:37 +00:00
Ensure RootService is launched
This commit is contained in:
parent
e67d0678f9
commit
f2c15c7701
@ -86,7 +86,7 @@ dependencies {
|
||||
implementation("${bindingAdapter}:${vBAdapt}")
|
||||
implementation("${bindingAdapter}-recyclerview:${vBAdapt}")
|
||||
|
||||
val vLibsu = "4.0.2"
|
||||
val vLibsu = "4.0.3"
|
||||
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
|
||||
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
||||
implementation("com.github.topjohnwu.libsu:service:${vLibsu}")
|
||||
|
@ -14,6 +14,7 @@ import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.JobService
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||
import com.topjohnwu.magisk.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.ui.theme.Theme
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
@ -104,6 +105,9 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
||||
|
||||
// Pre-fetch network services
|
||||
ServiceLocator.networkService
|
||||
|
||||
// Wait for root service
|
||||
RootUtils.Connection.await()
|
||||
}
|
||||
|
||||
private fun handleRepackage(pkg: String?) {
|
||||
|
@ -8,6 +8,7 @@ import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import com.topjohnwu.magisk.StubApk
|
||||
import com.topjohnwu.magisk.core.utils.*
|
||||
import com.topjohnwu.magisk.di.AppContext
|
||||
import com.topjohnwu.magisk.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@ -22,9 +23,9 @@ open class App() : Application() {
|
||||
constructor(o: Any) : this() {
|
||||
val data = StubApk.Data(o)
|
||||
// Add the root service name mapping
|
||||
data.classToComponent[RootRegistry::class.java.name] = data.rootService.name
|
||||
data.classToComponent[RootUtils::class.java.name] = data.rootService.name
|
||||
// Send back the actual root service class
|
||||
data.rootService = RootRegistry::class.java
|
||||
data.rootService = RootUtils::class.java
|
||||
Info.stub = data
|
||||
}
|
||||
|
||||
@ -38,43 +39,40 @@ open class App() : Application() {
|
||||
}
|
||||
|
||||
override fun attachBaseContext(context: Context) {
|
||||
Shell.setDefaultBuilder(Shell.Builder.create()
|
||||
.setFlags(Shell.FLAG_MOUNT_MASTER)
|
||||
.setInitializers(ShellInit::class.java)
|
||||
.setTimeout(2))
|
||||
Shell.EXECUTOR = DispatcherExecutor(Dispatchers.IO)
|
||||
|
||||
// Get the actual ContextImpl
|
||||
val app: Application
|
||||
val base: Context
|
||||
if (context is Application) {
|
||||
app = context
|
||||
base = context.baseContext
|
||||
AppApkPath = StubApk.current(base).path
|
||||
} else {
|
||||
app = this
|
||||
base = context
|
||||
AppApkPath = base.packageResourcePath
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
ServiceLocator.context = base
|
||||
|
||||
refreshLocale()
|
||||
AppApkPath = if (isRunningAsStub) {
|
||||
StubApk.current(base).path
|
||||
} else {
|
||||
base.packageResourcePath
|
||||
}
|
||||
|
||||
base.resources.patch()
|
||||
app.registerActivityLifecycleCallbacks(ActivityTracker)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
RootRegistry.bindTask = RootService.bindOrTask(
|
||||
intent<RootRegistry>(),
|
||||
Shell.setDefaultBuilder(Shell.Builder.create()
|
||||
.setFlags(Shell.FLAG_MOUNT_MASTER)
|
||||
.setInitializers(ShellInit::class.java)
|
||||
.setTimeout(2))
|
||||
Shell.EXECUTOR = DispatcherExecutor(Dispatchers.IO)
|
||||
RootUtils.bindTask = RootService.bindOrTask(
|
||||
intent<RootUtils>(),
|
||||
UiThreadHandler.executor,
|
||||
RootRegistry.Connection
|
||||
RootUtils.Connection
|
||||
)
|
||||
// Pre-heat the shell ASAP
|
||||
Shell.getShell(null) {}
|
||||
|
||||
refreshLocale()
|
||||
AppContext.resources.patch()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
|
@ -1,54 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ipc.RootService
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class RootRegistry(stub: Any?) : RootService() {
|
||||
|
||||
constructor() : this(null) {
|
||||
// Always log full stack trace with Timber
|
||||
Timber.plant(Timber.DebugTree())
|
||||
Thread.setDefaultUncaughtExceptionHandler { _, e ->
|
||||
Timber.e(e)
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
|
||||
private val className: String? = stub?.javaClass?.name
|
||||
|
||||
override fun onBind(intent: Intent): IBinder {
|
||||
// TODO: PLACEHOLDER
|
||||
return Binder()
|
||||
}
|
||||
|
||||
override fun getComponentName(): ComponentName {
|
||||
return ComponentName(packageName, className ?: javaClass.name)
|
||||
}
|
||||
|
||||
// TODO: PLACEHOLDER
|
||||
object Connection : CountDownLatch(1), ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
Timber.d("onServiceConnected")
|
||||
countDown()
|
||||
}
|
||||
override fun onNullBinding(name: ComponentName) {
|
||||
Timber.d("onServiceConnected")
|
||||
countDown()
|
||||
}
|
||||
override fun onServiceDisconnected(name: ComponentName) {
|
||||
bind(Intent().setComponent(name), this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var bindTask: Shell.Task? = null
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.topjohnwu.magisk.core.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import com.topjohnwu.superuser.ipc.RootService
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.locks.AbstractQueuedSynchronizer
|
||||
|
||||
class RootUtils(stub: Any?) : RootService() {
|
||||
|
||||
private val className: String = stub?.javaClass?.name ?: javaClass.name
|
||||
|
||||
constructor() : this(null) {
|
||||
Timber.plant(Timber.DebugTree())
|
||||
}
|
||||
|
||||
override fun getComponentName(): ComponentName {
|
||||
return ComponentName(packageName, className)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder {
|
||||
return Binder()
|
||||
}
|
||||
|
||||
object Connection : AbstractQueuedSynchronizer(), ServiceConnection {
|
||||
init {
|
||||
state = 1
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
Timber.d("onServiceConnected")
|
||||
obj = IRootUtils.Stub.asInterface(service)
|
||||
releaseShared(1)
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName) {
|
||||
state = 1
|
||||
obj = null
|
||||
bind(Intent().setComponent(name), this)
|
||||
}
|
||||
|
||||
override fun tryAcquireShared(acquires: Int) = if (state == 0) 1 else -1
|
||||
|
||||
override fun tryReleaseShared(releases: Int): Boolean {
|
||||
// Decrement count; signal when transition to zero
|
||||
while (true) {
|
||||
val c = state
|
||||
if (c == 0)
|
||||
return false
|
||||
val n = c - 1
|
||||
if (compareAndSetState(c, n))
|
||||
return n == 0
|
||||
}
|
||||
}
|
||||
|
||||
fun await() {
|
||||
// We cannot await on the main thread
|
||||
if (!ShellUtils.onMainThread())
|
||||
acquireSharedInterruptibly(1)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var bindTask: Shell.Task? = null
|
||||
var obj: IRootUtils? = null
|
||||
get() {
|
||||
Connection.await()
|
||||
return field
|
||||
}
|
||||
private set
|
||||
}
|
||||
}
|
@ -19,8 +19,8 @@ import java.util.jar.JarFile
|
||||
class ShellInit : Shell.Initializer() {
|
||||
override fun onInit(context: Context, shell: Shell): Boolean {
|
||||
if (shell.isRoot) {
|
||||
RootRegistry.bindTask?.let { shell.execTask(it) }
|
||||
RootRegistry.bindTask = null
|
||||
RootUtils.bindTask?.let { shell.execTask(it) }
|
||||
RootUtils.bindTask = null
|
||||
}
|
||||
shell.newJob().apply {
|
||||
add("export ASH_STANDALONE=1")
|
||||
|
Loading…
x
Reference in New Issue
Block a user