Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class ExecutePluginByShizukuUseCase @Inject constructor(
val pluginManifest = pluginRepositoryImpl.findPlugin(pluginId)!!
val shouldMonitor = settingPreferencesRepositoryImpl.observePluginStatusNotificationEnabled().first()

// Dispatch to PluginExecutionGateway.executePluginWithoutEnvironmentByShizuku
// Dispatch to PluginExecutionGateway.executePluginByShizuku
var pidSaved = false
val pluginExecutionResult = pluginExecutionGatewayImpl.executePluginWithoutEnvironmentByShizuku(
val pluginExecutionResult = pluginExecutionGatewayImpl.executePluginByShizuku(
pluginEntryPoint = pluginManifest.entryPoint,
pluginDirectory = pluginManifest.pluginPackageName,
shouldMonitor = shouldMonitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,21 @@ class PluginExecutionGatewayImpl @Inject constructor(
private val pluginProcessMonitor: PluginProcessMonitor
) {

internal fun resolveLocalShellExecutable(): String{
val shell = Shell.getShell()
return if (shell.isRoot){
"su"
}else{
"sh"
}
}
fun executePluginEntryPoint(
pluginEntryPoint: String,
pluginPackageDirectory: String,
shouldMonitor: Boolean = false
): Flow<ExecutionResult> = callbackFlow {
val processBuilder = ProcessBuilder(
resolveLocalShellExecutable(), "-c", "cd $pluginPackageDirectory ;echo PID:$$;exec $pluginEntryPoint"

// Prepare Commands
val command = commandFactory(
shellExecutable = resolveLocalShellExecutable(),
pluginEntryPoint = pluginEntryPoint,
pluginPackageDirectory = pluginPackageDirectory
)
val processBuilder = ProcessBuilder(command)

// Prepare Environments
val environment = processBuilder.environment()

val oldPath = environment["PATH"].orEmpty()
Expand All @@ -55,8 +53,9 @@ class PluginExecutionGatewayImpl @Inject constructor(
Log.d("executePluginEntryPoint","environmentPath: $environmentPath")
Log.d("executePluginEntryPoint","environmentLdPath: $environmentLdPath")

// Start Process and
// register monitor
val process = processBuilder.start()

if (shouldMonitor){
pluginProcessMonitor(process)
}
Expand Down Expand Up @@ -86,10 +85,10 @@ class PluginExecutionGatewayImpl @Inject constructor(

awaitClose {
}
}
.flowOn(Dispatchers.IO)

fun executePluginWithoutEnvironmentByShizuku(
}.flowOn(Dispatchers.IO)

fun executePluginByShizuku(
pluginDirectory: String,
pluginEntryPoint: String,
shouldMonitor: Boolean
Expand Down Expand Up @@ -148,4 +147,54 @@ class PluginExecutionGatewayImpl @Inject constructor(
}
}

/**
* Shizuku 是例外,因为普通 process 无法直接调用
*
*需要通过 Binder, 所以判断也没有意义,这里不做判断
*/
fun resolveLocalShellExecutable(): String{
val shell = Shell.getShell()
return if (shell.isRoot){
"su"
}else{
"sh"
}
}

/**
* 构造供 [ProcessBuilder] 使用的命令参数列表。
*
* 该方法只负责根据传入的 Shell、插件入口点以及插件目录组装命令,
* 不负责启动进程或配置运行环境。
*
* 最终返回的参数列表通常形如:`sh -c cd <pluginPackageDirectory> ; echo PID:$$ ; exec <pluginEntryPoint>`
*
* @param shellExecutable 用于执行命令的 Shell 可执行文件,例如 `sh` 或 `su`。
* @param pluginEntryPoint 插件的可执行入口点。
* @param pluginPackageDirectory 插件所在目录,同时作为执行时的工作目录。
* @return 可直接传递给 [ProcessBuilder] 的命令参数列表。
*
* @since 2026-10-03
* @lastModified 2026-10-03
*/
fun commandFactory(
shellExecutable: String,
pluginEntryPoint: String,
pluginPackageDirectory: String,
): List<String> {

val commandList = mutableListOf<String>()

commandList += shellExecutable
commandList += "-c"
commandList += listOf(
"cd $pluginPackageDirectory",
"echo PID:$$",
"exec $pluginEntryPoint"
).joinToString(" ; ")

return commandList

}

}
Loading