Add TIDL code for signal transmisstion 29/309029/2
authorIlho Kim <ilho159.kim@samsung.com>
Thu, 4 Apr 2024 02:18:41 +0000 (11:18 +0900)
committerIlho Kim <ilho159.kim@samsung.com>
Thu, 4 Apr 2024 06:36:18 +0000 (15:36 +0900)
Change-Id: Idc6cff23a044c07d06641662e663a3f5d4c667b5
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
client/src/PkgSignal.cc [new file with mode: 0644]
client/src/PkgSignal.h [new file with mode: 0644]
client/src/signal_receiver.cc [new file with mode: 0644]
client/src/signal_receiver.hh [new file with mode: 0644]
installer/src/PkgSignal.cc [new file with mode: 0644]
installer/src/PkgSignal.h [new file with mode: 0644]

diff --git a/client/src/PkgSignal.cc b/client/src/PkgSignal.cc
new file mode 100644 (file)
index 0000000..7869ac3
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <dlog.h>
+
+#include "PkgSignal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_GROUP"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "2.0.4"
+#endif
+
+namespace rpc_port {
+namespace PkgSignal {
+
+PkgInfo::PkgInfo() {}
+
+PkgInfo::PkgInfo(std::string Pkgid, std::string Appid, std::string PkgType)
+    : Pkgid_(std::move(Pkgid)), Appid_(std::move(Appid)), PkgType_(std::move(PkgType)) {}
+
+
+PathInfo::PathInfo() {}
+
+PathInfo::PathInfo(std::string Path, int State)
+    : Path_(std::move(Path)), State_(std::move(State)) {}
+
+
+ExtraData::ExtraData() {}
+
+ExtraData::ExtraData(int ErrCode, std::vector<PathInfo> Paths)
+    : ErrCode_(std::move(ErrCode)), Paths_(std::move(Paths)) {}
+
+
+namespace group {
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PkgInfo& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PkgInfo& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PathInfo& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PathInfo& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const ExtraData& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, ExtraData& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PathInfo>& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PathInfo>& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PkgInfo>& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PkgInfo>& param);
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PkgInfo& param) {
+  rpc_port_parcel_write_string(h, param.GetPkgid().c_str());
+  rpc_port_parcel_write_string(h, param.GetAppid().c_str());
+  rpc_port_parcel_write_string(h, param.GetPkgType().c_str());
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PathInfo& param) {
+  rpc_port_parcel_write_string(h, param.GetPath().c_str());
+  rpc_port_parcel_write_int32(h, param.GetState());
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const ExtraData& param) {
+  rpc_port_parcel_write_int32(h, param.GetErrCode());
+  h << param.GetPaths();
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PkgInfo& param) {
+  char* Pkgid_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Pkgid_raw);
+  std::string Pkgid(Pkgid_raw);
+  free(Pkgid_raw);
+  param.SetPkgid(std::move(Pkgid));
+
+  char* Appid_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Appid_raw);
+  std::string Appid(Appid_raw);
+  free(Appid_raw);
+  param.SetAppid(std::move(Appid));
+
+  char* PkgType_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &PkgType_raw);
+  std::string PkgType(PkgType_raw);
+  free(PkgType_raw);
+  param.SetPkgType(std::move(PkgType));
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PathInfo& param) {
+  char* Path_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Path_raw);
+  std::string Path(Path_raw);
+  free(Path_raw);
+  param.SetPath(std::move(Path));
+
+  int State;
+  rpc_port_parcel_read_int32(h, &State);
+  param.SetState(State);
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, ExtraData& param) {
+  int ErrCode;
+  rpc_port_parcel_read_int32(h, &ErrCode);
+  param.SetErrCode(ErrCode);
+
+  std::vector<PathInfo> Paths;
+  h >> Paths;
+  param.SetPaths(std::move(Paths));
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PathInfo>& param) {
+  rpc_port_parcel_write_array_count(h, param.size());
+  for (const auto& i : param) {
+    h << i;
+
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PathInfo>& param) {
+  int l = 0;
+  rpc_port_parcel_read_array_count(h, &l);
+
+  for (int i = 0; i < l; i++) {
+    PathInfo v;
+    h >> v;
+
+    param.push_back(std::move(v));
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PkgInfo>& param) {
+  rpc_port_parcel_write_array_count(h, param.size());
+  for (const auto& i : param) {
+    h << i;
+
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PkgInfo>& param) {
+  int l = 0;
+  rpc_port_parcel_read_array_count(h, &l);
+
+  for (int i = 0; i < l; i++) {
+    PkgInfo v;
+    h >> v;
+
+    param.push_back(std::move(v));
+  }
+
+  return h;
+}
+
+PkgSignal::PkgSignal(std::string sender_appid, bool is_system)
+    : sender_appid_(std::move(sender_appid)), is_system_(is_system) {
+  Subscribe();
+}
+
+
+PkgSignal::~PkgSignal() {
+  Unsubscribe();
+}
+
+void PkgSignal::Subscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_add_event_handler(GetEventName().c_str(), EventCb, this, &event_handler_);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to register events. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void PkgSignal::Unsubscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  if (event_handler_) {
+    event_remove_event_handler(event_handler_);
+    event_handler_ = nullptr;
+  }
+}
+
+bundle* PkgSignal::GetBundleFromParcel(rpc_port_parcel_h p, bundle* b) {
+  void* raw = nullptr;
+  unsigned int size = 0;
+
+  int ret = rpc_port_parcel_get_raw(p, &raw, &size);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  ret = bundle_add_byte(b, "TIDL_RAW", raw, size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  return b;
+}
+
+rpc_port_parcel_h PkgSignal::GetParcelFromBundle(bundle* b) {
+  void* raw = nullptr;
+  size_t size = 0;
+  rpc_port_parcel_h p;
+
+  int ret = bundle_get_byte(b, "TIDL_RAW", &raw, &size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  ret = rpc_port_parcel_create_from_raw(&p, raw,
+      static_cast<unsigned int>(size));
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  return p;
+}
+
+std::string PkgSignal::GetEventName() {
+  if (is_system_)
+    return "tizen.system.event.tidl_iface_PkgSignal";
+  return "event." + sender_appid_ + ".tidl_iface_PkgSignal";
+}
+
+void PkgSignal::EventCb(const char* event_name, bundle* event_data, void* user_data) {
+  auto* ptr = static_cast<PkgSignal*>(user_data);
+  rpc_port_parcel_h p = ptr->GetParcelFromBundle(event_data);
+  if (p == nullptr) {
+    _E("Invalid bundle");
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+
+  rpc_port_parcel_h header;
+  int seq_num = -1;
+  int cmd;
+  rpc_port_parcel_get_header(p, &header);
+  rpc_port_parcel_header_get_seq_num(header, &seq_num);
+
+  _W("[Sequence] %d", seq_num);
+  rpc_port_parcel_read_int32(p, &cmd);
+  switch (cmd) {
+
+    case static_cast<int>(MethodId::AsyncResult):
+    {
+      char* param1_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param1_raw);
+      std::string param1(param1_raw);
+      free(param1_raw);
+      int param2;
+      rpc_port_parcel_read_int32(p, &param2);
+      char* param3_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param3_raw);
+      std::string param3(param3_raw);
+      free(param3_raw);
+      std::vector<PkgInfo> param4;
+      p >> param4;
+      char* param5_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param5_raw);
+      std::string param5(param5_raw);
+      free(param5_raw);
+      char* param6_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param6_raw);
+      std::string param6(param6_raw);
+      free(param6_raw);
+      ptr->OnAsyncResult(param1, param2, param3, param4, param5, param6);
+
+    }
+    break;
+
+
+    case static_cast<int>(MethodId::AsyncResultForResource):
+    {
+      char* param1_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param1_raw);
+      std::string param1(param1_raw);
+      free(param1_raw);
+      int param2;
+      rpc_port_parcel_read_int32(p, &param2);
+      char* param3_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param3_raw);
+      std::string param3(param3_raw);
+      free(param3_raw);
+      char* param4_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param4_raw);
+      std::string param4(param4_raw);
+      free(param4_raw);
+      char* param5_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param5_raw);
+      std::string param5(param5_raw);
+      free(param5_raw);
+      ExtraData param6;
+      p >> param6;
+      ptr->OnAsyncResultForResource(param1, param2, param3, param4, param5, param6);
+
+    }
+    break;
+
+
+
+    default:
+      _E("Unknown command(%d)", cmd);
+  }
+}
+
+
+void PkgSignal::AsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val) {
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::AsyncResult));
+  rpc_port_parcel_write_string(p, signal.c_str());
+  rpc_port_parcel_write_int32(p, targetUid);
+  rpc_port_parcel_write_string(p, reqId.c_str());
+  p << pkgs;
+  rpc_port_parcel_write_string(p, key.c_str());
+  rpc_port_parcel_write_string(p, val.c_str());
+
+
+  // Send
+  bundle* b = bundle_create();
+  std::unique_ptr<bundle, decltype(bundle_free)*> b_auto(b, bundle_free);
+  if (GetBundleFromParcel(p, b) == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void PkgSignal::AsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra) {
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::AsyncResultForResource));
+  rpc_port_parcel_write_string(p, signal.c_str());
+  rpc_port_parcel_write_int32(p, targetUid);
+  rpc_port_parcel_write_string(p, reqId.c_str());
+  rpc_port_parcel_write_string(p, pkgid.c_str());
+  rpc_port_parcel_write_string(p, status.c_str());
+  p << extra;
+
+
+  // Send
+  bundle* b = bundle_create();
+  std::unique_ptr<bundle, decltype(bundle_free)*> b_auto(b, bundle_free);
+  if (GetBundleFromParcel(p, b) == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+}  // namespace group
+}  // namespace PkgSignal
+}  // namespace rpc_port
diff --git a/client/src/PkgSignal.h b/client/src/PkgSignal.h
new file mode 100644 (file)
index 0000000..b7a319d
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#pragma once
+
+#include <app_event.h>
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <mutex>
+#include <list>
+#include <atomic>
+
+
+namespace rpc_port {
+namespace PkgSignal {
+
+class Bundle final {
+ public:
+  Bundle() {
+    raw_ = bundle_create();
+  }
+
+  Bundle(bundle* b) {
+    raw_ = b;
+  }
+
+  ~Bundle() {
+    if (raw_)
+      bundle_free(raw_);
+  }
+
+  Bundle(Bundle&& b) : raw_(b.raw_) {
+    b.raw_ = nullptr;
+  }
+
+  Bundle& operator = (Bundle&& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = b.raw_;
+      b.raw_ = nullptr;
+    }
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = bundle_dup(b.GetHandle());
+    }
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+class File final {
+ public:
+  File() {
+  }
+
+  File(std::string filename) {
+    filename_ = filename;
+  }
+
+  std::string GetFileName() const {
+    return filename_;
+  }
+
+ private:
+  std::string filename_;
+};
+
+
+class PkgInfo final {
+ public:
+  PkgInfo();
+  PkgInfo(std::string Pkgid, std::string Appid, std::string PkgType);
+  
+  void SetPkgid(std::string Pkgid) {
+    Pkgid_ = std::move(Pkgid);
+  }
+
+  const std::string& GetPkgid() const {
+    return Pkgid_;
+  }
+
+  void SetAppid(std::string Appid) {
+    Appid_ = std::move(Appid);
+  }
+
+  const std::string& GetAppid() const {
+    return Appid_;
+  }
+
+  void SetPkgType(std::string PkgType) {
+    PkgType_ = std::move(PkgType);
+  }
+
+  const std::string& GetPkgType() const {
+    return PkgType_;
+  }
+
+
+ private:
+  std::string Pkgid_;
+  std::string Appid_;
+  std::string PkgType_;
+
+};
+
+class PathInfo final {
+ public:
+  PathInfo();
+  PathInfo(std::string Path, int State);
+  
+  void SetPath(std::string Path) {
+    Path_ = std::move(Path);
+  }
+
+  const std::string& GetPath() const {
+    return Path_;
+  }
+
+  void SetState(int State) {
+    State_ = State;
+  }
+
+  int GetState() const {
+    return State_;
+  }
+
+
+ private:
+  std::string Path_;
+  int State_ = 0;
+
+};
+
+class ExtraData final {
+ public:
+  ExtraData();
+  ExtraData(int ErrCode, std::vector<PathInfo> Paths);
+  
+  void SetErrCode(int ErrCode) {
+    ErrCode_ = ErrCode;
+  }
+
+  int GetErrCode() const {
+    return ErrCode_;
+  }
+
+  void SetPaths(std::vector<PathInfo> Paths) {
+    Paths_ = std::move(Paths);
+  }
+
+  const std::vector<PathInfo>& GetPaths() const {
+    return Paths_;
+  }
+
+
+ private:
+  int ErrCode_ = 0;
+  std::vector<PathInfo> Paths_;
+
+};
+
+namespace group {
+
+
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class PermissionDeniedException : public Exception {};
+class InvalidIDException : public Exception {};
+
+
+class PkgSignal {
+ public:
+  PkgSignal(std::string sender_appid, bool is_system = false);
+  virtual ~PkgSignal();
+
+  
+  
+  void AsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val);
+
+  virtual void OnAsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val) {}
+
+  
+  void AsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra);
+
+  virtual void OnAsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra) {}
+
+
+ private:
+
+  enum class MethodId : int {
+    __Result = 0,
+    __Callback = 1,
+    AsyncResult = 2,
+    AsyncResultForResource = 3,
+
+  };
+
+
+  bundle* GetBundleFromParcel(rpc_port_parcel_h p, bundle* b);
+  rpc_port_parcel_h GetParcelFromBundle(bundle* b);
+  std::string GetEventName();
+  void Subscribe();
+  void Unsubscribe();
+  static void EventCb(const char* event_name, bundle* event_data, void* user_data);
+
+ private:
+  event_handler_h event_handler_ = nullptr;
+  std::string sender_appid_;
+  std::recursive_mutex mutex_;
+  bool is_system_;
+};
+
+}  // namespace group
+}  // namespace PkgSignal
+}  // namespace rpc_port
diff --git a/client/src/signal_receiver.cc b/client/src/signal_receiver.cc
new file mode 100644 (file)
index 0000000..c95bcea
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include "signal_receiver.hh"
+
+namespace pkgmgr {
+namespace client {
+
+#define AGENT_APPID "signal_agent"
+
+SignalReceiver::SignalReceiver(bool is_system)
+    : PkgSignal(is_system ? "" : AGENT_APPID, is_system) {
+}
+
+SignalReceiver::~SignalReceiver() {
+}
+
+void SignalReceiver::OnAsyncResult(std::string signal, int targetUid,
+    std::string reqId, std::vector<pkg_signal::PkgInfo> pkgs,
+    std::string key, std::string val) {
+  HandleHandler(targetUid, reqId, pkgs, key, val);
+  HandleGlobalHandler(targetUid, reqId, pkgs, key, val);
+  HandleSizeInfoHandler(reqId, pkgs, key, val);
+}
+
+void SignalReceiver::HandleHandler(int targetUid,
+    const std::string& reqId, const std::vector<pkg_signal::PkgInfo>& pkgs,
+    const std::string& key, const std::string& val) const {
+  const auto it = handlers_.find(reqId);
+  if (it == handlers_.end())
+    return;
+  const auto& [id, cb, app_cb, data] = it->second;
+
+  for (auto& i : pkgs) {
+    if (cb) {
+      cb(targetUid, id, i.GetPkgType().c_str(), i.GetPkgid().c_str(),
+          key.c_str(), val.c_str(), nullptr, data);
+    } else {
+      app_cb(targetUid, id, i.GetPkgType().c_str(), i.GetPkgid().c_str(),
+          i.GetAppid().c_str(), key.c_str(), val.c_str(), nullptr, data);
+    }
+  }
+}
+
+void SignalReceiver::HandleGlobalHandler(int targetUid,
+    const std::string& reqId, const std::vector<pkg_signal::PkgInfo>& pkgs,
+    const std::string& key, const std::string& val) const {
+  for (auto& i : pkgs) {
+    for (const auto& [id, cb, app_cb, data] : global_handlers_) {
+      if (cb) {
+        cb(targetUid, id, i.GetPkgType().c_str(), i.GetPkgid().c_str(),
+            key.c_str(), val.c_str(), nullptr, data);
+      } else {
+        app_cb(targetUid, id, i.GetPkgType().c_str(), i.GetPkgid().c_str(),
+            i.GetAppid().c_str(), key.c_str(), val.c_str(), nullptr, data);
+      }
+    }
+  }
+}
+
+void SignalReceiver::HandleSizeInfoHandler(
+    const std::string& reqId, const std::vector<pkg_signal::PkgInfo>& pkgs,
+    const std::string& key, const std::string& val) const {
+  auto it = size_info_handlers_.find(reqId);
+  if (it == size_info_handlers_.end())
+    return;
+  const auto& [id, cb, pc, data] = it->second;
+
+  std::vector<std::string> tokens;
+  std::istringstream ss(val);
+  std::string token;
+
+  while (std::getline(ss, token, ':')) {
+      tokens.push_back(token);
+  }
+
+  if (tokens.size() != 6) {
+        return;
+    }
+
+  pkg_size_info_t size_info{
+      std::stoll(tokens[0]),
+      std::stoll(tokens[1]),
+      std::stoll(tokens[2]),
+      std::stoll(tokens[3]),
+      std::stoll(tokens[4]),
+      std::stoll(tokens[5]),
+  };
+
+  for (auto& i : pkgs) {
+    if (i.GetPkgid() == std::string(PKG_SIZE_INFO_TOTAL)) {
+      pkgmgr_total_pkg_size_info_receive_cb callback;
+      callback = (pkgmgr_total_pkg_size_info_receive_cb)cb;
+      callback(pc, &size_info, data);
+    } else {
+      cb(pc, i.GetPkgid().c_str(), &size_info, data);
+    }
+  }
+}
+
+void SignalReceiver::OnAsyncResultForResource(std::string signal,
+    int targetUid, std::string reqId, std::string pkgid,
+    std::string status, pkg_signal::ExtraData extra) {
+  HandleResHandler(signal, targetUid, reqId, pkgid, status, extra);
+  HandleGlobalResHandler(signal, targetUid, reqId, pkgid, status, extra);
+}
+
+void SignalReceiver::HandleResHandler(const std::string& signal,
+    int targetUid, const std::string& reqId, const std::string& pkgid,
+    const std::string& status, pkg_signal::ExtraData& extra) const {
+  auto it = res_handlers_.find(reqId);
+  if (it == res_handlers_.end())
+    return;
+  const auto& [id, cb, data] = it->second;
+
+  cb(targetUid, id, pkgid.c_str(), signal.c_str(), status.c_str(),
+      static_cast<void*>(&extra), data);
+}
+
+void SignalReceiver::HandleGlobalResHandler(const std::string& signal,
+    int targetUid, const std::string& reqId, const std::string& pkgid,
+    const std::string& status, pkg_signal::ExtraData& extra) const {
+  for (const auto& [id, cb, data] : global_res_handlers_) {
+    cb(targetUid, id, pkgid.c_str(), signal.c_str(), status.c_str(),
+        static_cast<void*>(&extra), data);
+  }
+}
+
+
+int SignalReceiver::AddEventHandler(std::string req_key,
+    pkgmgr_handler event_cb, void* data) {
+  return AddEventHandler(std::move(req_key), event_cb, nullptr, data);
+}
+
+int SignalReceiver::AddEventHandler(std::string req_key,
+    pkgmgr_app_handler app_event_cb, void* data) {
+  return AddEventHandler(std::move(req_key), nullptr, app_event_cb, data);
+}
+
+int SignalReceiver::AddEventHandler(std::string req_key,
+      pkgmgr_pkg_size_info_receive_cb event_cb, void* pc, void* data) {
+  int sId = SignalReceiver::GetRequestId();
+  if (req_key.empty())
+    global_size_info_handlers_.emplace_back(sId, event_cb, pc, data);
+  else
+    size_info_handlers_[req_key] = { sId, event_cb, pc, data };
+  return sId;
+}
+
+int SignalReceiver::AddEventHandler(std::string req_key,
+    pkgmgr_handler event_cb, pkgmgr_app_handler app_event_cb, void* data) {
+  int sId = SignalReceiver::GetRequestId();
+  if (req_key.empty())
+    global_handlers_.emplace_back(sId, event_cb, app_event_cb, data);
+  else
+    handlers_[req_key] = { sId, event_cb, app_event_cb, data };
+  return sId;
+}
+
+int SignalReceiver::AddEventHandler(std::string req_key,
+    pkgmgr_res_handler event_cb, void* data) {
+  int sId = SignalReceiver::GetRequestId();
+  if (req_key.empty())
+    global_res_handlers_.emplace_back(sId, event_cb, data);
+  else
+    res_handlers_[req_key] = { sId, event_cb, data };
+  return sId;
+}
+
+
+int SignalReceiver::GetRequestId() {
+  return ++request_id_;
+}
+
+}  // namespace client
+}  // namespace pkgmgr
+
diff --git a/client/src/signal_receiver.hh b/client/src/signal_receiver.hh
new file mode 100644 (file)
index 0000000..b6cf64b
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef CLIENT_SRC_SIGNAL_RECEIVER_H_
+#define CLIENT_SRC_SIGNAL_RECEIVER_H_
+
+#include "package-manager.h"
+
+#include <map>
+#include <memory>
+#include <string>
+#include <tuple>
+
+#include "PkgSignal.h"
+
+
+namespace pkgmgr {
+namespace client {
+
+namespace pkg_group = rpc_port::PkgSignal::group;
+namespace pkg_signal = rpc_port::PkgSignal;
+
+class SignalReceiver : public pkg_group::PkgSignal {
+ public:
+  SignalReceiver(bool is_system);
+  virtual ~SignalReceiver();
+
+  void OnAsyncResult(std::string signal, int targetUid, std::string reqId,
+      std::vector<pkg_signal::PkgInfo> pkgs, std::string key,
+      std::string val) override;
+
+  void OnAsyncResultForResource(std::string signal, int targetUid,
+      std::string reqId, std::string pkgid, std::string status,
+      pkg_signal::ExtraData extra) override;
+
+  int AddEventHandler(std::string req_key, pkgmgr_handler event_cb, void* data);
+  int AddEventHandler(std::string req_key, pkgmgr_app_handler app_event_cb,
+      void* data);
+  int AddEventHandler(std::string req_key,
+      pkgmgr_pkg_size_info_receive_cb event_cb, void* pc, void* data);
+  int AddEventHandler(std::string req_key, pkgmgr_res_handler event_cb,
+      void* data);
+
+ private:
+  static int GetRequestId();
+  int AddEventHandler(std::string req_key, pkgmgr_handler event_cb,
+      pkgmgr_app_handler app_event_cb, void* data);
+  void HandleHandler(int targetUid, const std::string& reqId,
+      const std::vector<pkg_signal::PkgInfo>& pkgs, const std::string& key,
+      const std::string& val) const;
+  void HandleGlobalHandler(int targetUid, const std::string& reqId,
+      const std::vector<pkg_signal::PkgInfo>& pkgs, const std::string& key,
+      const std::string& val) const;
+  void HandleResHandler(const std::string& signal, int targetUid,
+      const std::string& reqId, const std::string& pkgid,
+      const std::string& status, pkg_signal::ExtraData& extra) const;
+  void HandleGlobalResHandler(const std::string& signal, int targetUid,
+      const std::string& reqId, const std::string& pkgid,
+      const std::string& status, pkg_signal::ExtraData& extra) const;
+  void HandleSizeInfoHandler(const std::string& reqId,
+      const std::vector<pkg_signal::PkgInfo>& pkgs,
+      const std::string& key, const std::string& val) const;
+
+ private:
+  static inline int request_id_;
+  std::map<std::string, std::tuple<int, pkgmgr_handler, pkgmgr_app_handler,
+      void*>> handlers_;
+  std::list<std::tuple<int, pkgmgr_handler, pkgmgr_app_handler, void*>> global_handlers_;
+  std::map<std::string,
+      std::tuple<int, pkgmgr_res_handler, void*>> res_handlers_;
+  std::list<std::tuple<int, pkgmgr_res_handler, void*>> global_res_handlers_;
+  std::map<std::string,
+      std::tuple<int, pkgmgr_pkg_size_info_receive_cb, void*, void*>> size_info_handlers_;
+  std::list<std::tuple<int, pkgmgr_pkg_size_info_receive_cb, void*, void*>> global_size_info_handlers_;
+};
+
+}  // namespace client
+}  // namespace pkgmgr
+
+#endif  // CLIENT_SRC_CONNECTOR_H_
\ No newline at end of file
diff --git a/installer/src/PkgSignal.cc b/installer/src/PkgSignal.cc
new file mode 100644 (file)
index 0000000..7869ac3
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <dlog.h>
+
+#include "PkgSignal.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_GROUP"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "2.0.4"
+#endif
+
+namespace rpc_port {
+namespace PkgSignal {
+
+PkgInfo::PkgInfo() {}
+
+PkgInfo::PkgInfo(std::string Pkgid, std::string Appid, std::string PkgType)
+    : Pkgid_(std::move(Pkgid)), Appid_(std::move(Appid)), PkgType_(std::move(PkgType)) {}
+
+
+PathInfo::PathInfo() {}
+
+PathInfo::PathInfo(std::string Path, int State)
+    : Path_(std::move(Path)), State_(std::move(State)) {}
+
+
+ExtraData::ExtraData() {}
+
+ExtraData::ExtraData(int ErrCode, std::vector<PathInfo> Paths)
+    : ErrCode_(std::move(ErrCode)), Paths_(std::move(Paths)) {}
+
+
+namespace group {
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PkgInfo& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PkgInfo& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PathInfo& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PathInfo& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const ExtraData& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, ExtraData& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PathInfo>& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PathInfo>& param);
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PkgInfo>& param);
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PkgInfo>& param);
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PkgInfo& param) {
+  rpc_port_parcel_write_string(h, param.GetPkgid().c_str());
+  rpc_port_parcel_write_string(h, param.GetAppid().c_str());
+  rpc_port_parcel_write_string(h, param.GetPkgType().c_str());
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const PathInfo& param) {
+  rpc_port_parcel_write_string(h, param.GetPath().c_str());
+  rpc_port_parcel_write_int32(h, param.GetState());
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const ExtraData& param) {
+  rpc_port_parcel_write_int32(h, param.GetErrCode());
+  h << param.GetPaths();
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PkgInfo& param) {
+  char* Pkgid_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Pkgid_raw);
+  std::string Pkgid(Pkgid_raw);
+  free(Pkgid_raw);
+  param.SetPkgid(std::move(Pkgid));
+
+  char* Appid_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Appid_raw);
+  std::string Appid(Appid_raw);
+  free(Appid_raw);
+  param.SetAppid(std::move(Appid));
+
+  char* PkgType_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &PkgType_raw);
+  std::string PkgType(PkgType_raw);
+  free(PkgType_raw);
+  param.SetPkgType(std::move(PkgType));
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, PathInfo& param) {
+  char* Path_raw  = nullptr;
+  rpc_port_parcel_read_string(h, &Path_raw);
+  std::string Path(Path_raw);
+  free(Path_raw);
+  param.SetPath(std::move(Path));
+
+  int State;
+  rpc_port_parcel_read_int32(h, &State);
+  param.SetState(State);
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, ExtraData& param) {
+  int ErrCode;
+  rpc_port_parcel_read_int32(h, &ErrCode);
+  param.SetErrCode(ErrCode);
+
+  std::vector<PathInfo> Paths;
+  h >> Paths;
+  param.SetPaths(std::move(Paths));
+
+  return h;
+}
+
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PathInfo>& param) {
+  rpc_port_parcel_write_array_count(h, param.size());
+  for (const auto& i : param) {
+    h << i;
+
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PathInfo>& param) {
+  int l = 0;
+  rpc_port_parcel_read_array_count(h, &l);
+
+  for (int i = 0; i < l; i++) {
+    PathInfo v;
+    h >> v;
+
+    param.push_back(std::move(v));
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const std::vector<PkgInfo>& param) {
+  rpc_port_parcel_write_array_count(h, param.size());
+  for (const auto& i : param) {
+    h << i;
+
+  }
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, std::vector<PkgInfo>& param) {
+  int l = 0;
+  rpc_port_parcel_read_array_count(h, &l);
+
+  for (int i = 0; i < l; i++) {
+    PkgInfo v;
+    h >> v;
+
+    param.push_back(std::move(v));
+  }
+
+  return h;
+}
+
+PkgSignal::PkgSignal(std::string sender_appid, bool is_system)
+    : sender_appid_(std::move(sender_appid)), is_system_(is_system) {
+  Subscribe();
+}
+
+
+PkgSignal::~PkgSignal() {
+  Unsubscribe();
+}
+
+void PkgSignal::Subscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_add_event_handler(GetEventName().c_str(), EventCb, this, &event_handler_);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to register events. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void PkgSignal::Unsubscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  if (event_handler_) {
+    event_remove_event_handler(event_handler_);
+    event_handler_ = nullptr;
+  }
+}
+
+bundle* PkgSignal::GetBundleFromParcel(rpc_port_parcel_h p, bundle* b) {
+  void* raw = nullptr;
+  unsigned int size = 0;
+
+  int ret = rpc_port_parcel_get_raw(p, &raw, &size);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  ret = bundle_add_byte(b, "TIDL_RAW", raw, size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  return b;
+}
+
+rpc_port_parcel_h PkgSignal::GetParcelFromBundle(bundle* b) {
+  void* raw = nullptr;
+  size_t size = 0;
+  rpc_port_parcel_h p;
+
+  int ret = bundle_get_byte(b, "TIDL_RAW", &raw, &size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  ret = rpc_port_parcel_create_from_raw(&p, raw,
+      static_cast<unsigned int>(size));
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  return p;
+}
+
+std::string PkgSignal::GetEventName() {
+  if (is_system_)
+    return "tizen.system.event.tidl_iface_PkgSignal";
+  return "event." + sender_appid_ + ".tidl_iface_PkgSignal";
+}
+
+void PkgSignal::EventCb(const char* event_name, bundle* event_data, void* user_data) {
+  auto* ptr = static_cast<PkgSignal*>(user_data);
+  rpc_port_parcel_h p = ptr->GetParcelFromBundle(event_data);
+  if (p == nullptr) {
+    _E("Invalid bundle");
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+
+  rpc_port_parcel_h header;
+  int seq_num = -1;
+  int cmd;
+  rpc_port_parcel_get_header(p, &header);
+  rpc_port_parcel_header_get_seq_num(header, &seq_num);
+
+  _W("[Sequence] %d", seq_num);
+  rpc_port_parcel_read_int32(p, &cmd);
+  switch (cmd) {
+
+    case static_cast<int>(MethodId::AsyncResult):
+    {
+      char* param1_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param1_raw);
+      std::string param1(param1_raw);
+      free(param1_raw);
+      int param2;
+      rpc_port_parcel_read_int32(p, &param2);
+      char* param3_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param3_raw);
+      std::string param3(param3_raw);
+      free(param3_raw);
+      std::vector<PkgInfo> param4;
+      p >> param4;
+      char* param5_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param5_raw);
+      std::string param5(param5_raw);
+      free(param5_raw);
+      char* param6_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param6_raw);
+      std::string param6(param6_raw);
+      free(param6_raw);
+      ptr->OnAsyncResult(param1, param2, param3, param4, param5, param6);
+
+    }
+    break;
+
+
+    case static_cast<int>(MethodId::AsyncResultForResource):
+    {
+      char* param1_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param1_raw);
+      std::string param1(param1_raw);
+      free(param1_raw);
+      int param2;
+      rpc_port_parcel_read_int32(p, &param2);
+      char* param3_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param3_raw);
+      std::string param3(param3_raw);
+      free(param3_raw);
+      char* param4_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param4_raw);
+      std::string param4(param4_raw);
+      free(param4_raw);
+      char* param5_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param5_raw);
+      std::string param5(param5_raw);
+      free(param5_raw);
+      ExtraData param6;
+      p >> param6;
+      ptr->OnAsyncResultForResource(param1, param2, param3, param4, param5, param6);
+
+    }
+    break;
+
+
+
+    default:
+      _E("Unknown command(%d)", cmd);
+  }
+}
+
+
+void PkgSignal::AsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val) {
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::AsyncResult));
+  rpc_port_parcel_write_string(p, signal.c_str());
+  rpc_port_parcel_write_int32(p, targetUid);
+  rpc_port_parcel_write_string(p, reqId.c_str());
+  p << pkgs;
+  rpc_port_parcel_write_string(p, key.c_str());
+  rpc_port_parcel_write_string(p, val.c_str());
+
+
+  // Send
+  bundle* b = bundle_create();
+  std::unique_ptr<bundle, decltype(bundle_free)*> b_auto(b, bundle_free);
+  if (GetBundleFromParcel(p, b) == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void PkgSignal::AsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra) {
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::AsyncResultForResource));
+  rpc_port_parcel_write_string(p, signal.c_str());
+  rpc_port_parcel_write_int32(p, targetUid);
+  rpc_port_parcel_write_string(p, reqId.c_str());
+  rpc_port_parcel_write_string(p, pkgid.c_str());
+  rpc_port_parcel_write_string(p, status.c_str());
+  p << extra;
+
+
+  // Send
+  bundle* b = bundle_create();
+  std::unique_ptr<bundle, decltype(bundle_free)*> b_auto(b, bundle_free);
+  if (GetBundleFromParcel(p, b) == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+}  // namespace group
+}  // namespace PkgSignal
+}  // namespace rpc_port
diff --git a/installer/src/PkgSignal.h b/installer/src/PkgSignal.h
new file mode 100644 (file)
index 0000000..b7a319d
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#pragma once
+
+#include <app_event.h>
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <mutex>
+#include <list>
+#include <atomic>
+
+
+namespace rpc_port {
+namespace PkgSignal {
+
+class Bundle final {
+ public:
+  Bundle() {
+    raw_ = bundle_create();
+  }
+
+  Bundle(bundle* b) {
+    raw_ = b;
+  }
+
+  ~Bundle() {
+    if (raw_)
+      bundle_free(raw_);
+  }
+
+  Bundle(Bundle&& b) : raw_(b.raw_) {
+    b.raw_ = nullptr;
+  }
+
+  Bundle& operator = (Bundle&& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = b.raw_;
+      b.raw_ = nullptr;
+    }
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = bundle_dup(b.GetHandle());
+    }
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+class File final {
+ public:
+  File() {
+  }
+
+  File(std::string filename) {
+    filename_ = filename;
+  }
+
+  std::string GetFileName() const {
+    return filename_;
+  }
+
+ private:
+  std::string filename_;
+};
+
+
+class PkgInfo final {
+ public:
+  PkgInfo();
+  PkgInfo(std::string Pkgid, std::string Appid, std::string PkgType);
+  
+  void SetPkgid(std::string Pkgid) {
+    Pkgid_ = std::move(Pkgid);
+  }
+
+  const std::string& GetPkgid() const {
+    return Pkgid_;
+  }
+
+  void SetAppid(std::string Appid) {
+    Appid_ = std::move(Appid);
+  }
+
+  const std::string& GetAppid() const {
+    return Appid_;
+  }
+
+  void SetPkgType(std::string PkgType) {
+    PkgType_ = std::move(PkgType);
+  }
+
+  const std::string& GetPkgType() const {
+    return PkgType_;
+  }
+
+
+ private:
+  std::string Pkgid_;
+  std::string Appid_;
+  std::string PkgType_;
+
+};
+
+class PathInfo final {
+ public:
+  PathInfo();
+  PathInfo(std::string Path, int State);
+  
+  void SetPath(std::string Path) {
+    Path_ = std::move(Path);
+  }
+
+  const std::string& GetPath() const {
+    return Path_;
+  }
+
+  void SetState(int State) {
+    State_ = State;
+  }
+
+  int GetState() const {
+    return State_;
+  }
+
+
+ private:
+  std::string Path_;
+  int State_ = 0;
+
+};
+
+class ExtraData final {
+ public:
+  ExtraData();
+  ExtraData(int ErrCode, std::vector<PathInfo> Paths);
+  
+  void SetErrCode(int ErrCode) {
+    ErrCode_ = ErrCode;
+  }
+
+  int GetErrCode() const {
+    return ErrCode_;
+  }
+
+  void SetPaths(std::vector<PathInfo> Paths) {
+    Paths_ = std::move(Paths);
+  }
+
+  const std::vector<PathInfo>& GetPaths() const {
+    return Paths_;
+  }
+
+
+ private:
+  int ErrCode_ = 0;
+  std::vector<PathInfo> Paths_;
+
+};
+
+namespace group {
+
+
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class PermissionDeniedException : public Exception {};
+class InvalidIDException : public Exception {};
+
+
+class PkgSignal {
+ public:
+  PkgSignal(std::string sender_appid, bool is_system = false);
+  virtual ~PkgSignal();
+
+  
+  
+  void AsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val);
+
+  virtual void OnAsyncResult(std::string signal, int targetUid, std::string reqId, std::vector<PkgInfo> pkgs, std::string key, std::string val) {}
+
+  
+  void AsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra);
+
+  virtual void OnAsyncResultForResource(std::string signal, int targetUid, std::string reqId, std::string pkgid, std::string status, ExtraData extra) {}
+
+
+ private:
+
+  enum class MethodId : int {
+    __Result = 0,
+    __Callback = 1,
+    AsyncResult = 2,
+    AsyncResultForResource = 3,
+
+  };
+
+
+  bundle* GetBundleFromParcel(rpc_port_parcel_h p, bundle* b);
+  rpc_port_parcel_h GetParcelFromBundle(bundle* b);
+  std::string GetEventName();
+  void Subscribe();
+  void Unsubscribe();
+  static void EventCb(const char* event_name, bundle* event_data, void* user_data);
+
+ private:
+  event_handler_h event_handler_ = nullptr;
+  std::string sender_appid_;
+  std::recursive_mutex mutex_;
+  bool is_system_;
+};
+
+}  // namespace group
+}  // namespace PkgSignal
+}  // namespace rpc_port