From da5aa70fc940c3f0feec3bf83acab233c84966d7 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Sat, 17 Feb 2024 23:10:10 -0500 Subject: [PATCH] android: Port yuzu system info logging (#7431) --- .../org/citra/citra_emu/CitraApplication.kt | 14 +++ .../java/org/citra/citra_emu/NativeLibrary.kt | 4 +- .../utils/DirectoryInitialization.kt | 6 +- .../java/org/citra/citra_emu/utils/Log.kt | 27 +---- .../org/citra/citra_emu/utils/MemoryUtil.kt | 108 ++++++++++++++++++ src/android/app/src/main/jni/CMakeLists.txt | 1 + src/android/app/src/main/jni/native_log.cpp | 30 +++++ .../app/src/main/res/values/strings.xml | 11 ++ 8 files changed, 174 insertions(+), 27 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/utils/MemoryUtil.kt create mode 100644 src/android/app/src/main/jni/native_log.cpp diff --git a/src/android/app/src/main/java/org/citra/citra_emu/CitraApplication.kt b/src/android/app/src/main/java/org/citra/citra_emu/CitraApplication.kt index c414d4246..75a88baf1 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/CitraApplication.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/CitraApplication.kt @@ -9,10 +9,13 @@ import android.app.Application import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context +import android.os.Build import org.citra.citra_emu.utils.DirectoryInitialization import org.citra.citra_emu.utils.DocumentsTree import org.citra.citra_emu.utils.GpuDriverHelper import org.citra.citra_emu.utils.PermissionsHandler +import org.citra.citra_emu.utils.Log +import org.citra.citra_emu.utils.MemoryUtil class CitraApplication : Application() { private fun createNotificationChannel() { @@ -53,9 +56,20 @@ class CitraApplication : Application() { } NativeLibrary.logDeviceInfo() + logDeviceInfo() createNotificationChannel() } + fun logDeviceInfo() { + Log.info("Device Manufacturer - ${Build.MANUFACTURER}") + Log.info("Device Model - ${Build.MODEL}") + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) { + Log.info("SoC Manufacturer - ${Build.SOC_MANUFACTURER}") + Log.info("SoC Model - ${Build.SOC_MODEL}") + } + Log.info("Total System Memory - ${MemoryUtil.getDeviceRAM()}") + } + companion object { private var application: CitraApplication? = null diff --git a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt index 75150fd16..bfbe658f8 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt @@ -413,12 +413,12 @@ object NativeLibrary { } fun setEmulationActivity(emulationActivity: EmulationActivity?) { - Log.verbose("[NativeLibrary] Registering EmulationActivity.") + Log.debug("[NativeLibrary] Registering EmulationActivity.") sEmulationActivity = WeakReference(emulationActivity) } fun clearEmulationActivity() { - Log.verbose("[NativeLibrary] Unregistering EmulationActivity.") + Log.debug("[NativeLibrary] Unregistering EmulationActivity.") sEmulationActivity.clear() } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.kt index 10e509f23..c48f9d22e 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.kt @@ -94,14 +94,14 @@ object DirectoryInitialization { val dataPath = PermissionsHandler.citraDirectory if (dataPath.toString().isNotEmpty()) { userPath = dataPath.toString() - Log.debug("[DirectoryInitialization] User Dir: $userPath") + android.util.Log.d("[Citra Frontend]", "[DirectoryInitialization] User Dir: $userPath") return true } return false } private fun copyAsset(asset: String, output: File, overwrite: Boolean, context: Context) { - Log.verbose("[DirectoryInitialization] Copying File $asset to $output") + Log.debug("[DirectoryInitialization] Copying File $asset to $output") try { if (!output.exists() || overwrite) { val inputStream = context.assets.open(asset) @@ -121,7 +121,7 @@ object DirectoryInitialization { overwrite: Boolean, context: Context ) { - Log.verbose("[DirectoryInitialization] Copying Folder $assetFolder to $outputFolder") + Log.debug("[DirectoryInitialization] Copying Folder $assetFolder to $outputFolder") try { var createdFolder = false for (file in context.assets.list(assetFolder)!!) { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/Log.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/Log.kt index 26c41bc98..f691d51b0 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/Log.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/Log.kt @@ -4,34 +4,17 @@ package org.citra.citra_emu.utils -import android.util.Log -import org.citra.citra_emu.BuildConfig - -/** - * Contains methods that call through to [android.util.Log], but - * with the same TAG automatically provided. Also no-ops VERBOSE and DEBUG log - * levels in release builds. - */ object Log { // Tracks whether we should share the old log or the current log var gameLaunched = false - private const val TAG = "Citra Frontend" - fun verbose(message: String?) { - if (BuildConfig.DEBUG) { - Log.v(TAG, message!!) - } - } + external fun debug(message: String) - fun debug(message: String?) { - if (BuildConfig.DEBUG) { - Log.d(TAG, message!!) - } - } + external fun warning(message: String) - fun info(message: String?) = Log.i(TAG, message!!) + external fun info(message: String) - fun warning(message: String?) = Log.w(TAG, message!!) + external fun error(message: String) - fun error(message: String?) = Log.e(TAG, message!!) + external fun critical(message: String) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/MemoryUtil.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/MemoryUtil.kt new file mode 100644 index 000000000..4bf1d88c7 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/MemoryUtil.kt @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.citra.citra_emu.utils + +import android.app.ActivityManager +import android.content.Context +import android.os.Build +import org.citra.citra_emu.CitraApplication +import org.citra.citra_emu.R +import java.util.Locale +import kotlin.math.ceil + +object MemoryUtil { + private val context get() = CitraApplication.appContext + + private val Float.hundredths: String + get() = String.format(Locale.ROOT, "%.2f", this) + + const val Kb: Float = 1024F + const val Mb = Kb * 1024 + const val Gb = Mb * 1024 + const val Tb = Gb * 1024 + const val Pb = Tb * 1024 + const val Eb = Pb * 1024 + + fun bytesToSizeUnit(size: Float, roundUp: Boolean = false): String = + when { + size < Kb -> { + context.getString( + R.string.memory_formatted, + size.hundredths, + context.getString(R.string.memory_byte_shorthand) + ) + } + size < Mb -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Kb) else (size / Kb).hundredths, + context.getString(R.string.memory_kilobyte) + ) + } + size < Gb -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Mb) else (size / Mb).hundredths, + context.getString(R.string.memory_megabyte) + ) + } + size < Tb -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Gb) else (size / Gb).hundredths, + context.getString(R.string.memory_gigabyte) + ) + } + size < Pb -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Tb) else (size / Tb).hundredths, + context.getString(R.string.memory_terabyte) + ) + } + size < Eb -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Pb) else (size / Pb).hundredths, + context.getString(R.string.memory_petabyte) + ) + } + else -> { + context.getString( + R.string.memory_formatted, + if (roundUp) ceil(size / Eb) else (size / Eb).hundredths, + context.getString(R.string.memory_exabyte) + ) + } + } + + val totalMemory: Float + get() { + val memInfo = ActivityManager.MemoryInfo() + with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) { + getMemoryInfo(memInfo) + } + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + memInfo.advertisedMem.toFloat() + } else { + memInfo.totalMem.toFloat() + } + } + + fun isLessThan(minimum: Int, size: Float): Boolean = + when (size) { + Kb -> totalMemory < Mb && totalMemory < minimum + Mb -> totalMemory < Gb && (totalMemory / Mb) < minimum + Gb -> totalMemory < Tb && (totalMemory / Gb) < minimum + Tb -> totalMemory < Pb && (totalMemory / Tb) < minimum + Pb -> totalMemory < Eb && (totalMemory / Pb) < minimum + Eb -> totalMemory / Eb < minimum + else -> totalMemory < Kb && totalMemory < minimum + } + + // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for + // the potential error created by memInfo.totalMem + fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory, true) +} diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 84a34441a..233d568ed 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(citra-android SHARED ndk_motion.cpp ndk_motion.h system_save_game.cpp + native_log.cpp ) target_link_libraries(citra-android PRIVATE audio_core citra_common citra_core input_common network) diff --git a/src/android/app/src/main/jni/native_log.cpp b/src/android/app/src/main/jni/native_log.cpp new file mode 100644 index 000000000..86a57b99f --- /dev/null +++ b/src/android/app/src/main/jni/native_log.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include "android_common/android_common.h" + +extern "C" { + +void Java_org_citra_citra_1emu_utils_Log_debug(JNIEnv* env, jobject obj, jstring jmessage) { + LOG_DEBUG(Frontend, "{}", GetJString(env, jmessage)); +} + +void Java_org_citra_citra_1emu_utils_Log_warning(JNIEnv* env, jobject obj, jstring jmessage) { + LOG_WARNING(Frontend, "{}", GetJString(env, jmessage)); +} + +void Java_org_citra_citra_1emu_utils_Log_info(JNIEnv* env, jobject obj, jstring jmessage) { + LOG_INFO(Frontend, "{}", GetJString(env, jmessage)); +} + +void Java_org_citra_citra_1emu_utils_Log_error(JNIEnv* env, jobject obj, jstring jmessage) { + LOG_ERROR(Frontend, "{}", GetJString(env, jmessage)); +} + +void Java_org_citra_citra_1emu_utils_Log_critical(JNIEnv* env, jobject obj, jstring jmessage) { + LOG_CRITICAL(Frontend, "{}", GetJString(env, jmessage)); +} + +} // extern "C" diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 303632162..781e78da1 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -442,6 +442,17 @@ \"%s\" must be decrypted before being used with Citra.\n A real 3DS is required An unknown error occurred while installing \"%s\".\n Please see the log for more details + + %1$s %2$s + Byte + B + KB + MB + GB + TB + PB + EB + Change Theme Mode Follow System