mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 07:37:39 +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}:${vBAdapt}")
|
||||||
implementation("${bindingAdapter}-recyclerview:${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:core:${vLibsu}")
|
||||||
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
||||||
implementation("com.github.topjohnwu.libsu:service:${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.JobService
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||||
|
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||||
import com.topjohnwu.magisk.di.ServiceLocator
|
import com.topjohnwu.magisk.di.ServiceLocator
|
||||||
import com.topjohnwu.magisk.ui.theme.Theme
|
import com.topjohnwu.magisk.ui.theme.Theme
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
@ -104,6 +105,9 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
|
|
||||||
// Pre-fetch network services
|
// Pre-fetch network services
|
||||||
ServiceLocator.networkService
|
ServiceLocator.networkService
|
||||||
|
|
||||||
|
// Wait for root service
|
||||||
|
RootUtils.Connection.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRepackage(pkg: String?) {
|
private fun handleRepackage(pkg: String?) {
|
||||||
|
@ -8,6 +8,7 @@ import android.content.res.Configuration
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.topjohnwu.magisk.StubApk
|
import com.topjohnwu.magisk.StubApk
|
||||||
import com.topjohnwu.magisk.core.utils.*
|
import com.topjohnwu.magisk.core.utils.*
|
||||||
|
import com.topjohnwu.magisk.di.AppContext
|
||||||
import com.topjohnwu.magisk.di.ServiceLocator
|
import com.topjohnwu.magisk.di.ServiceLocator
|
||||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -22,9 +23,9 @@ open class App() : Application() {
|
|||||||
constructor(o: Any) : this() {
|
constructor(o: Any) : this() {
|
||||||
val data = StubApk.Data(o)
|
val data = StubApk.Data(o)
|
||||||
// Add the root service name mapping
|
// 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
|
// Send back the actual root service class
|
||||||
data.rootService = RootRegistry::class.java
|
data.rootService = RootUtils::class.java
|
||||||
Info.stub = data
|
Info.stub = data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,43 +39,40 @@ open class App() : Application() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(context: Context) {
|
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
|
// Get the actual ContextImpl
|
||||||
val app: Application
|
val app: Application
|
||||||
val base: Context
|
val base: Context
|
||||||
if (context is Application) {
|
if (context is Application) {
|
||||||
app = context
|
app = context
|
||||||
base = context.baseContext
|
base = context.baseContext
|
||||||
|
AppApkPath = StubApk.current(base).path
|
||||||
} else {
|
} else {
|
||||||
app = this
|
app = this
|
||||||
base = context
|
base = context
|
||||||
|
AppApkPath = base.packageResourcePath
|
||||||
}
|
}
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
ServiceLocator.context = base
|
ServiceLocator.context = base
|
||||||
|
|
||||||
refreshLocale()
|
|
||||||
AppApkPath = if (isRunningAsStub) {
|
|
||||||
StubApk.current(base).path
|
|
||||||
} else {
|
|
||||||
base.packageResourcePath
|
|
||||||
}
|
|
||||||
|
|
||||||
base.resources.patch()
|
|
||||||
app.registerActivityLifecycleCallbacks(ActivityTracker)
|
app.registerActivityLifecycleCallbacks(ActivityTracker)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
RootRegistry.bindTask = RootService.bindOrTask(
|
Shell.setDefaultBuilder(Shell.Builder.create()
|
||||||
intent<RootRegistry>(),
|
.setFlags(Shell.FLAG_MOUNT_MASTER)
|
||||||
|
.setInitializers(ShellInit::class.java)
|
||||||
|
.setTimeout(2))
|
||||||
|
Shell.EXECUTOR = DispatcherExecutor(Dispatchers.IO)
|
||||||
|
RootUtils.bindTask = RootService.bindOrTask(
|
||||||
|
intent<RootUtils>(),
|
||||||
UiThreadHandler.executor,
|
UiThreadHandler.executor,
|
||||||
RootRegistry.Connection
|
RootUtils.Connection
|
||||||
)
|
)
|
||||||
|
// Pre-heat the shell ASAP
|
||||||
|
Shell.getShell(null) {}
|
||||||
|
|
||||||
|
refreshLocale()
|
||||||
|
AppContext.resources.patch()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
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() {
|
class ShellInit : Shell.Initializer() {
|
||||||
override fun onInit(context: Context, shell: Shell): Boolean {
|
override fun onInit(context: Context, shell: Shell): Boolean {
|
||||||
if (shell.isRoot) {
|
if (shell.isRoot) {
|
||||||
RootRegistry.bindTask?.let { shell.execTask(it) }
|
RootUtils.bindTask?.let { shell.execTask(it) }
|
||||||
RootRegistry.bindTask = null
|
RootUtils.bindTask = null
|
||||||
}
|
}
|
||||||
shell.newJob().apply {
|
shell.newJob().apply {
|
||||||
add("export ASH_STANDALONE=1")
|
add("export ASH_STANDALONE=1")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user