From b45437b78b1c1374a29e6b7887939289d9a0e7e7 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Wed, 6 Apr 2022 11:18:26 +0530 Subject: [PATCH] Move Skyline internal files to external directory Any Skyline files that should have been user-accessible were moved from `/data/data/skyline.emu/files` to `/sdcard/Android/data/skyline.emu/files` as the former directory is entirely private and cannot be accessed without either adb or root. This made retrieving certain data such as saves or loading custom driver shared objects extremely hard to do while this can be trivially done now. --- app/src/main/cpp/emu_jni.cpp | 13 ++++++++----- app/src/main/cpp/skyline/gpu.cpp | 4 ++-- app/src/main/cpp/skyline/os.cpp | 8 +++++--- app/src/main/cpp/skyline/os.h | 6 ++++-- .../cpp/skyline/services/fssrv/IFileSystemProxy.cpp | 4 ++-- .../main/cpp/skyline/services/pl/shared_font_core.h | 2 +- app/src/main/java/emu/skyline/EmulationActivity.kt | 7 ++++--- app/src/main/java/emu/skyline/KeyReader.kt | 5 ++++- app/src/main/java/emu/skyline/MainActivity.kt | 8 +++----- app/src/main/java/emu/skyline/SkylineApplication.kt | 12 +++++++++++- app/src/main/java/emu/skyline/loader/RomFile.kt | 2 +- app/src/main/res/xml/filepaths.xml | 3 ++- 12 files changed, 47 insertions(+), 27 deletions(-) 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 @@ - + +