implement third-party app launching from home screen

This commit is contained in:
2026-01-19 13:50:05 +01:00
parent ad28cf2360
commit d6b7504408
5 changed files with 214 additions and 33 deletions

View File

@@ -6,6 +6,7 @@
#include "apps/app_manager.h"
#include "apps/update_service.h"
#include "apps/app_api.h"
#include "sandbox/sandbox_manager.h"
#include "aidl/com/omixlab/mosis/IMosisListener.h"
#include <android/hardware_buffer.h>
#include <android/asset_manager.h>
@@ -17,16 +18,30 @@
#include <ranges>
#include <chrono>
#include <format>
#include <fstream>
#include <filesystem>
// Global state for Lua access
static Rml::Context* g_context = nullptr;
static Rml::ElementDocument* g_document = nullptr;
static mosis::AppManager* g_app_manager = nullptr;
static mosis::UpdateService* g_update_service = nullptr;
static mosis::LuaSandboxManager* g_sandbox_manager = nullptr;
using namespace aidl::com::omixlab::mosis;
using namespace aidl::android::hardware;
// File handle wrapper to support both assets and filesystem files
struct FileHandleWrapper {
enum class Type { Asset, File };
Type type;
union {
AAsset* asset;
std::ifstream* file;
};
size_t file_size = 0; // For filesystem files
};
class AssetFilesInterface : public Rml::FileInterface
{
public:
@@ -35,51 +50,137 @@ public:
static AssetFilesInterface instance;
return instance;
}
// Check if path is a filesystem path (starts with /)
static bool IsFilesystemPath(const Rml::String& path) {
return !path.empty() && path[0] == '/';
}
Rml::FileHandle Open(const Rml::String &path) override
{
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER);
return reinterpret_cast<Rml::FileHandle>(asset);
auto* wrapper = new FileHandleWrapper();
if (IsFilesystemPath(path)) {
// Filesystem path
auto* file = new std::ifstream(path, std::ios::binary);
if (!file->is_open()) {
delete file;
delete wrapper;
return 0;
}
file->seekg(0, std::ios::end);
wrapper->file_size = file->tellg();
file->seekg(0, std::ios::beg);
wrapper->type = FileHandleWrapper::Type::File;
wrapper->file = file;
} else {
// Asset path
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER);
if (!asset) {
delete wrapper;
return 0;
}
wrapper->type = FileHandleWrapper::Type::Asset;
wrapper->asset = asset;
}
return reinterpret_cast<Rml::FileHandle>(wrapper);
}
void Close(Rml::FileHandle file) override
{
AAsset* asset = reinterpret_cast<AAsset*>(file);
AAsset_close(asset);
auto* wrapper = reinterpret_cast<FileHandleWrapper*>(file);
if (!wrapper) return;
if (wrapper->type == FileHandleWrapper::Type::Asset) {
AAsset_close(wrapper->asset);
} else {
wrapper->file->close();
delete wrapper->file;
}
delete wrapper;
}
size_t Read(void *buffer, size_t size, Rml::FileHandle file) override
{
AAsset* asset = reinterpret_cast<AAsset*>(file);
return AAsset_read(asset, buffer, size);
auto* wrapper = reinterpret_cast<FileHandleWrapper*>(file);
if (!wrapper) return 0;
if (wrapper->type == FileHandleWrapper::Type::Asset) {
return AAsset_read(wrapper->asset, buffer, size);
} else {
wrapper->file->read(static_cast<char*>(buffer), size);
return wrapper->file->gcount();
}
}
bool Seek(Rml::FileHandle file, long offset, int origin) override
{
AAsset* asset = reinterpret_cast<AAsset*>(file);
off_t new_cursor = AAsset_seek(asset, offset, origin);
return new_cursor != -1;
auto* wrapper = reinterpret_cast<FileHandleWrapper*>(file);
if (!wrapper) return false;
if (wrapper->type == FileHandleWrapper::Type::Asset) {
off_t new_cursor = AAsset_seek(wrapper->asset, offset, origin);
return new_cursor != -1;
} else {
std::ios_base::seekdir dir = std::ios::beg;
if (origin == SEEK_CUR) dir = std::ios::cur;
else if (origin == SEEK_END) dir = std::ios::end;
wrapper->file->seekg(offset, dir);
return !wrapper->file->fail();
}
}
size_t Tell(Rml::FileHandle file) override
{
AAsset* asset = reinterpret_cast<AAsset*>(file);
return AAsset_seek(asset, 0, SEEK_CUR);
auto* wrapper = reinterpret_cast<FileHandleWrapper*>(file);
if (!wrapper) return 0;
if (wrapper->type == FileHandleWrapper::Type::Asset) {
return AAsset_seek(wrapper->asset, 0, SEEK_CUR);
} else {
return wrapper->file->tellg();
}
}
size_t Length(Rml::FileHandle file) override
{
AAsset* asset = reinterpret_cast<AAsset*>(file);
return AAsset_getLength(asset);
auto* wrapper = reinterpret_cast<FileHandleWrapper*>(file);
if (!wrapper) return 0;
if (wrapper->type == FileHandleWrapper::Type::Asset) {
return AAsset_getLength(wrapper->asset);
} else {
return wrapper->file_size;
}
}
bool LoadFile(const Rml::String &path, Rml::String &out_data) override
{
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER);
if (!asset)
return false;
out_data.resize(AAsset_getLength(asset));
auto data_ptr = static_cast<const char*>(AAsset_getBuffer(asset));
std::span data = std::span(data_ptr, out_data.size());
std::ranges::copy(data, out_data.begin());
return true;
if (IsFilesystemPath(path)) {
// Load from filesystem
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open()) return false;
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
out_data.resize(size);
file.read(out_data.data(), size);
return true;
} else {
// Load from assets
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER);
if (!asset) return false;
out_data.resize(AAsset_getLength(asset));
auto data_ptr = static_cast<const char*>(AAsset_getBuffer(asset));
std::span data = std::span(data_ptr, out_data.size());
std::ranges::copy(data, out_data.begin());
AAsset_close(asset);
return true;
}
}
};
@@ -110,16 +211,27 @@ static int LuaLoadScreen(lua_State* L)
const char* path = luaL_checkstring(L, 1);
Logger::Log(std::format("Loading screen: {}", path));
// Check if asset exists
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path, AASSET_MODE_BUFFER);
if (!asset)
// Check if file exists - support both asset and filesystem paths
bool exists = false;
if (AssetFilesInterface::IsFilesystemPath(path)) {
// Filesystem path
exists = std::filesystem::exists(path);
} else {
// Asset path
AAssetManager* am = AssetsManager::Native();
AAsset* asset = AAssetManager_open(am, path, AASSET_MODE_BUFFER);
if (asset) {
exists = true;
AAsset_close(asset);
}
}
if (!exists)
{
Logger::Log(std::format("Screen not found: {}", path));
lua_pushboolean(L, false);
return 1;
}
AAsset_close(asset);
// Unload current document
if (g_document)
@@ -201,8 +313,11 @@ void Kernel::main_loop()
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");
m_sandbox_manager = std::make_unique<mosis::LuaSandboxManager>(data_root);
m_app_manager->SetSandboxManager(m_sandbox_manager.get());
g_app_manager = m_app_manager.get();
g_update_service = m_update_service.get();
g_sandbox_manager = m_sandbox_manager.get();
Logger::Log("App management system initialized");
// Start background update checks (every 24 hours)
@@ -248,6 +363,11 @@ void Kernel::main_loop()
m_tasks.clear();
}
// Update sandbox timers for running apps
if (m_sandbox_manager) {
m_sandbox_manager->UpdateTimers();
}
m_render_target->bind();
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -289,8 +409,21 @@ void Kernel::on_touch_down(float x, float y)
Logger::Log(std::format("on_touch_down {} - {}", x, y));
std::lock_guard _lock(m_mutex);
m_tasks.emplace_back([x, y](Rml::Context* context){
context->ProcessMouseMove(static_cast<int>(x * 540), static_cast<int>(y * 960), 0);
context->ProcessMouseButtonDown(0, 0);
int px = static_cast<int>(x * 540);
int py = static_cast<int>(y * 960);
bool move_handled = context->ProcessMouseMove(px, py, 0);
bool down_handled = context->ProcessMouseButtonDown(0, 0);
Logger::Log(std::format("Touch at ({}, {}): move={}, down={}", px, py, move_handled, down_handled));
// Debug: Check if there's a hover element
auto* hover_elem = context->GetHoverElement();
if (hover_elem) {
Logger::Log(std::format(" Hover element: {} (id={})",
hover_elem->GetTagName().c_str(),
hover_elem->GetId().c_str()));
} else {
Logger::Log(" No hover element at this position");
}
});
}