diff --git a/application/src/main/kotlin/com/baidaidai/rootless_store/application/execute/ExecutePluginByShizukuUseCase.kt b/application/src/main/kotlin/com/baidaidai/rootless_store/application/execute/ExecutePluginByShizukuUseCase.kt index ed148e21..7b9af21b 100644 --- a/application/src/main/kotlin/com/baidaidai/rootless_store/application/execute/ExecutePluginByShizukuUseCase.kt +++ b/application/src/main/kotlin/com/baidaidai/rootless_store/application/execute/ExecutePluginByShizukuUseCase.kt @@ -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 diff --git a/data/src/main/kotlin/com/baidaidai/rootless_store/data/execution/gateway/PluginExecutionGatewayImpl.kt b/data/src/main/kotlin/com/baidaidai/rootless_store/data/execution/gateway/PluginExecutionGatewayImpl.kt index e88d1763..dbccdb67 100644 --- a/data/src/main/kotlin/com/baidaidai/rootless_store/data/execution/gateway/PluginExecutionGatewayImpl.kt +++ b/data/src/main/kotlin/com/baidaidai/rootless_store/data/execution/gateway/PluginExecutionGatewayImpl.kt @@ -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 = 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() @@ -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) } @@ -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 @@ -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 ; echo PID:$$ ; exec ` + * + * @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 { + + val commandList = mutableListOf() + + commandList += shellExecutable + commandList += "-c" + commandList += listOf( + "cd $pluginPackageDirectory", + "echo PID:$$", + "exec $pluginEntryPoint" + ).joinToString(" ; ") + + return commandList + + } + }