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:
@@ -585,13 +585,20 @@ bool AppManager::DownloadFile(const std::string& url, const std::string& dest_pa
|
|||||||
void AppManager::ScanAppsDirectory() {
|
void AppManager::ScanAppsDirectory() {
|
||||||
std::string apps_dir = m_data_root + "/apps";
|
std::string apps_dir = m_data_root + "/apps";
|
||||||
|
|
||||||
|
try {
|
||||||
if (!fs::exists(apps_dir)) {
|
if (!fs::exists(apps_dir)) {
|
||||||
return;
|
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());
|
LOG_INFO("Scanning apps directory: %s", apps_dir.c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
for (const auto& entry : fs::directory_iterator(apps_dir)) {
|
for (const auto& entry : fs::directory_iterator(apps_dir)) {
|
||||||
|
try {
|
||||||
if (!entry.is_directory()) {
|
if (!entry.is_directory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -610,13 +617,18 @@ void AppManager::ScanAppsDirectory() {
|
|||||||
std::string actual_manifest;
|
std::string actual_manifest;
|
||||||
std::string app_base_path;
|
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;
|
actual_manifest = manifest_path;
|
||||||
app_base_path = entry.path().string();
|
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;
|
actual_manifest = manifest_path_pkg;
|
||||||
app_base_path = entry.path().string() + "/package";
|
app_base_path = entry.path().string() + "/package";
|
||||||
} else {
|
} else {
|
||||||
|
if (ec) {
|
||||||
|
LOG_WARN("Cannot access %s: %s", package_id.c_str(), ec.message().c_str());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +638,6 @@ void AppManager::ScanAppsDirectory() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
json j;
|
json j;
|
||||||
mf >> 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());
|
LOG_INFO("Discovered app: %s (%s)", app.name.c_str(), app.package_id.c_str());
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} 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() {
|
void AppManager::LoadInstalledApps() {
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
#include <mosis/sandbox/crypto_api.h>
|
#include <mosis/sandbox/crypto_api.h>
|
||||||
#include <mosis/sandbox/virtual_fs.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
|
// Global state for Lua access
|
||||||
static Rml::Context* g_context = nullptr;
|
static Rml::Context* g_context = nullptr;
|
||||||
static Rml::ElementDocument* g_document = nullptr;
|
static Rml::ElementDocument* g_document = nullptr;
|
||||||
@@ -500,9 +503,15 @@ void Kernel::main_loop()
|
|||||||
Logger::Log("RmlUi Lua bindings initialized");
|
Logger::Log("RmlUi Lua bindings initialized");
|
||||||
|
|
||||||
// Initialize app management system
|
// Initialize app management system
|
||||||
// TODO: Get data root from Android context (for now use a placeholder)
|
// Get files directory from Android context (set via JNI)
|
||||||
std::string data_root = "/data/data/com.omixlab.mosis/files";
|
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
|
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_app_manager = std::make_unique<mosis::AppManager>(data_root);
|
||||||
m_update_service = std::make_unique<mosis::UpdateService>(
|
m_update_service = std::make_unique<mosis::UpdateService>(
|
||||||
m_app_manager.get(), "https://portal.mosis.dev/api/v1");
|
m_app_manager.get(), "https://portal.mosis.dev/api/v1");
|
||||||
|
|||||||
@@ -84,3 +84,21 @@ Java_com_omixlab_mosis_NativeService_setAssetManager(JNIEnv *env, jobject thiz,
|
|||||||
{
|
{
|
||||||
AssetsManager::Init(AAssetManager_fromJava(env, asset_manager));
|
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;
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ class NativeService : Service() {
|
|||||||
}
|
}
|
||||||
external fun getBinderNative(): IBinder
|
external fun getBinderNative(): IBinder
|
||||||
external fun setAssetManager(assetManager: AssetManager)
|
external fun setAssetManager(assetManager: AssetManager)
|
||||||
|
external fun setFilesDir(filesDir: String)
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder {
|
override fun onBind(intent: Intent): IBinder {
|
||||||
return getBinderNative()
|
return getBinderNative()
|
||||||
@@ -27,6 +28,9 @@ class NativeService : Service() {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
setAssetManager(assets)
|
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 {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
|||||||
Reference in New Issue
Block a user