Use raw bundle to sending appcontrol to remote device
authorSangyoon Jang <jeremy.jang@samsung.com>
Tue, 17 Jul 2018 11:06:19 +0000 (20:06 +0900)
committer장상윤/Tizen Platform Lab(SR)/Engineer/삼성전자 <jeremy.jang@samsung.com>
Mon, 23 Jul 2018 06:49:27 +0000 (15:49 +0900)
Change-Id: I5c595b79bbdc732a9b84aa27b8aca72c8cdf9d3f
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
12 files changed:
src/capmgr/capmgr.cc
src/client/CMakeLists.txt
src/client/client.cc
src/client/dbus.cc [new file with mode: 0644]
src/client/dbus.h [new file with mode: 0644]
src/common/appcontrol_manager.cc
src/common/appcontrol_manager.h
src/common/connection_manager.h
src/common/dbus_service.cc
src/common/dbus_service.h
src/common/mdg_manager.cc
src/common/mdg_manager.h

index 9d0fc32da4b79f121b6c0118006870cd3733f6db..5f2f4aa5b6cb717b0a937f24891ecb674d783200 100644 (file)
@@ -77,9 +77,8 @@ bool Capmgr::Initialize() {
       &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;
 }
index 87f1b36cde7ed714342c0bd66b3240ba4cedc7c2..82d2bfdc628b90972a4cfa391a40c740c736a5a1 100644 (file)
@@ -6,7 +6,11 @@ ADD_LIBRARY(${TARGET_LIB_CLIENT} SHARED
 )
 
 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})
index 212aa06e8ff87145dfa62e8036c0098611c7c2a5..863fc9f66d4c72b5aac94cbbafbb5456f46f2002 100644 (file)
@@ -2,11 +2,17 @@
 // 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"
@@ -33,11 +39,7 @@ struct capmgr_device_s {
 
 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,
@@ -193,7 +195,11 @@ API int capmgr_app_control_create(capmgr_app_control_h* app_control) {
 
   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();
@@ -216,11 +222,12 @@ API int capmgr_app_control_clone(const capmgr_app_control_h app_control,
       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) {
@@ -236,6 +243,7 @@ API int capmgr_app_control_destroy(capmgr_app_control_h app_control) {
     return CAPMGR_ERROR_INVALID_PARAMETER;
 
   capmgr_device_destroy(app_control->device);
+  bundle_free(app_control->b);
   delete app_control;
 
   return CAPMGR_ERROR_NONE;
@@ -246,7 +254,16 @@ API int capmgr_app_control_get_operation(capmgr_app_control_h app_control,
   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;
 
@@ -258,7 +275,11 @@ API int capmgr_app_control_get_uri(capmgr_app_control_h app_control,
   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;
 
@@ -270,7 +291,11 @@ API int capmgr_app_control_get_mime(capmgr_app_control_h app_control,
   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;
 
@@ -282,7 +307,11 @@ API int capmgr_app_control_get_appid(capmgr_app_control_h app_control,
   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;
 
@@ -296,13 +325,13 @@ API int capmgr_app_control_get_extra_data(capmgr_app_control_h app_control,
 
   // 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;
 
@@ -326,7 +355,9 @@ API int capmgr_app_control_set_operation(capmgr_app_control_h app_control,
   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;
 }
@@ -336,7 +367,9 @@ API int capmgr_app_control_set_uri(capmgr_app_control_h app_control,
   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;
 }
@@ -346,7 +379,9 @@ API int capmgr_app_control_set_mime(capmgr_app_control_h app_control,
   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;
 }
@@ -356,7 +391,9 @@ API int capmgr_app_control_set_appid(capmgr_app_control_h app_control,
   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;
 }
@@ -368,11 +405,9 @@ API int capmgr_app_control_add_extra_data(capmgr_app_control_h app_control,
 
   // 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;
 }
@@ -384,13 +419,9 @@ API int capmgr_app_control_remove_extra_data(capmgr_app_control_h app_control,
 
   // 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;
 }
@@ -399,7 +430,35 @@ API int capmgr_app_control_send(capmgr_app_control_h app_control) {
   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;
 }
diff --git a/src/client/dbus.cc b/src/client/dbus.cc
new file mode 100644 (file)
index 0000000..acb55eb
--- /dev/null
@@ -0,0 +1,60 @@
+// 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
diff --git a/src/client/dbus.h b/src/client/dbus.h
new file mode 100644 (file)
index 0000000..722719a
--- /dev/null
@@ -0,0 +1,16 @@
+// 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_
index e54ceb5939ba7228e1b91769449cf33e101b511b..90f2c252b35c248e361e4fb27226dd68131beb7a 100644 (file)
 
 #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
index f8f331738e9281a3f94f4b868d22e4a20ba0ba70..fdb167289bf6088d8424bcb45d6cd6020f2b4e2d 100644 (file)
@@ -16,7 +16,7 @@ class AppControlManager {
   AppControlManager();
   ~AppControlManager();
 
-  static int LaunchApplication(const Capability& capability);
+  static bool LaunchApplication(const unsigned char* data, size_t len);
  private:
 };
 
index 825faea6b6170334b7950b648e75b2aae2d1a64d..451443edd51e7669389f21b13d32290e3426caf1 100644 (file)
@@ -5,6 +5,10 @@
 #ifndef COMMON_CONNECTION_MANAGER_H_
 #define COMMON_CONNECTION_MANAGER_H_
 
+#include <sys/types.h>
+
+#include <string>
+
 namespace capmgr {
 
 class CapabilityManager;
@@ -17,8 +21,8 @@ class ConnectionManager {
   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_;
index 2cf32b7fbf9469cfdb3fc79fa2cd966adc3d0248..c48ce86cdf4ba9de24d002abc937edc62528b2db 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <glib.h>
 #include <gio/gio.h>
+#include <sys/types.h>
 
 #include <functional>
 #include <vector>
@@ -28,9 +29,9 @@ const char kDBusInstropectionXml[] =
   "      <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>"
@@ -74,7 +75,8 @@ void DBusService::RegisterMethodHandler(const std::string& method,
 }
 
 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);
 }
@@ -100,23 +102,24 @@ bool DBusService::HandleExchangeCapabilities(GVariant* params,
 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;
 }
 
index c934ee73bfe093c699c03bcf4f412964a5dc54dd..f224a4263336752ed49b221d22c7f8d5ed15d411 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <glib.h>
 #include <gio/gio.h>
+#include <sys/types.h>
 
 #include <boost/signals2.hpp>
 
@@ -17,7 +18,7 @@ namespace capmgr {
 class Capability;
 
 class DBusService {
-  typedef std::function<void(Capability, int)> AppControlHandler;
+  typedef std::function<void(unsigned char*, int)> AppControlHandler;
 
  public:
   DBusService();
@@ -26,7 +27,8 @@ class 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);
 
@@ -35,8 +37,8 @@ class DBusService {
    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;
   };
index d64aa2b81edf226b6aa2f511469c58081e5be983..6a114b9c27eaffd2b9482a5ed5f580ca957ca6e7 100644 (file)
@@ -7,6 +7,7 @@
 #include <glib.h>
 #include <mdg.h>
 #include <mdg_internal.h>
+#include <sys/types.h>
 
 #include <cstring>
 #include <map>
@@ -98,9 +99,13 @@ void MDGManager::RequestCb(char* cmd, char* device_id, unsigned char* arg,
 
   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 =
@@ -108,10 +113,9 @@ void MDGManager::RequestCb(char* cmd, char* device_id, unsigned char* arg,
       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;
     }
@@ -286,26 +290,47 @@ bool MDGManager::CreateOrJoinGroup() {
   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;
 
@@ -324,13 +349,15 @@ void MDGManager::RegisterEndpoint() {
 
 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
index 45f172f6f3c04417b309ea8438902ceab1f96a4f..c0e0248e8ee31bebbb442d864403dfc8c4333c82 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <glib.h>
 #include <mdg.h>
+#include <sys/types.h>
 
 #include <functional>
 #include <string>
@@ -26,18 +27,19 @@ class MDGManager : public ConnectionManager {
   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);