提交 3d0d4538 编写于 作者: S Simon Fels

Implement simple app database which maintains app information at runtime

This helps us to collect information about an app (title, ..) we can
reuse for certain other things like window construction.
上级 3f34c059
......@@ -116,7 +116,12 @@ public final class PlatformService {
if (icon == null)
continue;
data.writeString(appInfo.name);
String name = appInfo.name;
CharSequence label = appInfo.loadLabel(mPm);
if (label != null)
name = label.toString();
data.writeString(name);
data.writeString(appInfo.packageName);
data.writeString(launchIntent.getAction());
......
......@@ -60,7 +60,6 @@ set(SOURCES
anbox/daemon.cpp
anbox/config.cpp
anbox/not_reachable.cpp
anbox/application_manager.h
anbox/android/intent.cpp
......@@ -187,6 +186,7 @@ set(SOURCES
anbox/dbus/stub/application_manager.cpp
anbox/application/launcher_storage.cpp
anbox/application/database.cpp
anbox/cmds/version.cpp
anbox/cmds/session_manager.cpp
......
/*
* Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "anbox/application/database.h"
#include "anbox/application/launcher_storage.h"
#include "anbox/config.h"
#include "anbox/logger.h"
namespace anbox {
namespace application {
const Database::Item Database::Unknown{};
Database::Database() :
storage_(std::make_shared<LauncherStorage>(SystemConfiguration::instance().application_item_dir())) {
storage_->reset();
}
Database::~Database() {}
void Database::store_or_update(const Item &item) {
storage_->add_or_update(item);
items_[item.package] = item;
// We don't need to store the icon data anymore at this point as the
// launcher is already stored it on the disk.
items_[item.package].icon.clear();
}
void Database::remove(const Item &item) {
auto iter = items_.find(item.package);
if (iter == items_.end())
return;
storage_->remove(item);
items_.erase(iter);
}
const Database::Item& Database::find_by_package(const std::string &package) const {
auto iter = items_.find(package);
if (iter == items_.end())
return Unknown;
return iter->second;
}
} // namespace application
} // namespace anbox
/*
* Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_APPLICATION_DATABASE_H_
#define ANBOX_APPLICATION_DATABASE_H_
#include "anbox/android/intent.h"
#include <string>
#include <map>
#include <memory>
namespace anbox {
namespace application {
class LauncherStorage;
class Database {
public:
struct Item {
std::string name;
std::string package;
android::Intent launch_intent;
std::vector<char> icon;
bool valid() const { return package.length() > 0; }
};
static const Item Unknown;
Database();
~Database();
void store_or_update(const Item &item);
void remove(const Item &item);
const Item& find_by_package(const std::string &package) const;
private:
std::shared_ptr<LauncherStorage> storage_;
std::map<std::string,Item> items_;
};
} // namespace application
} // namespace anbox
#endif
......@@ -33,18 +33,14 @@ constexpr const char *snap_exe_path{"/snap/bin/anbox"};
namespace anbox {
namespace application {
LauncherStorage::LauncherStorage(const fs::path &path,
const boost::filesystem::path &icon_path) : path_(path), icon_path_(icon_path) {
}
LauncherStorage::LauncherStorage(const fs::path &path) :
path_(path) {}
LauncherStorage::~LauncherStorage() {}
void LauncherStorage::reset() {
if (fs::exists(path_))
fs::remove_all(path_);
if (fs::exists(icon_path_))
fs::remove_all(icon_path_);
}
std::string LauncherStorage::clean_package_name(const std::string &package_name) {
......@@ -58,12 +54,11 @@ fs::path LauncherStorage::path_for_item(const std::string &package_name) {
}
fs::path LauncherStorage::path_for_item_icon(const std::string &package_name) {
return icon_path_ / utils::string_format("anbox-%s.png", package_name);
return path_ / utils::string_format("anbox-%s.png", package_name);
}
void LauncherStorage::add_or_update(const Item &item) {
void LauncherStorage::add_or_update(const Database::Item &item) {
if (!fs::exists(path_)) fs::create_directories(path_);
if (!fs::exists(icon_path_)) fs::create_directories(icon_path_);
auto package_name = item.package;
std::replace(package_name.begin(), package_name.end(), '.', '-');
......@@ -92,7 +87,7 @@ void LauncherStorage::add_or_update(const Item &item) {
const auto item_icon_path = path_for_item_icon(package_name);
if (auto desktop_item = std::ofstream(path_for_item(package_name).string())) {
desktop_item << "[Desktop Entry]" << std::endl
<< "Name=" << item.package << std::endl
<< "Name=" << item.name << std::endl
<< "Exec=" << exec << std::endl
<< "Terminal=false" << std::endl
<< "Type=Application" << std::endl
......@@ -107,7 +102,7 @@ void LauncherStorage::add_or_update(const Item &item) {
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to write icon"));
}
void LauncherStorage::remove(const Item &item) {
void LauncherStorage::remove(const Database::Item &item) {
auto package_name = clean_package_name(item.package);
const auto item_path = path_for_item(package_name);
......
......@@ -18,6 +18,7 @@
#ifndef ANBOX_APPLICATION_LAUNCHER_STORAGE_H_
#define ANBOX_APPLICATION_LAUNCHER_STORAGE_H_
#include "anbox/application/database.h"
#include "anbox/android/intent.h"
#include <string>
......@@ -29,20 +30,12 @@ namespace anbox {
namespace application {
class LauncherStorage {
public:
LauncherStorage(const boost::filesystem::path &path,
const boost::filesystem::path &icon_path);
LauncherStorage(const boost::filesystem::path &path);
~LauncherStorage();
struct Item {
std::string name;
std::string package;
android::Intent launch_intent;
std::vector<char> icon;
};
void reset();
void add_or_update(const Item &item);
void remove(const Item &item);
void add_or_update(const Database::Item &item);
void remove(const Database::Item &item);
private:
std::string clean_package_name(const std::string &package_name);
......@@ -50,7 +43,6 @@ class LauncherStorage {
boost::filesystem::path path_for_item_icon(const std::string &package_name);
boost::filesystem::path path_;
boost::filesystem::path icon_path_;
};
} // namespace application
} // namespace anbox
......
......@@ -16,7 +16,7 @@
*/
#include "anbox/bridge/platform_api_skeleton.h"
#include "anbox/application/launcher_storage.h"
#include "anbox/application/database.h"
#include "anbox/platform/policy.h"
#include "anbox/wm/manager.h"
#include "anbox/wm/window_state.h"
......@@ -30,11 +30,11 @@ PlatformApiSkeleton::PlatformApiSkeleton(
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<platform::Policy> &platform_policy,
const std::shared_ptr<wm::Manager> &window_manager,
const std::shared_ptr<application::LauncherStorage> &launcher_storage)
const std::shared_ptr<application::Database> &app_db)
: pending_calls_(pending_calls),
platform_policy_(platform_policy),
window_manager_(window_manager),
launcher_storage_(launcher_storage) {}
app_db_(app_db) {}
PlatformApiSkeleton::~PlatformApiSkeleton() {}
......@@ -62,10 +62,7 @@ void PlatformApiSkeleton::get_clipboard_data(anbox::protobuf::rpc::Void const *r
done->Run();
}
void PlatformApiSkeleton::handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event) {
if (event.first_boot_done())
launcher_storage_->reset();
void PlatformApiSkeleton::handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent&) {
if (boot_finished_handler_)
boot_finished_handler_();
}
......@@ -99,7 +96,7 @@ void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf
void PlatformApiSkeleton::handle_application_list_update_event(const anbox::protobuf::bridge::ApplicationListUpdateEvent &event) {
for (int n = 0; n < event.removed_applications_size(); n++) {
application::LauncherStorage::Item item;
application::Database::Item item;
const auto app = event.removed_applications(n);
item.package = app.package();
......@@ -107,11 +104,11 @@ void PlatformApiSkeleton::handle_application_list_update_event(const anbox::prot
if (item.package.empty())
continue;
launcher_storage_->remove(item);
app_db_->remove(item);
}
for (int n = 0; n < event.applications_size(); n++) {
application::LauncherStorage::Item item;
application::Database::Item item;
const auto app = event.applications(n);
item.name = app.name();
......@@ -132,7 +129,7 @@ void PlatformApiSkeleton::handle_application_list_update_event(const anbox::prot
if (item.package.empty())
continue;
launcher_storage_->add_or_update(item);
app_db_->store_or_update(item);
}
}
......
......@@ -48,7 +48,7 @@ namespace wm {
class Manager;
} // namespace wm
namespace application {
class LauncherStorage;
class Database;
} // namespace application
namespace bridge {
class PlatformApiSkeleton {
......@@ -57,7 +57,7 @@ class PlatformApiSkeleton {
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<platform::Policy> &platform_policy,
const std::shared_ptr<wm::Manager> &window_manager,
const std::shared_ptr<application::LauncherStorage> &launcher_storage);
const std::shared_ptr<application::Database> &app_db);
virtual ~PlatformApiSkeleton();
void set_clipboard_data(anbox::protobuf::bridge::ClipboardData const *request,
......@@ -80,7 +80,7 @@ class PlatformApiSkeleton {
std::shared_ptr<rpc::PendingCallCache> pending_calls_;
std::shared_ptr<platform::Policy> platform_policy_;
std::shared_ptr<wm::Manager> window_manager_;
std::shared_ptr<application::LauncherStorage> launcher_storage_;
std::shared_ptr<application::Database> app_db_;
std::function<void()> boot_finished_handler_;
};
} // namespace bridge
......
......@@ -22,6 +22,7 @@
#include "core/posix/signal.h"
#include "anbox/application/launcher_storage.h"
#include "anbox/application/database.h"
#include "anbox/audio/server.h"
#include "anbox/bridge/android_api_stub.h"
#include "anbox/bridge/platform_api_skeleton.h"
......@@ -139,11 +140,8 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
// FIXME this needs to be removed and solved differently behind the scenes
registerDisplayManager(policy);
auto window_manager = std::make_shared<wm::Manager>(policy);
auto launcher_storage = std::make_shared<application::LauncherStorage>(
xdg::data().home() / "applications" / "anbox",
xdg::data().home() / "anbox" / "icons");
auto app_db = std::make_shared<application::Database>();
auto window_manager = std::make_shared<wm::Manager>(policy, app_db);
auto gl_server = std::make_shared<graphics::GLRendererServer>(
graphics::GLRendererServer::Config{gles_driver_}, window_manager);
......@@ -175,7 +173,7 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
android_api_stub->set_rpc_channel(rpc_channel);
auto server = std::make_shared<bridge::PlatformApiSkeleton>(
pending_calls, policy, window_manager, launcher_storage);
pending_calls, policy, window_manager, app_db);
server->register_boot_finished_handler([&]() {
DEBUG("Android successfully booted");
android_api_stub->ready().set(true);
......
......@@ -19,6 +19,7 @@
#include "anbox/config.h"
#include "anbox/utils.h"
#include "external/xdg/xdg.h"
#include <cstring>
......@@ -70,6 +71,11 @@ std::string anbox::SystemConfiguration::input_device_dir() const {
return dir;
}
std::string anbox::SystemConfiguration::application_item_dir() const {
static auto dir = xdg::data().home() / "applications" / "anbox";
return dir.string();
}
anbox::SystemConfiguration& anbox::SystemConfiguration::instance() {
static SystemConfiguration config;
return config;
......
......@@ -39,6 +39,7 @@ class SystemConfiguration {
std::string container_config_dir() const;
std::string container_socket_path() const;
std::string input_device_dir() const;
std::string application_item_dir() const;
protected:
SystemConfiguration() = default;
......
......@@ -16,6 +16,7 @@
*/
#include "anbox/wm/manager.h"
#include "anbox/application/database.h"
#include "anbox/platform/policy.h"
#include "anbox/logger.h"
......@@ -23,8 +24,9 @@
namespace anbox {
namespace wm {
Manager::Manager(const std::shared_ptr<platform::Policy> &policy)
: platform_policy_(policy) {}
Manager::Manager(const std::shared_ptr<platform::Policy> &policy,
const std::shared_ptr<application::Database> &app_db)
: platform_policy_(policy), app_db_(app_db) {}
Manager::~Manager() {}
......@@ -60,7 +62,12 @@ void Manager::apply_window_state_update(const WindowState::List &updated,
continue;
}
auto platform_window = platform_policy_->create_window(window.task(), window.frame(), window.package_name());
auto title = window.package_name();
auto app = app_db_->find_by_package(window.package_name());
if (app.valid())
title = app.name;
auto platform_window = platform_policy_->create_window(window.task(), window.frame(), title);
platform_window->attach();
windows_.insert({window.task(), platform_window});
}
......
......@@ -26,13 +26,17 @@
#include <mutex>
namespace anbox {
namespace application {
class Database;
} // namespace application
namespace platform {
class Policy;
} // namespace platform
namespace wm {
class Manager {
public:
Manager(const std::shared_ptr<platform::Policy> &policy);
Manager(const std::shared_ptr<platform::Policy> &policy,
const std::shared_ptr<application::Database> &app_db);
~Manager();
void apply_window_state_update(const WindowState::List &updated,
......@@ -43,6 +47,7 @@ class Manager {
private:
std::mutex mutex_;
std::shared_ptr<platform::Policy> platform_policy_;
std::shared_ptr<application::Database> app_db_;
std::map<Task::Id, std::shared_ptr<Window>> windows_;
};
} // namespace wm
......
......@@ -20,6 +20,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "anbox/application/database.h"
#include "anbox/platform/default_policy.h"
#include "anbox/wm/manager.h"
#include "anbox/wm/window_state.h"
......@@ -44,7 +45,8 @@ TEST(LayerComposer, FindsNoSuitableWindowForLayer) {
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform_policy = std::make_shared<platform::DefaultPolicy>();
auto wm = std::make_shared<wm::Manager>(platform_policy);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::Manager>(platform_policy, app_db);
auto single_window = wm::WindowState{
wm::Display::Id{1},
......@@ -77,7 +79,8 @@ TEST(LayerComposer, MapsLayersToWindows) {
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform_policy = std::make_shared<platform::DefaultPolicy>();
auto wm = std::make_shared<wm::Manager>(platform_policy);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::Manager>(platform_policy, app_db);
auto first_window = wm::WindowState{
wm::Display::Id{1},
......@@ -136,7 +139,8 @@ TEST(LayerComposer, WindowPartiallyOffscreen) {
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform_policy = std::make_shared<platform::DefaultPolicy>();
auto wm = std::make_shared<wm::Manager>(platform_policy);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::Manager>(platform_policy, app_db);
auto window = wm::WindowState{
wm::Display::Id{1},
......@@ -180,7 +184,8 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) {
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform_policy = std::make_shared<platform::DefaultPolicy>();
auto wm = std::make_shared<wm::Manager>(platform_policy);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::Manager>(platform_policy, app_db);
auto window = wm::WindowState{
wm::Display::Id{1},
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册