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'" ) }