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.
This commit is contained in:
PixelyIon 2022-04-06 11:18:26 +05:30
parent e5e20f39c9
commit b45437b78b
12 changed files with 47 additions and 27 deletions

View File

@ -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<skyline::Logger::LogLevel>(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<skyline::Settings>(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<skyline::kernel::OS>(
jvmManager,
settings,
appFilesPath,
publicAppFilesPath,
privateAppFilesPath,
nativeLibraryPath,
GetTimeZoneName(),
static_cast<skyline::language::SystemLanguage>(systemLanguage),

View File

@ -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);
}

View File

@ -16,13 +16,15 @@ namespace skyline::kernel {
OS::OS(
std::shared_ptr<JvmManager> &jvmManager,
std::shared_ptr<Settings> &settings,
std::string appFilesPath,
std::string publicAppFilesPath,
std::string privateAppFilesPath,
std::string nativeLibraryPath,
std::string deviceTimeZone,
language::SystemLanguage systemLanguage,
std::shared_ptr<vfs::FileSystem> 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<vfs::OsBacking>(romFd)};
auto keyStore{std::make_shared<crypto::KeyStore>(appFilesPath)};
auto keyStore{std::make_shared<crypto::KeyStore>(privateAppFilesPath + "keys/")};
state.loader = [&]() -> std::shared_ptr<loader::Loader> {
switch (romType) {

View File

@ -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<vfs::FileSystem> assetFileSystem; //!< A filesystem to be used for accessing emulator assets (like tzdata)
@ -29,7 +30,8 @@ namespace skyline::kernel {
OS(
std::shared_ptr<JvmManager> &jvmManager,
std::shared_ptr<Settings> &settings,
std::string appFilesPath,
std::string publicAppFilesPath,
std::string privateAppFilesPath,
std::string deviceTimeZone,
std::string nativeLibraryPath,
language::SystemLanguage systemLanguage,

View File

@ -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<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch/sdmc/"), state, manager), session, response);
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->publicAppFilesPath + "/switch/sdmc/"), state, manager), session, response);
return {};
}
@ -57,7 +57,7 @@ namespace skyline::service::fssrv {
}
}()};
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->appFilesPath + "/switch" + saveDataPath), state, manager), session, response);
manager.RegisterService(std::make_shared<IFileSystem>(std::make_shared<vfs::OsFileSystem>(state.os->publicAppFilesPath + "/switch" + saveDataPath), state, manager), session, response);
return {};
}

View File

@ -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<vfs::OsFileSystem>(state.os->appFilesPath + "fonts/")};
auto fontsDirectory{std::make_shared<vfs::OsFileSystem>(state.os->publicAppFilesPath + "fonts/")};
auto ptr{reinterpret_cast<u32 *>(sharedFontMemory->host.ptr)};
for (auto &font : fonts) {
*ptr++ = 0x18029a7f;

View File

@ -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()
}

View File

@ -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 ->

View File

@ -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 {

View File

@ -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())
}
}

View File

@ -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 ->

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path path="/" name="Skyline" />
<files-path path="/" name="Skyline Internal" />
<external-files-path path="/" name="Skyline External" />
</paths>