From bce01c2f3aad505dcef153bcde4241b9375e7b8d Mon Sep 17 00:00:00 2001 From: KreitinnSoftware Date: Sun, 1 Sep 2024 22:31:58 -0300 Subject: [PATCH] Refactor ShellLoader, Using Class, This allows to bring more clean code, execute multiple processes on singles shell instead of creating one for one thing only, Improve CPU Viewer, Fix Behaviour of Exit Button --- .../emu/activities/EmulationActivity.kt | 6 +- .../micewine/emu/activities/MainActivity.kt | 35 +++--- .../com/micewine/emu/core/ShellExecutorCmd.kt | 118 +++++++----------- .../java/com/micewine/emu/core/WineWrapper.kt | 26 ++-- 4 files changed, 70 insertions(+), 115 deletions(-) diff --git a/app/src/main/java/com/micewine/emu/activities/EmulationActivity.kt b/app/src/main/java/com/micewine/emu/activities/EmulationActivity.kt index 8b0ef66..d84bf66 100644 --- a/app/src/main/java/com/micewine/emu/activities/EmulationActivity.kt +++ b/app/src/main/java/com/micewine/emu/activities/EmulationActivity.kt @@ -53,7 +53,7 @@ import com.micewine.emu.controller.ControllerUtils.checkControllerButtons import com.micewine.emu.controller.ControllerUtils.controllerMouseEmulation import com.micewine.emu.controller.ControllerUtils.prepareButtonsAxisValues import com.micewine.emu.core.ShellExecutorCmd -import com.micewine.emu.core.WineWrapper +import com.micewine.emu.core.WineWrapper.wineShell import com.micewine.emu.fragments.FloatingLogViewerFragment import com.micewine.emu.input.InputEventSender import com.micewine.emu.input.InputStub @@ -153,7 +153,9 @@ class EmulationActivity : AppCompatActivity(), View.OnApplyWindowInsetsListener R.id.exit -> { drawerLayout?.closeDrawers() - WineWrapper.wineServer("--kill") + wineShell.runCommand("pkill -9 wineserver") + wineShell.runCommand("pkill -9 .exe") + wineShell.runCommand("pkill -9 pulseaudio") val intent = Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT diff --git a/app/src/main/java/com/micewine/emu/activities/MainActivity.kt b/app/src/main/java/com/micewine/emu/activities/MainActivity.kt index 1c667bd..4682034 100644 --- a/app/src/main/java/com/micewine/emu/activities/MainActivity.kt +++ b/app/src/main/java/com/micewine/emu/activities/MainActivity.kt @@ -41,14 +41,15 @@ import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_D3DX_RENDE import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_DRIVER_KEY import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_DXVK_HUD_PRESET_KEY import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_DXVK_KEY +import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_GL_PROFILE_KEY import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_MESA_VK_WSI_PRESENT_MODE_KEY import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_TU_DEBUG_PRESET_KEY -import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_GL_PROFILE_KEY import com.micewine.emu.activities.GeneralSettings.Companion.SELECTED_WINED3D_KEY import com.micewine.emu.core.ObbExtractor.extractZip -import com.micewine.emu.core.ShellExecutorCmd.executeShell +import com.micewine.emu.core.ShellExecutorCmd.ShellLoader import com.micewine.emu.core.ShellExecutorCmd.executeShellWithOutput import com.micewine.emu.core.WineWrapper +import com.micewine.emu.core.WineWrapper.wineShell import com.micewine.emu.databinding.ActivityMainBinding import com.micewine.emu.fragments.DeleteGameItemFragment import com.micewine.emu.fragments.FileManagerFragment @@ -63,7 +64,6 @@ import com.micewine.emu.fragments.SetupFragment import com.micewine.emu.fragments.SetupFragment.Companion.dialogTitleText import com.micewine.emu.fragments.SetupFragment.Companion.progressBarIsIndeterminate import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File @@ -139,6 +139,7 @@ class MainActivity : AppCompatActivity() { private var bottomNavigation: BottomNavigationView? = null private var runningXServer = false + private val xServerShell = ShellLoader() private val homeFragment: HomeFragment = HomeFragment() private val settingsFragment: SettingsFragment = SettingsFragment() private val fileManagerFragment: FileManagerFragment = FileManagerFragment() @@ -388,9 +389,7 @@ class MainActivity : AppCompatActivity() { private suspend fun runWine(exePath: String, winePrefix: File) { withContext(Dispatchers.Default) { - lifecycleScope.launch { - WineWrapper.wineServerSuspend("--foreground --persistent") - } + WineWrapper.wineServer("--foreground --persistent") installDXWrapper(winePrefix) @@ -410,9 +409,8 @@ class MainActivity : AppCompatActivity() { runningXServer = true - executeShell( - "export CLASSPATH=${getClassPath(this@MainActivity)};" + - "/system/bin/app_process / com.micewine.emu.CmdEntryPoint $display", "XServer" + xServerShell.runCommand( + "env CLASSPATH=${getClassPath(this@MainActivity)} /system/bin/app_process / com.micewine.emu.CmdEntryPoint $display" ) } } @@ -437,8 +435,8 @@ class MainActivity : AppCompatActivity() { File("$appRootDir/wine-utils/CoreFonts").copyRecursively(File("$appRootDir/wine/share/wine/fonts"), true) - executeShellWithOutput("chmod 700 -R $appRootDir") - executeShellWithOutput("$usrDir/generateSymlinks.sh") + wineShell.runCommand("chmod 700 -R $appRootDir") + wineShell.runCommand("$usrDir/generateSymlinks.sh") File("$usrDir/icons").mkdirs() @@ -526,7 +524,7 @@ class MainActivity : AppCompatActivity() { File("$userSharedFolder/AppData").mkdirs() - executeShell("ln -sf $userSharedFolder/AppData $localAppData", "Symlink") + ShellLoader().runCommand("ln -sf $userSharedFolder/AppData $localAppData") startMenu.deleteRecursively() @@ -649,17 +647,14 @@ class MainActivity : AppCompatActivity() { suspend fun getCpuInfo() { withContext(Dispatchers.IO) { - var usageInfo: String - var usageProcessed: String + var usageInfo: Float while (enableCpuCounter) { - usageInfo = executeShellWithOutput("top -n 1 | grep user | head -n 1 | cut -d \"%\" -f 2 | sed \"s/cpu//g\"") - - usageProcessed = usageInfo.replace(" ", "").replace("\n", "") - - totalCpuUsage = "${(usageProcessed.toInt() / Runtime.getRuntime().availableProcessors())}%" + usageInfo = executeShellWithOutput("top -bn 1 -u \$(whoami) -o %CPU -q | head -n 1").toFloat() / Runtime.getRuntime().availableProcessors() - delay(750) + totalCpuUsage = "$usageInfo%" + + Thread.sleep(650) } } } diff --git a/app/src/main/java/com/micewine/emu/core/ShellExecutorCmd.kt b/app/src/main/java/com/micewine/emu/core/ShellExecutorCmd.kt index c1e0908..7865073 100644 --- a/app/src/main/java/com/micewine/emu/core/ShellExecutorCmd.kt +++ b/app/src/main/java/com/micewine/emu/core/ShellExecutorCmd.kt @@ -11,9 +11,8 @@ import java.io.IOException import java.io.InputStreamReader object ShellExecutorCmd { - fun executeShell(cmd: String, msg: String?) { + fun executeShellWithOutput(cmd: String): String { try { - Log.e(msg, "Trying to exec: $cmd") val shell = Runtime.getRuntime().exec("/system/bin/sh") val os = DataOutputStream(shell.outputStream) @@ -21,122 +20,91 @@ object ShellExecutorCmd { os.flush() val stdout = BufferedReader(InputStreamReader(shell.inputStream)) - val stderr = BufferedReader(InputStreamReader(shell.errorStream)) + BufferedReader(InputStreamReader(shell.errorStream)) + + var output = "" val stdoutThread = Thread { try { var stdOut: String? while (stdout.readLine().also { stdOut = it } != null) { - sharedLogs.appendText("$stdOut") - Log.v(msg, "$stdOut") + output += stdOut + "\n" } - } catch (e: IOException) { - Log.e(msg, "Error reading stdout", e) + } catch (_: IOException) { } finally { try { stdout.close() - } catch (e: IOException) { - Log.e(msg, "Error closing stdout", e) - } - } - } - - val stderrThread = Thread { - try { - var stdErr: String? - while (stderr.readLine().also { stdErr = it } != null) { - sharedLogs.appendText("$stdErr") - Log.v(msg, "$stdErr") - } - } catch (e: IOException) { - Log.e(msg, "Error reading stderr", e) - } finally { - try { - stderr.close() - } catch (e: IOException) { - Log.e(msg, "Error closing stderr", e) + } catch (_: IOException) { } } } stdoutThread.start() - stderrThread.start() stdoutThread.join() - stderrThread.join() os.close() shell.waitFor() shell.destroy() - } catch (e: IOException) { - Log.e(msg, "IOException occurred", e) - throw RuntimeException(e) - } catch (e: InterruptedException) { - Log.e(msg, "InterruptedException occurred", e) - Thread.currentThread().interrupt() - } - } - - fun executeShellWithOutput(cmd: String): String { - try { - val shell = Runtime.getRuntime().exec("/system/bin/sh") - val os = DataOutputStream(shell.outputStream) - os.writeBytes("$cmd\nexit\n") - os.flush() + return output + } catch (_: IOException) { + } - val stdout = BufferedReader(InputStreamReader(shell.inputStream)) - val stderr = BufferedReader(InputStreamReader(shell.errorStream)) + return "" + } - var output = "" + class ShellLoader { + var shell: Process? = Runtime.getRuntime().exec("/system/bin/sh") + var os: DataOutputStream? = DataOutputStream(shell?.outputStream) + var stdout: BufferedReader? = BufferedReader(InputStreamReader(shell?.inputStream)) + var stderr: BufferedReader? = BufferedReader(InputStreamReader(shell?.errorStream)) - val stdoutThread = Thread { + init { + Thread { try { var stdOut: String? - while (stdout.readLine().also { stdOut = it } != null) { - output += stdOut + "\n" + while ( stdout?.readLine().also { stdOut = it } != null) { + sharedLogs.appendText("$stdOut") + Log.v("ShellLoader", "$stdOut") } - } catch (_: IOException) { + } catch (e: IOException) { + Log.e("ShellLoader", "Error reading stdout", e) } finally { try { - stdout.close() - } catch (_: IOException) { + stdout?.close() + } catch (e: IOException) { + Log.e("ShellLoader", "Error closing stdout", e) } } - } + }.start() - val stderrThread = Thread { + Thread { try { var stdErr: String? - while (stderr.readLine().also { stdErr = it } != null) { - output += stdErr + "\n" + while (stderr?.readLine().also { stdErr = it } != null) { + sharedLogs.appendText("$stdErr") + Log.v("ShellLoader", "$stdErr") } - } catch (_: IOException) { + } catch (e: IOException) { + Log.e("ShellLoader", "Error reading stderr", e) } finally { try { - stderr.close() - } catch (_: IOException) { + stderr?.close() + } catch (e: IOException) { + Log.e("ShellLoader", "Error closing stderr", e) } } - } - - stdoutThread.start() - stderrThread.start() - - stdoutThread.join() - stderrThread.join() - - os.close() + }.start() + } - shell.waitFor() - shell.destroy() + fun runCommand(cmd: String): Int { + os?.writeBytes("$cmd &\n") + os?.flush() - return output - } catch (_: IOException) { + return -1 } - - return "0" } class ViewModelAppLogs : ViewModel() { diff --git a/app/src/main/java/com/micewine/emu/core/WineWrapper.kt b/app/src/main/java/com/micewine/emu/core/WineWrapper.kt index 6c3cb1f..a16087d 100644 --- a/app/src/main/java/com/micewine/emu/core/WineWrapper.kt +++ b/app/src/main/java/com/micewine/emu/core/WineWrapper.kt @@ -4,45 +4,35 @@ import android.os.Build import com.micewine.emu.activities.MainActivity.Companion.appRootDir import com.micewine.emu.activities.MainActivity.Companion.usrDir import com.micewine.emu.core.EnvVars.getEnv -import com.micewine.emu.core.ShellExecutorCmd.executeShell -import com.micewine.emu.core.ShellExecutorCmd.executeShellWithOutput -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import com.micewine.emu.core.ShellExecutorCmd.ShellLoader import java.io.File object WineWrapper { private var IS_BOX64 = if (Build.SUPPORTED_ABIS[0] == "x86_64") "" else "$usrDir/bin/box64" + var wineShell = ShellLoader() fun wineServer(args: String) { - executeShellWithOutput( + wineShell.runCommand( getEnv() + "$IS_BOX64 $appRootDir/wine/bin/wineserver $args" ) } - suspend fun wineServerSuspend(args: String) { - withContext(Dispatchers.Default) { - executeShell( - getEnv() + "$IS_BOX64 $appRootDir/wine/bin/wineserver $args", "WineServer" - ) - } - } - fun wine(args: String, winePrefix: File) { - executeShell( - getEnv() + "WINEPREFIX=$winePrefix $IS_BOX64 $appRootDir/wine/bin/wine $args", "WineProcess" + wineShell.runCommand( + getEnv() + "WINEPREFIX=$winePrefix $IS_BOX64 $appRootDir/wine/bin/wine $args" ) } fun wine(args: String, winePrefix: File, cwd: String) { - executeShell( + wineShell.runCommand( "cd $cwd;" + - getEnv() + "WINEPREFIX=$winePrefix $IS_BOX64 $appRootDir/wine/bin/wine $args", "WineProcess" + getEnv() + "WINEPREFIX=$winePrefix $IS_BOX64 $appRootDir/wine/bin/wine $args" ) } fun extractIcon(exeFile: File, output: String) { if (exeFile.name.endsWith(".exe")) { - executeShellWithOutput( + wineShell.runCommand( getEnv() + "$usrDir/bin/wrestool -x -t 14 '${exeFile.path}' > '$output'" ) }