Merge pull request #62 from morphis/f/maintain-app-info
Implement simple app database which maintains app information at runtime
This commit is contained in:
commit
572c80c6a9
14 changed files with 180 additions and 53 deletions
|
|
@ -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
|
||||
|
|
|
|||
58
src/anbox/application/database.cpp
Normal file
58
src/anbox/application/database.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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
|
||||
58
src/anbox/application/database.h
Normal file
58
src/anbox/application/database.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue