diff --git a/app/src/main/cpp/emu_jni.cpp b/app/src/main/cpp/emu_jni.cpp index 4a6a06eb..75c56ee3 100644 --- a/app/src/main/cpp/emu_jni.cpp +++ b/app/src/main/cpp/emu_jni.cpp @@ -62,7 +62,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_SkylineApplication_initializeLog( ) { std::string appFilesPath{env->GetStringUTFChars(appFilesPathJstring, nullptr)}; skyline::Logger::configLevel = static_cast(logLevel); - skyline::Logger::LoaderContext.Initialize(appFilesPath + "loader.sklog"); + skyline::Logger::LoaderContext.Initialize(appFilesPath + "logs/loader.sklog"); } extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( @@ -73,7 +73,8 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( jint romFd, jint preferenceFd, jint systemLanguage, - jstring appFilesPathJstring, + jstring publicAppFilesPathJstring, + jstring privateAppFilesPathJstring, jstring nativeLibraryPathJstring, jobject assetManager ) { @@ -87,8 +88,8 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( auto settings{std::make_shared(preferenceFd)}; close(preferenceFd); - skyline::JniString appFilesPath(env, appFilesPathJstring); - skyline::Logger::EmulationContext.Initialize(appFilesPath + "emulation.sklog"); + skyline::JniString publicAppFilesPath(env, publicAppFilesPathJstring); + skyline::Logger::EmulationContext.Initialize(publicAppFilesPath + "logs/emulation.sklog"); auto start{std::chrono::steady_clock::now()}; @@ -100,11 +101,13 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( try { skyline::JniString nativeLibraryPath(env, nativeLibraryPathJstring); + skyline::JniString privateAppFilesPath{env, privateAppFilesPathJstring}; auto os{std::make_shared( jvmManager, settings, - appFilesPath, + publicAppFilesPath, + privateAppFilesPath, nativeLibraryPath, GetTimeZoneName(), static_cast(systemLanguage), diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 07267627..0f4f6663 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -218,7 +218,7 @@ namespace skyline::gpu { ADRENOTOOLS_DRIVER_CUSTOM, nullptr, // We require Android 10 so don't need to supply state.os->nativeLibraryPath.c_str(), - (state.os->appFilesPath + "turnip/").c_str(), + (state.os->publicAppFilesPath + "gpu/turnip/").c_str(), "libvulkan_freedreno.so", nullptr)}; if (!libvulkanHandle) { @@ -228,7 +228,7 @@ namespace skyline::gpu { state.os->nativeLibraryPath.c_str(), nullptr, nullptr, - (state.os->appFilesPath + "vk_file_redirect/").c_str()); + (state.os->publicAppFilesPath + "gpu/vk_file_redirect/").c_str()); if (!libvulkanHandle) libvulkanHandle = dlopen("libvulkan.so", RTLD_NOW); } diff --git a/app/src/main/cpp/skyline/os.cpp b/app/src/main/cpp/skyline/os.cpp index 395e796c..1c0d1ba5 100644 --- a/app/src/main/cpp/skyline/os.cpp +++ b/app/src/main/cpp/skyline/os.cpp @@ -16,13 +16,15 @@ namespace skyline::kernel { OS::OS( std::shared_ptr &jvmManager, std::shared_ptr &settings, - std::string appFilesPath, + std::string publicAppFilesPath, + std::string privateAppFilesPath, std::string nativeLibraryPath, std::string deviceTimeZone, language::SystemLanguage systemLanguage, std::shared_ptr assetFileSystem) : nativeLibraryPath(std::move(nativeLibraryPath)), - appFilesPath(std::move(appFilesPath)), + publicAppFilesPath(std::move(publicAppFilesPath)), + privateAppFilesPath(std::move(privateAppFilesPath)), state(this, jvmManager, settings), deviceTimeZone(std::move(deviceTimeZone)), assetFileSystem(std::move(assetFileSystem)), @@ -31,7 +33,7 @@ namespace skyline::kernel { void OS::Execute(int romFd, loader::RomFormat romType) { auto romFile{std::make_shared(romFd)}; - auto keyStore{std::make_shared(appFilesPath)}; + auto keyStore{std::make_shared(privateAppFilesPath + "keys/")}; state.loader = [&]() -> std::shared_ptr { switch (romType) { diff --git a/app/src/main/cpp/skyline/os.h b/app/src/main/cpp/skyline/os.h index e854d3ef..0ed1ec65 100644 --- a/app/src/main/cpp/skyline/os.h +++ b/app/src/main/cpp/skyline/os.h @@ -15,7 +15,8 @@ namespace skyline::kernel { class OS { public: std::string nativeLibraryPath; //!< The full path to the app's native library directory - std::string appFilesPath; //!< The full path to the app's files directory + std::string publicAppFilesPath; //!< The full path to the app's public files directory + std::string privateAppFilesPath; //!< The full path to the app's private files directory DeviceState state; std::string deviceTimeZone; //!< The timezone name (e.g. Europe/London) std::shared_ptr assetFileSystem; //!< A filesystem to be used for accessing emulator assets (like tzdata) @@ -29,7 +30,8 @@ namespace skyline::kernel { OS( std::shared_ptr &jvmManager, std::shared_ptr &settings, - std::string appFilesPath, + std::string publicAppFilesPath, + std::string privateAppFilesPath, std::string deviceTimeZone, std::string nativeLibraryPath, language::SystemLanguage systemLanguage, diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp index 13ffff5d..3c44d444 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp @@ -17,7 +17,7 @@ namespace skyline::service::fssrv { } Result IFileSystemProxy::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - manager.RegisterService(std::make_shared(std::make_shared(state.os->appFilesPath + "/switch/sdmc/"), state, manager), session, response); + manager.RegisterService(std::make_shared(std::make_shared(state.os->publicAppFilesPath + "/switch/sdmc/"), state, manager), session, response); return {}; } @@ -57,7 +57,7 @@ namespace skyline::service::fssrv { } }()}; - manager.RegisterService(std::make_shared(std::make_shared(state.os->appFilesPath + "/switch" + saveDataPath), state, manager), session, response); + manager.RegisterService(std::make_shared(std::make_shared(state.os->publicAppFilesPath + "/switch" + saveDataPath), state, manager), session, response); return {}; } diff --git a/app/src/main/cpp/skyline/services/pl/shared_font_core.h b/app/src/main/cpp/skyline/services/pl/shared_font_core.h index 32c879bc..7cfcc49f 100644 --- a/app/src/main/cpp/skyline/services/pl/shared_font_core.h +++ b/app/src/main/cpp/skyline/services/pl/shared_font_core.h @@ -37,7 +37,7 @@ namespace skyline::service::pl { constexpr u32 SharedFontMagic{0x36F81A1E}; //!< The encrypted magic for a single font in the shared font data constexpr u32 SharedFontKey{SharedFontMagic ^ SharedFontResult}; //!< The XOR key for encrypting the font size - auto fontsDirectory{std::make_shared(state.os->appFilesPath + "fonts/")}; + auto fontsDirectory{std::make_shared(state.os->publicAppFilesPath + "fonts/")}; auto ptr{reinterpret_cast(sharedFontMemory->host.ptr)}; for (auto &font : fonts) { *ptr++ = 0x18029a7f; diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index 477516e9..19e1e9a7 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -75,11 +75,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo * @param romType The type of the ROM as an enum value * @param romFd The file descriptor of the ROM object * @param preferenceFd The file descriptor of the Preference XML - * @param appFilesPath The full path to the app files directory + * @param publicAppFilesPath The full path to the public app files directory + * @param privateAppFilesPath The full path to the private app files directory * @param nativeLibraryPath The full path to the app native library directory * @param assetManager The asset manager used for accessing app assets */ - private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, language : Int, appFilesPath : String, nativeLibraryPath : String, assetManager : AssetManager) + private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, language : Int, publicAppFilesPath : String, privateAppFilesPath : String, nativeLibraryPath : String, assetManager : AssetManager) /** * @param join If the function should only return after all the threads join or immediately @@ -218,7 +219,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo val preferenceFd = ParcelFileDescriptor.open(File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml"), ParcelFileDescriptor.MODE_READ_WRITE) emulationThread = Thread { - executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), settings.systemLanguage, applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets) + executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), settings.systemLanguage, applicationContext.getPublicFilesDir().canonicalPath + "/", applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets) returnFromEmulation() } diff --git a/app/src/main/java/emu/skyline/KeyReader.kt b/app/src/main/java/emu/skyline/KeyReader.kt index c816f1ea..e881fdce 100644 --- a/app/src/main/java/emu/skyline/KeyReader.kt +++ b/app/src/main/java/emu/skyline/KeyReader.kt @@ -45,7 +45,10 @@ object KeyReader { if (!DocumentFile.isDocumentUri(context, uri)) return false - val tmpOutputFile = File("${context.filesDir.canonicalFile}/${keyType.fileName}.tmp") + val outputDirectory = File("${context.filesDir.canonicalFile}/keys/") + if (!outputDirectory.exists()) + outputDirectory.mkdirs() + val tmpOutputFile = File(outputDirectory, "${keyType.fileName}.tmp") context.contentResolver.openInputStream(uri).use { inputStream -> tmpOutputFile.bufferedWriter().use { writer -> diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index 4ef274d9..b91ddd8f 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -21,7 +21,6 @@ import androidx.core.content.res.use import androidx.core.graphics.drawable.toBitmap import androidx.core.view.isInvisible import androidx.core.view.isVisible -import androidx.core.view.size import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -130,13 +129,12 @@ class MainActivity : AppCompatActivity() { binding.searchBar.apply { binding.logIcon.setOnClickListener { - val file = applicationContext.filesDir.resolve("emulation.sklog") - if (file.length() != 0L) { + val file = applicationContext.getPublicFilesDir().resolve("logs/emulation.sklog") + if (file.exists() && file.length() != 0L) { val uri = FileProvider.getUriForFile(this@MainActivity, "skyline.emu.fileprovider", file) val intent = Intent(Intent.ACTION_SEND) - .setType("text/plain") + .setDataAndType(uri, "text/plain") .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .setData(uri) .putExtra(Intent.EXTRA_STREAM, uri) startActivity(Intent.createChooser(intent, getString(R.string.log_share_prompt))) } else { diff --git a/app/src/main/java/emu/skyline/SkylineApplication.kt b/app/src/main/java/emu/skyline/SkylineApplication.kt index 19533d15..d0b5c17f 100644 --- a/app/src/main/java/emu/skyline/SkylineApplication.kt +++ b/app/src/main/java/emu/skyline/SkylineApplication.kt @@ -6,8 +6,15 @@ package emu.skyline import android.app.Application +import android.content.Context import dagger.hilt.android.HiltAndroidApp import emu.skyline.di.getSettings +import java.io.File + +/** + * @return The optimal directory for putting public files inside, this may return a private directory if a public directory cannot be retrieved + */ +fun Context.getPublicFilesDir() : File = getExternalFilesDir(null) ?: filesDir @HiltAndroidApp class SkylineApplication : Application() { @@ -16,6 +23,9 @@ class SkylineApplication : Application() { override fun onCreate() { super.onCreate() System.loadLibrary("skyline") - initializeLog(applicationContext.filesDir.canonicalPath + "/", getSettings().logLevel.toInt()) + + val appFilesPath = applicationContext.getPublicFilesDir().canonicalPath + File("$appFilesPath/logs/").mkdirs() + initializeLog("$appFilesPath/", getSettings().logLevel.toInt()) } } diff --git a/app/src/main/java/emu/skyline/loader/RomFile.kt b/app/src/main/java/emu/skyline/loader/RomFile.kt index c4c18e11..644d8623 100644 --- a/app/src/main/java/emu/skyline/loader/RomFile.kt +++ b/app/src/main/java/emu/skyline/loader/RomFile.kt @@ -128,7 +128,7 @@ internal class RomFile(context : Context, format : RomFormat, uri : Uri, systemL init { context.contentResolver.openFileDescriptor(uri, "r")!!.use { - result = LoaderResult.get(populate(format.ordinal, it.fd, context.filesDir.canonicalPath + "/", systemLanguage)) + result = LoaderResult.get(populate(format.ordinal, it.fd, "${context.filesDir.canonicalPath}/keys/", systemLanguage)) } appEntry = applicationName?.let { name -> diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml index 4faddd29..5343ac84 100644 --- a/app/src/main/res/xml/filepaths.xml +++ b/app/src/main/res/xml/filepaths.xml @@ -1,4 +1,5 @@ - + +