fix files directory handling: use internal storage and add exception handling

- Use internal files dir instead of external (fixes scoped storage permissions)
- Pass files directory from Android context via JNI instead of hardcoding
- Add exception handling in ScanAppsDirectory to prevent crashes on permission errors
- Use std::error_code overload of fs::exists() to avoid throwing on access denial

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-19 21:49:58 +01:00
parent 76d97e202b
commit 8cf24d8c2a
4 changed files with 113 additions and 68 deletions

View File

@@ -585,13 +585,20 @@ bool AppManager::DownloadFile(const std::string& url, const std::string& dest_pa
void AppManager::ScanAppsDirectory() {
std::string apps_dir = m_data_root + "/apps";
try {
if (!fs::exists(apps_dir)) {
return;
}
} catch (const std::exception& e) {
LOG_ERROR("Cannot access apps directory: %s", e.what());
return;
}
LOG_INFO("Scanning apps directory: %s", apps_dir.c_str());
try {
for (const auto& entry : fs::directory_iterator(apps_dir)) {
try {
if (!entry.is_directory()) {
continue;
}
@@ -610,13 +617,18 @@ void AppManager::ScanAppsDirectory() {
std::string actual_manifest;
std::string app_base_path;
if (fs::exists(manifest_path)) {
// Use error_code overload to avoid exceptions on permission errors
std::error_code ec;
if (fs::exists(manifest_path, ec) && !ec) {
actual_manifest = manifest_path;
app_base_path = entry.path().string();
} else if (fs::exists(manifest_path_pkg)) {
} else if (fs::exists(manifest_path_pkg, ec) && !ec) {
actual_manifest = manifest_path_pkg;
app_base_path = entry.path().string() + "/package";
} else {
if (ec) {
LOG_WARN("Cannot access %s: %s", package_id.c_str(), ec.message().c_str());
}
continue;
}
@@ -626,7 +638,6 @@ void AppManager::ScanAppsDirectory() {
continue;
}
try {
json j;
mf >> j;
@@ -657,9 +668,12 @@ void AppManager::ScanAppsDirectory() {
LOG_INFO("Discovered app: %s (%s)", app.name.c_str(), app.package_id.c_str());
} catch (const std::exception& e) {
LOG_WARN("Failed to parse manifest for %s: %s", package_id.c_str(), e.what());
LOG_WARN("Error processing app entry: %s", e.what());
}
}
} catch (const std::exception& e) {
LOG_ERROR("Error scanning apps directory: %s", e.what());
}
}
void AppManager::LoadInstalledApps() {

View File

@@ -27,6 +27,9 @@
#include <mosis/sandbox/crypto_api.h>
#include <mosis/sandbox/virtual_fs.h>
// External function to get files directory from JNI
extern const std::string& GetFilesDir();
// Global state for Lua access
static Rml::Context* g_context = nullptr;
static Rml::ElementDocument* g_document = nullptr;
@@ -500,9 +503,15 @@ void Kernel::main_loop()
Logger::Log("RmlUi Lua bindings initialized");
// Initialize app management system
// TODO: Get data root from Android context (for now use a placeholder)
std::string data_root = "/data/data/com.omixlab.mosis/files";
// Get files directory from Android context (set via JNI)
std::string data_root = GetFilesDir();
if (data_root.empty()) {
// Fallback if not set (shouldn't happen in normal operation)
data_root = "/data/data/com.omixlab.mosis/files";
Logger::Log("Warning: Files directory not set, using fallback");
}
g_data_root = data_root; // Store for sandbox switching
Logger::Log("Using data root: " + data_root);
m_app_manager = std::make_unique<mosis::AppManager>(data_root);
m_update_service = std::make_unique<mosis::UpdateService>(
m_app_manager.get(), "https://portal.mosis.dev/api/v1");

View File

@@ -84,3 +84,21 @@ Java_com_omixlab_mosis_NativeService_setAssetManager(JNIEnv *env, jobject thiz,
{
AssetsManager::Init(AAssetManager_fromJava(env, asset_manager));
}
// Global storage for files directory path
static std::string g_files_dir;
extern "C"
JNIEXPORT void JNICALL
Java_com_omixlab_mosis_NativeService_setFilesDir(JNIEnv *env, jobject thiz,
jstring files_dir)
{
const char* path = env->GetStringUTFChars(files_dir, nullptr);
g_files_dir = path;
env->ReleaseStringUTFChars(files_dir, path);
LOG_INFO("Files directory set to: %s", g_files_dir.c_str());
}
const std::string& GetFilesDir() {
return g_files_dir;
}

View File

@@ -19,6 +19,7 @@ class NativeService : Service() {
}
external fun getBinderNative(): IBinder
external fun setAssetManager(assetManager: AssetManager)
external fun setFilesDir(filesDir: String)
override fun onBind(intent: Intent): IBinder {
return getBinderNative()
@@ -27,6 +28,9 @@ class NativeService : Service() {
override fun onCreate() {
super.onCreate()
setAssetManager(assets)
// Use internal files dir - more reliable access in service processes
// For debugging, use: adb shell run-as com.omixlab.mosis ls files/
setFilesDir(filesDir.absolutePath)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {