&ConnectionManager::ExchangeCapabilities, connmgr_.get()));
DBusService::RegisterSendAppcontrolHandler("SendRemoteAppControl", std::bind(
- &ConnectionManager::SendCapability, connmgr_.get(),
- std::placeholders::_1,
- std::placeholders::_2));
+ &ConnectionManager::SendAppControl, connmgr_.get(),
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
return true;
}
)
APPLY_PKG_CONFIG(${TARGET_LIB_CLIENT} PUBLIC
+ AUL_DEPS
+ BUNDLE_DEPS
DLOG_DEPS
+ GIO_DEPS
+ GLIB_DEPS
)
SET_TARGET_PROPERTIES(${TARGET_LIB_CLIENT} PROPERTIES VERSION ${FULLVER})
// Use of this source code is governed by a apache 2.0 license that can be
// found in the LICENSE file.
+#include <aul_svc.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <glib.h>
+
#include <cstring>
#include <map>
#include <memory>
#include <string>
+#include "client/dbus.h"
#include "client/include/capmgr.h"
#include "common/sql_connection.h"
#include "common/sql_statement.h"
struct capmgr_app_control_s {
capmgr_device_h device;
- std::string operation;
- std::string uri;
- std::string mime;
- std::string appid;
- std::map<std::string, std::string> extra_data;
+ bundle* b;
};
API int capmgr_device_foreach_devices(capmgr_device_foreach_cb cb,
try {
struct capmgr_app_control_s* control = new struct capmgr_app_control_s;
-
+ control->b = bundle_create();
+ if (!control->b) {
+ delete control;
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+ }
*app_control = control;
} catch (const std::bad_alloc& e) {
LOG(ERROR) << e.what();
delete clone;
return CAPMGR_ERROR_OUT_OF_MEMORY;
}
- clone->operation = app_control->operation;
- clone->uri = app_control->uri;
- clone->mime = app_control->mime;
- clone->appid = app_control->appid;
- clone->extra_data = app_control->extra_data;
+
+ clone->b = bundle_dup(app_control->b);
+ if (!clone->b) {
+ capmgr_app_control_destroy(clone);
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+ }
*app_control_clone = clone;
} catch (const std::bad_alloc& e) {
return CAPMGR_ERROR_INVALID_PARAMETER;
capmgr_device_destroy(app_control->device);
+ bundle_free(app_control->b);
delete app_control;
return CAPMGR_ERROR_NONE;
if (!app_control || !operation)
return CAPMGR_ERROR_INVALID_PARAMETER;
- *operation = strdup(app_control->operation.c_str());
+ int r;
+ const char* val = aul_svc_get_operation(app_control->b);
+ if (!val) {
+ r = aul_svc_set_operation(app_control->b, AUL_SVC_OPERATION_DEFAULT);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+ val = AUL_SVC_OPERATION_DEFAULT;
+ }
+
+ *operation = strdup(val);
if (*operation == nullptr)
return CAPMGR_ERROR_OUT_OF_MEMORY;
if (!app_control || !uri)
return CAPMGR_ERROR_INVALID_PARAMETER;
- *uri = strdup(app_control->uri.c_str());
+ const char* val = aul_svc_get_uri(app_control->b);
+ if (!val)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ *uri = strdup(val);
if (*uri == nullptr)
return CAPMGR_ERROR_OUT_OF_MEMORY;
if (!app_control || !mime)
return CAPMGR_ERROR_INVALID_PARAMETER;
- *mime = strdup(app_control->mime.c_str());
+ const char* val = aul_svc_get_mime(app_control->b);
+ if (!val)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ *mime = strdup(val);
if (*mime == nullptr)
return CAPMGR_ERROR_OUT_OF_MEMORY;
if (!app_control || !appid)
return CAPMGR_ERROR_INVALID_PARAMETER;
- *appid = strdup(app_control->appid.c_str());
+ const char* val = aul_svc_get_appid(app_control->b);
+ if (!val)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ *appid = strdup(val);
if (*appid == nullptr)
return CAPMGR_ERROR_OUT_OF_MEMORY;
// TODO(jeremy.jang): handle reserved key
- const auto it = app_control->extra_data.find(key);
- if (it == app_control->extra_data.end()) {
+ const char* val = aul_svc_get_data(app_control->b, key);
+ if (!val) {
LOG(ERROR) << "There is no extra data of key(" << key << ")";
return CAPMGR_ERROR_INVALID_PARAMETER;
}
- *value = strdup(it->second.c_str());
+ *value = strdup(val);
if (*value == nullptr)
return CAPMGR_ERROR_OUT_OF_MEMORY;
if (!app_control || !operation)
return CAPMGR_ERROR_INVALID_PARAMETER;
- app_control->operation = operation;
+ int r = aul_svc_set_operation(app_control->b, operation);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
return CAPMGR_ERROR_NONE;
}
if (!app_control || !uri)
return CAPMGR_ERROR_INVALID_PARAMETER;
- app_control->uri = uri;
+ int r = aul_svc_set_uri(app_control->b, uri);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
return CAPMGR_ERROR_NONE;
}
if (!app_control || !mime)
return CAPMGR_ERROR_INVALID_PARAMETER;
- app_control->mime = mime;
+ int r = aul_svc_set_mime(app_control->b, mime);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
return CAPMGR_ERROR_NONE;
}
if (!app_control || !appid)
return CAPMGR_ERROR_INVALID_PARAMETER;
- app_control->appid = appid;
+ int r = aul_svc_set_appid(app_control->b, appid);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
return CAPMGR_ERROR_NONE;
}
// TODO(jeremy.jang): handle reserved key
- auto r = app_control->extra_data.emplace(key, value);
- if (!r.second) {
- auto elem = r.first;
- elem->second = value;
- }
+ int r = aul_svc_add_data(app_control->b, key, value);
+ if (r != AUL_SVC_RET_OK)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
return CAPMGR_ERROR_NONE;
}
// TODO(jeremy.jang): handle reserved key
- const auto it = app_control->extra_data.find(key);
- if (it == app_control->extra_data.end()) {
- LOG(ERROR) << "There is no extra data of key(" << key << ")";
+ int r = bundle_del(app_control->b, key);
+ if (r != BUNDLE_ERROR_NONE)
return CAPMGR_ERROR_INVALID_PARAMETER;
- }
-
- app_control->extra_data.erase(it);
return CAPMGR_ERROR_NONE;
}
if (!app_control || !app_control->device)
return CAPMGR_ERROR_INVALID_PARAMETER;
+ bundle_raw* raw;
+ int len;
+ int r = bundle_encode(app_control->b, &raw, &len);
+ if (r != BUNDLE_ERROR_NONE) {
+ LOG(ERROR) << "Failed to encode bundle: " << r;
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+
// send app_control
+ GVariantBuilder* array_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+ for (int i = 0; i < len; i++)
+ g_variant_builder_add(array_builder, "y", raw[i]);
+ GVariant* gv = g_variant_new("(sayu)",
+ app_control->device->device_id.c_str(), array_builder, len);
+ g_variant_builder_unref(array_builder);
+ bundle_free_encoded_rawdata(&raw);
+ if (!gv) {
+ LOG(ERROR) << "Failed to create GVariant";
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+ g_variant_ref_sink(gv);
+ if (!capmgr::ProxyCallSync("SendRemoteAppControl", gv)) {
+ LOG(ERROR) << "Failed to dbus method call";
+ g_variant_unref(gv);
+ // errcode?
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_unref(gv);
return CAPMGR_ERROR_NONE;
}
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "client/dbus.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "common/utils/logging.h"
+
+namespace {
+
+const char kDBusServiceName[] = "org.tizen.capmgr";
+const char kDBusObjectPath[] = "/org/tizen/capmgr";
+const char kDBusInterfaceName[] = "org.tizen.capmgr";
+
+} // namespace
+
+namespace capmgr {
+
+bool ProxyCallSync(const char* method, GVariant* params) {
+ GError* error = nullptr;
+ GDBusConnection* conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+ if (!conn || error) {
+ LOG(ERROR) << "g_bus_get_sync() failed: " << error->message;
+ return false;
+ }
+ GDBusProxy* proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, nullptr,
+ kDBusServiceName, kDBusObjectPath, kDBusInterfaceName, nullptr,
+ &error);
+ if (!proxy || error) {
+ LOG(ERROR) << "g_dbus_proxy_new_sync() failed: " << error->message;
+ g_object_unref(conn);
+ return false;
+ }
+
+ GVariant* ret = g_dbus_proxy_call_sync(proxy, method,
+ params, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
+ if (error) {
+ LOG(ERROR) << "g_dbus_proxy_call_sync of " << method << " failed: "
+ << error->message;
+ }
+
+ // TODO(jeremy.jang): some data maybe returned
+ gboolean r;
+ g_variant_get(ret, "(b)", &r);
+ if (!r) {
+ LOG(ERROR) << "Some error occurred";
+ }
+
+ g_object_unref(proxy);
+ g_dbus_connection_flush_sync(conn, nullptr, nullptr);
+ g_object_unref(conn);
+
+ return true;
+}
+
+} // namespace capmgr
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef CLIENT_DBUS_H_
+#define CLIENT_DBUS_H_
+
+#include <glib.h>
+
+namespace capmgr {
+
+bool ProxyCallSync(const char* method, GVariant* params);
+
+} // namespace capmgr
+
+#endif // CLIENT_DBUS_H_
#include "common/utils/logging.h"
+namespace {
+
+void ReplyCb(bundle* b, int request_code, aul_svc_result_val result,
+ void* data) {
+ LOG(DEBUG) << "aul_svc_run_service result code: " << result;
+
+ // b is reply bundle
+
+ switch (result) {
+ case AUL_SVC_RES_OK:
+ LOG(DEBUG) << "AUL_SVC_RES_OK";
+ break;
+ case AUL_SVC_RES_NOT_OK:
+ LOG(ERROR) << "AUL_SVC_RES_NOT_OK";
+ break;
+ case AUL_SVC_RES_CANCEL:
+ LOG(DEBUG) << "AUL_SVC_RES_CANCEL";
+ break;
+ default:
+ break;
+ }
+
+ // TODO(jeremy.jang): need to send reply to remote device
+}
+
+} // namespace
+
namespace capmgr {
-int AppControlManager::LaunchApplication(const Capability& capability) {
- int ret;
- bundle* b = bundle_create();
+// TODO(jeremy.jang): handle reply, async?
+bool AppControlManager::LaunchApplication(const unsigned char* data,
+ size_t len) {
+ bundle* b = bundle_decode(data, len);
+ if (!b) {
+ LOG(ERROR) << "Invalid bundle data!";
+ return false;
+ }
- aul_svc_set_operation(b, capability.operation().c_str());
- ret = aul_launch_app(capability.pkgid().c_str(), b);
+ // FIXME: for uid..?
+ int ret = aul_svc_run_service(b, 0, ReplyCb, nullptr);
if (ret < AUL_R_OK) {
LOG(ERROR) << "launch failed : " << ret;
bundle_free(b);
- return ret;
+ return false;
}
bundle_free(b);
- return 0;
+ return true;
}
} // namespace capmgr
AppControlManager();
~AppControlManager();
- static int LaunchApplication(const Capability& capability);
+ static bool LaunchApplication(const unsigned char* data, size_t len);
private:
};
#ifndef COMMON_CONNECTION_MANAGER_H_
#define COMMON_CONNECTION_MANAGER_H_
+#include <sys/types.h>
+
+#include <string>
+
namespace capmgr {
class CapabilityManager;
virtual void FindDevices() = 0;
virtual void RegisterEndpoint() = 0;
virtual void ExchangeCapabilities() = 0;
- virtual bool SendCapability(
- Capability* cap, std::function<void(Capability, int)> reply) = 0;
+ virtual bool SendAppControl(const std::string& device_id,
+ const unsigned char* data, size_t len) = 0;
protected:
CapabilityManager* capmgr_;
#include <glib.h>
#include <gio/gio.h>
+#include <sys/types.h>
#include <functional>
#include <vector>
" <arg type='v' name='result' direction='out'/>"
" </method>"
" <method name='SendRemoteAppControl'>"
+ " <arg type='s' name='devicd_id' direction='in'/>"
" <arg type='s' name='appcontrol' direction='in'/>"
- " <arg type='s' name='appid' direction='in'/>"
- " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='u' name='len' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
" </interface>"
}
void DBusService::RegisterSendAppcontrolHandler(const std::string& method,
- std::function<bool(Capability*, AppControlHandler)> handler) {
+ std::function<bool(const std::string&, const unsigned char*, size_t len)>
+ handler) {
if (method == "SendRemoteAppControl")
EventHandler().send_app_control_event.connect(handler);
}
bool DBusService::HandleSendRemoteAppControl(GVariant* params,
GDBusMethodInvocation* invocation) {
LOG(INFO) << "HandleGetRemoteCapabilities ";
- gchar* operation;
- gchar* uri;
- gchar* mime;
- gchar* appid;
- gchar* pkgid;
- g_variant_get(params, "(sssss)", &operation, &uri, &mime, &appid, &pkgid);
-
- Capability cap(operation, uri, mime, pkgid, appid);
- LOG(INFO) << "From: " << cap.operation();
-
- EventHandler().send_app_control_event(&cap,
- [=](Capability cap, int ret) {
- LOG(INFO) << "RET: " << ret;
- LOG(INFO) << "Success launch: " << cap.operation();
- g_dbus_method_invocation_return_value(invocation,
- g_variant_new("(b)", ret));
- });
+ gchar* device_id;
+ GVariantIter* iter;
+ guchar* data;
+ guint len;
+ g_variant_get(params, "(&sayu)", &device_id, &iter, &len);
+
+ LOG(INFO) << "To: " << device_id;
+ data = reinterpret_cast<guchar*>(g_try_malloc(len));
+ if (!data) {
+ LOG(ERROR) << "Out of memory";
+ return false;
+ }
+
+ int i = 0;
+ while (g_variant_iter_loop(iter, "y", &data[i]))
+ i++;
+
+ EventHandler().send_app_control_event(device_id, data, len);
return true;
}
#include <glib.h>
#include <gio/gio.h>
+#include <sys/types.h>
#include <boost/signals2.hpp>
class Capability;
class DBusService {
- typedef std::function<void(Capability, int)> AppControlHandler;
+ typedef std::function<void(unsigned char*, int)> AppControlHandler;
public:
DBusService();
static void RegisterMethodHandler(const std::string& method,
std::function<void()> handler);
static void RegisterSendAppcontrolHandler(const std::string& method,
- std::function<bool(Capability*, AppControlHandler)> handler);
+ std::function<bool(const std::string&, const unsigned char*,
+ size_t)> handler);
static void RegisterGetRemoteCapsHandler(const std::string& method,
std::function<void(GVariant**)> handler);
public:
boost::signals2::signal<void()> on_event;
boost::signals2::signal<void()> on_event2;
- boost::signals2::signal<bool(Capability*, AppControlHandler)>
- send_app_control_event;
+ boost::signals2::signal<bool(const std::string&, const unsigned char*,
+ size_t)> send_app_control_event;
boost::signals2::signal<void(GVariant**)> get_remote_caps_event;
boost::signals2::signal<void(char* data)> send_data_event;
};
#include <glib.h>
#include <mdg.h>
#include <mdg_internal.h>
+#include <sys/types.h>
#include <cstring>
#include <map>
MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
if (!strcmp(cmd, kSendDataCmd)) {
+ unsigned char* p = arg;
Command cmd;
- memcpy(&cmd, arg, sizeof(unsigned char));
- unsigned char* p = arg + sizeof(unsigned char);
+ memcpy(&cmd, p, sizeof(Command));
+ p = p + sizeof(Command);
+ size_t datasize;
+ memcpy(&datasize, p, sizeof(size_t));
+ p = p + sizeof(size_t);
if (cmd == Command::EXCHANGE_CAPS) {
std::string caps_str = std::string(reinterpret_cast<char*>(p));
std::vector<Capability> caps =
LOG(INFO) << "Received " << caps.size() << " capabilities from device "
<< device_id;
RemoteDeviceManager::RegisterRemoteDevice(device_id, caps);
- } else if (cmd == Command::SEND_CAP) {
- std::string cap_str = std::string(reinterpret_cast<char*>(p));
- Capability cap(cap_str);
- int r = AppControlManager::LaunchApplication(cap);
+ } else if (cmd == Command::SEND_APPCONTROL) {
+ unsigned char* data = p;
+ int r = AppControlManager::LaunchApplication(data, datasize);
if (r != 0)
LOG(ERROR) << "Failed to launch application: " << ret;
}
return true;
}
-bool MDGManager::SendData(Command cmd, const std::string& data) {
- if (!g_list_length(device_list_)) {
- LOG(ERROR) << "No device in list!";
+bool MDGManager::SendData(const std::string& device_id, Command cmd,
+ const unsigned char* data, size_t len) {
+ mdg_device_h device = nullptr;
+ for (auto& dev : GListRange<mdg_device_h>(device_list_)) {
+ char* dev_id;
+ int ret = mdg_device_info_get_device_id(device, &dev_id);
+ if (ret != MDG_ERROR_NONE)
+ continue;
+ ret = strcmp(dev_id, device_id.c_str());
+ free(dev_id);
+ if (ret)
+ continue;
+
+ device = dev;
+ break;
+ }
+
+ if (!device) {
+ LOG(ERROR) << "There is no such device in list!";
return false;
}
- size_t datasize = sizeof(Command) + data.size();
+ // packet format
+ // +----------------------+----------------+-------+
+ // |Command(unsigned char)|datasize(size_t)|data...|
+ // +----------------------+----------------+-------+
+ size_t datasize = sizeof(Command) + sizeof(size_t) + len;
unsigned char* buf = new unsigned char[datasize];
unsigned char* p = buf;
memcpy(p, &cmd, sizeof(Command));
p = p + sizeof(Command);
- memcpy(p, data.c_str(), data.size());
- for (auto& device : GListRange<mdg_device_h>(device_list_)) {
- int ret = mdg_device_send_data(mdg_handle_, device,
- const_cast<char*>(kChannelId),
- buf, datasize, SendDataFinishCb, this);
- if (ret != MDG_ERROR_NONE)
- LOG(ERROR) << "Failed to send data: " << MDGErrorToString(ret);
- }
+ memcpy(p, &len, sizeof(size_t));
+ p = p + sizeof(size_t);
+ memcpy(p, data, len);
+
+ int ret = mdg_device_send_data(mdg_handle_, device,
+ const_cast<char*>(kChannelId),
+ buf, datasize, SendDataFinishCb, this);
+ if (ret != MDG_ERROR_NONE)
+ LOG(ERROR) << "Failed to send data: " << MDGErrorToString(ret);
delete buf;
void MDGManager::ExchangeCapabilities() {
std::string caps = capmgr_->PackCapabilities();
- SendData(Command::EXCHANGE_CAPS, caps);
+ unsigned char* caps_data = new unsigned char[caps.size()];
+ // FIXME: pass device_id?
+ SendData({}, Command::EXCHANGE_CAPS, caps_data, caps.size());
+ delete caps_data;
}
-bool MDGManager::SendCapability(Capability* cap,
- std::function<void(Capability, int)> reply) {
- std::string cap_str = cap->Serialize();
- return SendData(Command::SEND_CAP, cap_str);
+bool MDGManager::SendAppControl(const std::string& device_id,
+ const unsigned char* appcontrol, size_t len) {
+ return SendData(device_id, Command::SEND_APPCONTROL, appcontrol, len);
}
} // namespace capmgr
#include <glib.h>
#include <mdg.h>
+#include <sys/types.h>
#include <functional>
#include <string>
void FindDevices() override;
void RegisterEndpoint() override;
void ExchangeCapabilities() override;
- bool SendCapability(
- Capability* cap, std::function<void(Capability, int)> reply) override;
+ bool SendAppControl(const std::string& device_id,
+ const unsigned char* appcontrol, size_t len) override;
private:
enum class Command : unsigned char {
EXCHANGE_CAPS,
- SEND_CAP,
+ SEND_APPCONTROL,
};
bool Initialize();
bool CreateOrJoinGroup();
- bool SendData(Command cmd, const std::string& data);
+ bool SendData(const std::string& device_id, Command cmd,
+ const unsigned char* data, size_t len);
static void RequestCb(char* cmd, char* device_id, unsigned char* arg,
int len, int ret, void* user_data);