diff --git a/src/main/cpp/apps/app_manager.cpp b/src/main/cpp/apps/app_manager.cpp index b89b68d..e00ad30 100644 --- a/src/main/cpp/apps/app_manager.cpp +++ b/src/main/cpp/apps/app_manager.cpp @@ -585,80 +585,94 @@ bool AppManager::DownloadFile(const std::string& url, const std::string& dest_pa void AppManager::ScanAppsDirectory() { std::string apps_dir = m_data_root + "/apps"; - if (!fs::exists(apps_dir)) { + 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()); - for (const auto& entry : fs::directory_iterator(apps_dir)) { - if (!entry.is_directory()) { - continue; - } - - std::string package_id = entry.path().filename().string(); - - // Skip if already registered - if (m_installed_apps.find(package_id) != m_installed_apps.end()) { - continue; - } - - // Look for manifest.json in direct folder or package/ subfolder - std::string manifest_path = entry.path().string() + "/manifest.json"; - std::string manifest_path_pkg = entry.path().string() + "/package/manifest.json"; - - std::string actual_manifest; - std::string app_base_path; - - if (fs::exists(manifest_path)) { - actual_manifest = manifest_path; - app_base_path = entry.path().string(); - } else if (fs::exists(manifest_path_pkg)) { - actual_manifest = manifest_path_pkg; - app_base_path = entry.path().string() + "/package"; - } else { - continue; - } - - // Parse manifest - std::ifstream mf(actual_manifest); - if (!mf) { - continue; - } - - try { - json j; - mf >> j; - - InstalledApp app; - app.package_id = j.value("id", package_id); - app.name = j.value("name", package_id); - app.version_name = j.value("version", "1.0.0"); - app.version_code = j.value("version_code", 1); - app.install_path = entry.path().string(); - app.entry_point = j.value("entry", "main.rml"); - app.icon_path = j.value("icon", ""); - app.is_system_app = false; - - if (j.contains("developer")) { - app.developer_name = j["developer"].value("name", ""); - } - - if (j.contains("permissions") && j["permissions"].is_array()) { - for (const auto& perm : j["permissions"]) { - app.permissions.push_back(perm.get()); + try { + for (const auto& entry : fs::directory_iterator(apps_dir)) { + try { + if (!entry.is_directory()) { + continue; } + + std::string package_id = entry.path().filename().string(); + + // Skip if already registered + if (m_installed_apps.find(package_id) != m_installed_apps.end()) { + continue; + } + + // Look for manifest.json in direct folder or package/ subfolder + std::string manifest_path = entry.path().string() + "/manifest.json"; + std::string manifest_path_pkg = entry.path().string() + "/package/manifest.json"; + + std::string actual_manifest; + std::string app_base_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, 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; + } + + // Parse manifest + std::ifstream mf(actual_manifest); + if (!mf) { + continue; + } + + json j; + mf >> j; + + InstalledApp app; + app.package_id = j.value("id", package_id); + app.name = j.value("name", package_id); + app.version_name = j.value("version", "1.0.0"); + app.version_code = j.value("version_code", 1); + app.install_path = entry.path().string(); + app.entry_point = j.value("entry", "main.rml"); + app.icon_path = j.value("icon", ""); + app.is_system_app = false; + + if (j.contains("developer")) { + app.developer_name = j["developer"].value("name", ""); + } + + if (j.contains("permissions") && j["permissions"].is_array()) { + for (const auto& perm : j["permissions"]) { + app.permissions.push_back(perm.get()); + } + } + + app.installed_at = std::chrono::system_clock::now(); + app.updated_at = std::chrono::system_clock::now(); + + m_installed_apps[app.package_id] = app; + LOG_INFO("Discovered app: %s (%s)", app.name.c_str(), app.package_id.c_str()); + + } catch (const std::exception& e) { + LOG_WARN("Error processing app entry: %s", e.what()); } - - app.installed_at = std::chrono::system_clock::now(); - app.updated_at = std::chrono::system_clock::now(); - - m_installed_apps[app.package_id] = app; - 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()); } + } catch (const std::exception& e) { + LOG_ERROR("Error scanning apps directory: %s", e.what()); } } diff --git a/src/main/cpp/kernel.cpp b/src/main/cpp/kernel.cpp index 835b02d..5e065c0 100644 --- a/src/main/cpp/kernel.cpp +++ b/src/main/cpp/kernel.cpp @@ -27,6 +27,9 @@ #include #include +// 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(data_root); m_update_service = std::make_unique( m_app_manager.get(), "https://portal.mosis.dev/api/v1"); diff --git a/src/main/cpp/mosis-service.cpp b/src/main/cpp/mosis-service.cpp index d069215..ade28ac 100644 --- a/src/main/cpp/mosis-service.cpp +++ b/src/main/cpp/mosis-service.cpp @@ -83,4 +83,22 @@ Java_com_omixlab_mosis_NativeService_setAssetManager(JNIEnv *env, jobject thiz, jobject 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; } \ No newline at end of file diff --git a/src/main/java/com/omixlab/mosis/NativeService.kt b/src/main/java/com/omixlab/mosis/NativeService.kt index af66ad2..4e29e14 100644 --- a/src/main/java/com/omixlab/mosis/NativeService.kt +++ b/src/main/java/com/omixlab/mosis/NativeService.kt @@ -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 {