mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	android: add logging
This commit is contained in:
		
							parent
							
								
									9848610ea2
								
							
						
					
					
						commit
						f767b5fdef
					
				
					 10 changed files with 160 additions and 30 deletions
				
			
		|  | @ -1,6 +1,9 @@ | |||
| cmake_minimum_required(VERSION 3.8) | ||||
| 
 | ||||
| add_library(citra-android SHARED | ||||
|             logging/log.cpp | ||||
|             logging/logcat_backend.cpp | ||||
|             logging/logcat_backend.h | ||||
|             native_interface.cpp | ||||
|             native_interface.h | ||||
|             ui/main/main_activity.cpp | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/android/app/src/main/cpp/logging/log.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/android/app/src/main/cpp/logging/log.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| #include "common/logging/log.h" | ||||
| #include "native_interface.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| extern "C" { | ||||
| JNICALL void Java_org_citra_1emu_citra_LOG_logEntry(JNIEnv* env, jclass type, jint level, | ||||
|                                                     jstring file_name, jint line_number, | ||||
|                                                     jstring function, jstring msg) { | ||||
|     using CitraJNI::GetJString; | ||||
|     FmtLogMessage(Class::Frontend, static_cast<Level>(level), GetJString(env, file_name).data(), | ||||
|                   static_cast<unsigned int>(line_number), GetJString(env, function).data(), | ||||
|                   GetJString(env, msg).data()); | ||||
| } | ||||
| } | ||||
| } // namespace Log
 | ||||
							
								
								
									
										38
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| // Copyright 2019 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <android/log.h> | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/text_formatter.h" | ||||
| #include "logcat_backend.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| void LogcatBackend::Write(const Entry& entry) { | ||||
|     android_LogPriority priority; | ||||
|     switch (entry.log_level) { | ||||
|     case Level::Trace: | ||||
|         priority = ANDROID_LOG_VERBOSE; | ||||
|         break; | ||||
|     case Level::Debug: | ||||
|         priority = ANDROID_LOG_DEBUG; | ||||
|         break; | ||||
|     case Level::Info: | ||||
|         priority = ANDROID_LOG_INFO; | ||||
|         break; | ||||
|     case Level::Warning: | ||||
|         priority = ANDROID_LOG_WARN; | ||||
|         break; | ||||
|     case Level::Error: | ||||
|         priority = ANDROID_LOG_ERROR; | ||||
|         break; | ||||
|     case Level::Critical: | ||||
|         priority = ANDROID_LOG_FATAL; | ||||
|         break; | ||||
|     case Level::Count: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
| 
 | ||||
|     __android_log_print(priority, "citra", "%s\n", FormatLogMessage(entry).c_str()); | ||||
| } | ||||
| } // namespace Log
 | ||||
							
								
								
									
										22
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| // Copyright 2019 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/logging/backend.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| class LogcatBackend : public Backend { | ||||
| public: | ||||
|     static const char* Name() { | ||||
|         return "Logcat"; | ||||
|     } | ||||
| 
 | ||||
|     const char* GetName() const override { | ||||
|         return Name(); | ||||
|     } | ||||
| 
 | ||||
|     void Write(const Entry& entry) override; | ||||
| }; | ||||
| } // namespace Log
 | ||||
|  | @ -2,14 +2,30 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/filter.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/settings.h" | ||||
| #include "logging/logcat_backend.h" | ||||
| #include "native_interface.h" | ||||
| 
 | ||||
| namespace MainActivity { | ||||
| extern "C" { | ||||
| JNICALL void Java_org_citra_1emu_citra_ui_main_MainActivity_initUserPath(JNIEnv* env, jclass type, | ||||
|                                                                          jstring path) { | ||||
|     FileUtil::SetUserPath(CitraJNI::GetJString(env, path)); | ||||
|     FileUtil::SetUserPath(CitraJNI::GetJString(env, path) + '/'); | ||||
| } | ||||
| 
 | ||||
| JNICALL void Java_org_citra_1emu_citra_ui_main_MainActivity_initLogging(JNIEnv* env, jclass type) { | ||||
|     Log::Filter log_filter(Log::Level::Debug); | ||||
|     log_filter.ParseFilterString(Settings::values.log_filter); | ||||
|     Log::SetGlobalFilter(log_filter); | ||||
| 
 | ||||
|     const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | ||||
|     FileUtil::CreateFullPath(log_dir); | ||||
|     Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | ||||
|     Log::AddBackend(std::make_unique<Log::LogcatBackend>()); | ||||
| } | ||||
| }; | ||||
| }; // namespace MainActivity
 | ||||
|  |  | |||
							
								
								
									
										41
									
								
								src/android/app/src/main/java/org/citra_emu/citra/LOG.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/android/app/src/main/java/org/citra_emu/citra/LOG.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| package org.citra_emu.citra; | ||||
| 
 | ||||
| public class LOG { | ||||
| 
 | ||||
|     private interface LOG_LEVEL { | ||||
|         int TRACE = 0, DEBUG = 1, INFO = 2, WARNING = 3, ERROR = 4, CRITICAL = 5; | ||||
|     } | ||||
| 
 | ||||
|     public static void TRACE(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.TRACE, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     public static void DEBUG(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.DEBUG, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     public static void INFO(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.INFO, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     public static void WARNING(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.WARNING, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     public static void ERROR(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.ERROR, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     public static void CRITICAL(String msg, Object... args) { | ||||
|         LOG(LOG_LEVEL.CRITICAL, msg, args); | ||||
|     } | ||||
| 
 | ||||
|     private static void LOG(int level, String msg, Object... args) { | ||||
|         StackTraceElement trace = Thread.currentThread().getStackTrace()[4]; | ||||
|         logEntry(level, trace.getFileName(), trace.getLineNumber(), trace.getMethodName(), | ||||
|                  String.format(msg, args)); | ||||
|     } | ||||
| 
 | ||||
|     private static native void logEntry(int level, String file_name, int line_number, | ||||
|                                         String function, String message); | ||||
| } | ||||
|  | @ -18,7 +18,7 @@ import org.citra_emu.citra.utils.PermissionUtil; | |||
| public final class MainActivity extends AppCompatActivity { | ||||
| 
 | ||||
|     // Java enums suck | ||||
|     private interface PermissionCodes { int INIT_USER_PATH = 0; } | ||||
|     private interface PermissionCodes { int INITIALIZE = 0; } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|  | @ -26,16 +26,17 @@ public final class MainActivity extends AppCompatActivity { | |||
|         setContentView(R.layout.activity_main); | ||||
| 
 | ||||
|         PermissionUtil.verifyPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, | ||||
|                                         PermissionCodes.INIT_USER_PATH); | ||||
|                                         PermissionCodes.INITIALIZE); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, | ||||
|                                            @NonNull int[] grantResults) { | ||||
|         switch (requestCode) { | ||||
|         case PermissionCodes.INIT_USER_PATH: | ||||
|         case PermissionCodes.INITIALIZE: | ||||
|             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { | ||||
|                 initUserPath(FileUtil.getUserPath().toString()); | ||||
|                 initLogging(); | ||||
|             } else { | ||||
|                 AlertDialog.Builder dialog = | ||||
|                     new AlertDialog.Builder(this) | ||||
|  | @ -45,7 +46,7 @@ public final class MainActivity extends AppCompatActivity { | |||
|                         .setPositiveButton("OK", (dialogInterface, which) -> { | ||||
|                             PermissionUtil.verifyPermission( | ||||
|                                 MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, | ||||
|                                 PermissionCodes.INIT_USER_PATH); | ||||
|                                 PermissionCodes.INITIALIZE); | ||||
|                         }); | ||||
|                 dialog.show(); | ||||
|             } | ||||
|  | @ -53,4 +54,5 @@ public final class MainActivity extends AppCompatActivity { | |||
|     } | ||||
| 
 | ||||
|     private static native void initUserPath(String path); | ||||
|     private static native void initLogging(); | ||||
| } | ||||
|  |  | |||
|  | @ -259,7 +259,7 @@ Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsign | |||
|     entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||||
|     entry.log_class = log_class; | ||||
|     entry.log_level = log_level; | ||||
|     entry.filename = Common::TrimSourcePath(filename); | ||||
|     entry.filename = Common::TrimSourcePath(filename, {R"(\.\.)", "src"}).data(); | ||||
|     entry.line_num = line_nr; | ||||
|     entry.function = function; | ||||
|     entry.message = std::move(message); | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <codecvt> | ||||
| #include <cstdlib> | ||||
| #include <locale> | ||||
| #include <regex> | ||||
| #include <sstream> | ||||
| #include "common/common_paths.h" | ||||
| #include "common/logging/log.h" | ||||
|  | @ -210,25 +211,17 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t | |||
|     return std::string(buffer, len); | ||||
| } | ||||
| 
 | ||||
| const char* TrimSourcePath(const char* path, const char* root) { | ||||
|     const char* p = path; | ||||
| 
 | ||||
|     while (*p != '\0') { | ||||
|         const char* next_slash = p; | ||||
|         while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') { | ||||
|             ++next_slash; | ||||
|         } | ||||
| 
 | ||||
|         bool is_src = Common::ComparePartialString(p, next_slash, root); | ||||
|         p = next_slash; | ||||
| 
 | ||||
|         if (*p != '\0') { | ||||
|             ++p; | ||||
|         } | ||||
|         if (is_src) { | ||||
|             path = p; | ||||
|         } | ||||
| std::string TrimSourcePath(const std::string& file_path, const std::vector<std::string>& roots) { | ||||
|     // match from beginning of path to dir sep
 | ||||
|     std::string regex_src = R"(.*([\/\\]|^)()"; | ||||
|     // plus the last occurrence of any root
 | ||||
|     for (auto root = roots.begin(); root < roots.end() - 1; ++root) { | ||||
|         regex_src += '(' + *root + ")|"; | ||||
|     } | ||||
|     return path; | ||||
|     regex_src += '(' + roots.back() + ')'; | ||||
|     // plus dir sep
 | ||||
|     regex_src += R"()[\/\\])"; | ||||
|     std::regex regex(regex_src); | ||||
|     return std::regex_replace(file_path, regex, ""); | ||||
| } | ||||
| } // namespace Common
 | ||||
|  |  | |||
|  | @ -69,11 +69,11 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t | |||
|  * intended to be used to strip a system-specific build directory from the `__FILE__` macro, | ||||
|  * leaving only the path relative to the sources root. | ||||
|  * | ||||
|  * @param path The input file path as a null-terminated string | ||||
|  * @param root The name of the root source directory as a null-terminated string. Path up to and | ||||
|  *             including the last occurrence of this name will be stripped | ||||
|  * @return A pointer to the same string passed as `path`, but starting at the trimmed portion | ||||
|  * @param path The input file path as a string | ||||
|  * @param roots The name of the root source directorys as a vector of strings. Path up to and | ||||
|  *             including the last occurrence of these names will be stripped | ||||
|  * @return The trimmed path as a string | ||||
|  */ | ||||
| const char* TrimSourcePath(const char* path, const char* root = "src"); | ||||
| std::string TrimSourcePath(const std::string& file_path, const std::vector<std::string>& roots); | ||||
| 
 | ||||
| } // namespace Common
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue