提交 5c7b0adf 编写于 作者: S Simon Fels

Synchronize application icons with the host

上级 8caaa1f3
...@@ -27,8 +27,14 @@ import android.content.Context; ...@@ -27,8 +27,14 @@ import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.net.Uri; import android.net.Uri;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import java.util.List; import java.util.List;
import java.io.ByteArrayOutputStream;
public final class PlatformService { public final class PlatformService {
private static final String TAG = "AnboxAppMgr"; private static final String TAG = "AnboxAppMgr";
...@@ -69,28 +75,41 @@ public final class PlatformService { ...@@ -69,28 +75,41 @@ public final class PlatformService {
data.writeInt(apps.size()); data.writeInt(apps.size());
for (int n = 0; n < apps.size(); n++) { for (int n = 0; n < apps.size(); n++) {
ApplicationInfo appInfo = apps.get(n); ApplicationInfo appInfo = apps.get(n);
data.writeString(appInfo.name);
data.writeString(appInfo.packageName);
Intent launchIntent = mPm.getLaunchIntentForPackage(appInfo.packageName); Intent launchIntent = mPm.getLaunchIntentForPackage(appInfo.packageName);
if (launchIntent != null) { if (launchIntent == null)
data.writeInt(1); continue;
data.writeString(launchIntent.getAction());
if (launchIntent.getData() != null) Drawable icon = null;
data.writeString(launchIntent.getData().toString()); try {
else icon = mPm.getApplicationIcon(appInfo.packageName);
data.writeString("");
data.writeString(launchIntent.getType());
data.writeString(launchIntent.getComponent().getPackageName());
data.writeString(launchIntent.getComponent().getClassName());
data.writeInt(launchIntent.getCategories().size());
for (String category : launchIntent.getCategories())
data.writeString(category);
} else {
data.writeInt(0);
} }
catch (PackageManager.NameNotFoundException ex) {
continue;
}
if (icon == null)
continue;
data.writeString(appInfo.name);
data.writeString(appInfo.packageName);
// FIXME add icon, flags, ... data.writeString(launchIntent.getAction());
if (launchIntent.getData() != null)
data.writeString(launchIntent.getData().toString());
else
data.writeString("");
data.writeString(launchIntent.getType());
data.writeString(launchIntent.getComponent().getPackageName());
data.writeString(launchIntent.getComponent().getClassName());
data.writeInt(launchIntent.getCategories().size());
for (String category : launchIntent.getCategories())
data.writeString(category);
Bitmap iconBitmap = drawableToBitmap(icon);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
iconBitmap.compress(Bitmap.CompressFormat.PNG, 90, outStream);
data.writeByteArray(outStream.toByteArray());
} }
Parcel reply = Parcel.obtain(); Parcel reply = Parcel.obtain();
...@@ -107,4 +126,16 @@ public final class PlatformService { ...@@ -107,4 +126,16 @@ public final class PlatformService {
public void notifyPackageRemoved(Intent intent) { public void notifyPackageRemoved(Intent intent) {
} }
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable)
return ((BitmapDrawable)drawable).getBitmap();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
} }
...@@ -81,6 +81,8 @@ void PlatformApiStub::update_application_list(const ApplicationListUpdate &updat ...@@ -81,6 +81,8 @@ void PlatformApiStub::update_application_list(const ApplicationListUpdate &updat
auto c = launch_intent->add_categories(); auto c = launch_intent->add_categories();
*c = category; *c = category;
} }
app->set_icon(a.icon.data(), a.icon.size());
} }
rpc_channel_->send_event(seq); rpc_channel_->send_event(seq);
......
...@@ -73,6 +73,7 @@ public: ...@@ -73,6 +73,7 @@ public:
std::vector<std::string> categories; std::vector<std::string> categories;
}; };
Intent launch_intent; Intent launch_intent;
std::vector<int8_t> icon;
}; };
std::vector<Application> applications; std::vector<Application> applications;
}; };
......
...@@ -97,27 +97,27 @@ status_t PlatformService::update_application_list(const Parcel &data) { ...@@ -97,27 +97,27 @@ status_t PlatformService::update_application_list(const Parcel &data) {
package_name.string(), package_name.string(),
}; };
if (data.readInt32() == 1) { String8 action(data.readString16());
String8 action(data.readString16()); String8 uri(data.readString16());
String8 uri(data.readString16()); String8 type(data.readString16());
String8 type(data.readString16()); String8 component_package(data.readString16());
String8 component_package(data.readString16()); String8 component_class(data.readString16());
String8 component_class(data.readString16());
std::vector<std::string> categories;
std::vector<std::string> categories; unsigned int num_categories = data.readInt32();
unsigned int num_categories = data.readInt32(); for (int m = 0; m < num_categories; m++)
for (int m = 0; m < num_categories; m++) categories.push_back(String8(data.readString16()).string());
categories.push_back(String8(data.readString16()).string());
p.launch_intent.action = action;
p.launch_intent.action = action; p.launch_intent.uri = uri;
p.launch_intent.uri = uri; p.launch_intent.type = type;
p.launch_intent.type = type; p.launch_intent.package = component_package;
p.launch_intent.package = component_package; p.launch_intent.component = component_class;
p.launch_intent.component = component_class; p.launch_intent.categories = categories;
p.launch_intent.categories = categories;
data.readByteVector(&p.icon);
update.applications.push_back(p);
}; update.applications.push_back(p);
} }
platform_api_stub_->update_application_list(update); platform_api_stub_->update_application_list(update);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "anbox/application/launcher_storage.h" #include "anbox/application/launcher_storage.h"
#include "anbox/utils.h" #include "anbox/utils.h"
#include "anbox/logger.h"
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
...@@ -26,19 +27,25 @@ namespace fs = boost::filesystem; ...@@ -26,19 +27,25 @@ namespace fs = boost::filesystem;
namespace anbox { namespace anbox {
namespace application { namespace application {
LauncherStorage::LauncherStorage(const fs::path &path) : path_(path) {} LauncherStorage::LauncherStorage(const fs::path &path,
const boost::filesystem::path &icon_path) : path_(path), icon_path_(icon_path) {
}
LauncherStorage::~LauncherStorage() {} LauncherStorage::~LauncherStorage() {}
void LauncherStorage::add(const Item &item) { void LauncherStorage::add(const Item &item) {
if (!fs::exists(path_)) fs::create_directories(path_); if (!fs::exists(path_)) fs::create_directories(path_);
if (!fs::exists(icon_path_)) fs::create_directories(icon_path_);
auto package_name = item.package; auto package_name = item.package;
std::replace(package_name.begin(), package_name.end(), '.', '-'); std::replace(package_name.begin(), package_name.end(), '.', '-');
const auto item_path = const auto item_path =
path_ / utils::string_format("anbox-%s.desktop", package_name); path_ / utils::string_format("anbox-%s.desktop", package_name);
std::string exec = "anbox launch "; const auto item_icon_path =
icon_path_ / utils::string_format("anbox-%s.png", package_name);
std::string exec = utils::string_format("%s launch ", utils::process_get_exe_path(getpid()));
if (!item.launch_intent.action.empty()) if (!item.launch_intent.action.empty())
exec += utils::string_format("--action=%s ", item.launch_intent.action); exec += utils::string_format("--action=%s ", item.launch_intent.action);
...@@ -62,7 +69,11 @@ void LauncherStorage::add(const Item &item) { ...@@ -62,7 +69,11 @@ void LauncherStorage::add(const Item &item) {
<< "Exec=" << exec << std::endl << "Exec=" << exec << std::endl
<< "Terminal=false" << std::endl << "Terminal=false" << std::endl
<< "Type=Application" << std::endl << "Type=Application" << std::endl
<< "Encoding=UTF-8" << std::endl; << "Icon=" << item_icon_path.string() << std::endl;
f.close();
f = std::ofstream(item_icon_path.string());
f.write(item.icon.data(), item.icon.size());
f.close(); f.close();
} }
} // namespace application } // namespace application
......
...@@ -29,19 +29,22 @@ namespace anbox { ...@@ -29,19 +29,22 @@ namespace anbox {
namespace application { namespace application {
class LauncherStorage { class LauncherStorage {
public: public:
LauncherStorage(const boost::filesystem::path &path); LauncherStorage(const boost::filesystem::path &path,
const boost::filesystem::path &icon_path);
~LauncherStorage(); ~LauncherStorage();
struct Item { struct Item {
std::string name; std::string name;
std::string package; std::string package;
android::Intent launch_intent; android::Intent launch_intent;
std::vector<char> icon;
}; };
void add(const Item &item); void add(const Item &item);
private: private:
boost::filesystem::path path_; boost::filesystem::path path_;
boost::filesystem::path icon_path_;
}; };
} // namespace application } // namespace application
} // namespace anbox } // namespace anbox
......
...@@ -89,6 +89,11 @@ void PlatformApiSkeleton::handle_application_list_update_event( ...@@ -89,6 +89,11 @@ void PlatformApiSkeleton::handle_application_list_update_event(
for (int m = 0; m < li.categories_size(); m++) for (int m = 0; m < li.categories_size(); m++)
item.launch_intent.categories.push_back(li.categories(m)); item.launch_intent.categories.push_back(li.categories(m));
item.icon = std::vector<char>(app.icon().begin(), app.icon().end());
if (item.package.empty())
continue;
// If the item is already stored it will be updated // If the item is already stored it will be updated
launcher_storage_->add(item); launcher_storage_->add(item);
} }
......
...@@ -114,7 +114,8 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory) ...@@ -114,7 +114,8 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory)
auto window_manager = std::make_shared<wm::Manager>(policy); auto window_manager = std::make_shared<wm::Manager>(policy);
auto launcher_storage = std::make_shared<application::LauncherStorage>( auto launcher_storage = std::make_shared<application::LauncherStorage>(
xdg::data().home() / "applications"); xdg::data().home() / "applications" / "anbox",
xdg::data().home() / "anbox" / "icons");
auto gl_server = auto gl_server =
std::make_shared<graphics::GLRendererServer>(window_manager); std::make_shared<graphics::GLRendererServer>(window_manager);
......
...@@ -74,6 +74,7 @@ message ApplicationListUpdateEvent { ...@@ -74,6 +74,7 @@ message ApplicationListUpdateEvent {
required string name = 1; required string name = 1;
required string package = 2; required string package = 2;
optional Intent launch_intent = 3; optional Intent launch_intent = 3;
optional bytes icon = 4;
} }
repeated Application applications = 1; repeated Application applications = 1;
} }
......
...@@ -158,5 +158,10 @@ std::string prefix_dir_from_env(const std::string &path, ...@@ -158,5 +158,10 @@ std::string prefix_dir_from_env(const std::string &path,
return result; return result;
} }
std::string process_get_exe_path(const pid_t &pid) {
auto exe_path = string_format("/proc/%d/exe", pid);
return boost::filesystem::read_symlink(exe_path).string();
}
} // namespace utils } // namespace utils
} // namespace anbox } // namespace anbox
...@@ -48,6 +48,8 @@ void ensure_paths(const std::vector<std::string> &paths); ...@@ -48,6 +48,8 @@ void ensure_paths(const std::vector<std::string> &paths);
std::string prefix_dir_from_env(const std::string &path, std::string prefix_dir_from_env(const std::string &path,
const std::string &env_var); const std::string &env_var);
std::string process_get_exe_path(const pid_t &pid);
template <typename... Types> template <typename... Types>
static std::string string_format(const std::string &fmt_str, Types &&... args); static std::string string_format(const std::string &fmt_str, Types &&... args);
} // namespace utils } // namespace utils
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册