Add policy change notification interface 40/64440/1
authorJaemin Ryu <jm77.ryu@samsung.com>
Fri, 1 Apr 2016 07:38:10 +0000 (16:38 +0900)
committerJaemin Ryu <jm77.ryu@samsung.com>
Fri, 1 Apr 2016 07:38:10 +0000 (16:38 +0900)
Change-Id: If0befb88079d691bd2b0ca66d994776c73431ca4
Signed-off-by: Jaemin Ryu <jm77.ryu@samsung.com>
common/rmi/client.cpp
common/rmi/client.h
common/rmi/service.h
libs/dpm/client-handle.cpp
libs/dpm/device-policy-client.h
libs/policy-client.cpp
libs/policy-client.h
server/server.cpp
server/server.h
tests/unit/rmi.cpp

index fe2abb1..3c4f15c 100644 (file)
@@ -35,9 +35,9 @@ void Client::connect()
     dispatcher = std::thread([this] { mainloop.run(); });
 }
 
-int Client::subscribe(const std::string& name)
+int Client::subscribe(const std::string& provider, const std::string& name)
 {
-    Message request = connection->createMessage(Message::MethodCall, "Server::subscribeNotification");
+    Message request = connection->createMessage(Message::MethodCall, provider);
     request.packParameters(name);
     connection->send(request);
 
index 1bd8d78..7318903 100644 (file)
@@ -41,11 +41,11 @@ public:
     void connect();
     void disconnect();
 
-    int subscribe(const std::string& name);
+    int subscribe(const std::string& provider, const std::string& name);
 
     template<typename... Args>
-    void subscribe(const std::string& name,
-                   const typename MethodHandler<void, Args...>::type& handler);
+    int subscribe(const std::string& provider, const std::string& name,
+                  const typename MethodHandler<void, Args...>::type& handler);
 
     template<typename Type, typename... Args>
     Type methodCall(const std::string& method, Args&&... args);
@@ -58,7 +58,7 @@ private:
 };
 
 template<typename... Args>
-void Client::subscribe(const std::string& name,
+int Client::subscribe(const std::string& provider, const std::string& name,
                        const typename MethodHandler<void, Args...>::type& handler)
 {
     auto callback = [handler, this](int fd, runtime::Mainloop::Event event) {
@@ -79,10 +79,13 @@ void Client::subscribe(const std::string& name,
         }
     };
 
-    int fd = subscribe(name);
+    int fd = subscribe(provider, name);
     if (fd > 0) {
         mainloop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, callback);
+        return 0;
     }
+
+    return -1;
 }
 
 template<typename Type, typename... Args>
index 22020d7..5bc582d 100644 (file)
@@ -168,10 +168,9 @@ template <typename... Args>
 void Service::notify(const std::string& name, Args&&... args)
 {
     Notification& slot = notificationRegistry[name];
-    slot.notify(std::forward<Args>(args)...);
+    slot.notify(name, std::forward<Args>(args)...);
 }
 
 } // namespace rmi
 
 #endif //__RMI_SERVICE_H__
-
index fecb94d..6465321 100644 (file)
@@ -49,3 +49,18 @@ DPM_API void dpm_destroy_client(dpm_client_h handle)
 
     delete &GetDevicePolicyClient(handle);
 }
+
+DPM_API int dpm_add_policy_change_listener(dpm_client_h handle, const char* name, dpm_policy_change_cb handler, void* user_data)
+{
+    assert(handle);
+
+    DevicePolicyClient &client = GetDevicePolicyClient(handle);
+    client.subscribePolicyChange(name, handler, user_data);
+
+    return 0;
+}
+
+DPM_API void dpm_remove_policy_change_listener(dpm_client_h handle, const char* name, int id)
+{
+    assert(handle);
+}
index e2e658c..c9daf23 100644 (file)
@@ -45,6 +45,11 @@ extern "C" {
  * @{
  */
 
+ /**
+  * @brief       Called when a policy has changed
+  */
+ typedef void (*dpm_policy_change_cb)(const char* name, int state, void *user_data);
+
 /**
  * @brief       The Device Policy Client handle
  * @details     The Device Policy Client Handle is an abstraction of the
@@ -113,6 +118,40 @@ DPM_API dpm_client_h dpm_create_client(void);
 DPM_API void dpm_destroy_client(dpm_client_h handle);
 
 /**
+ * @brief       Adds policy change notification listener to the Device Policy Manager
+ * @details     This API can be used to subscribe policy change notification.
+ *              The handler will be asynchronously called when policy is changed on runtime.
+ * @since_tizen 3.0
+ * @param[in]   handle Device Policy Client Handle
+ * @param[in]   name Policy name to subscribe
+ * @param[in]   callback handler to be invoked
+ * @param[in]   user_data User specified data passed to the listener
+ * @return      Listener identifier on success, otherwise negative value
+ * @retval      #DPM_ERROR_INVALID_PARAMETER Invalid policy name
+ * @retval      #DPM_ERROR_PERMISSION_DENIED The application does not have
+ *              the privilege to subscribe the policy change notification
+ * @pre         The handle must be created by dpm_create_client()
+ * @see         dpm_create_client()
+ * @see         dpm_remove_policy_change_listener()
+ */
+DPM_API int dpm_add_policy_change_listener(dpm_client_h handle, const char* name, dpm_policy_change_cb listener, void* user_data);
+
+/**
+ * @brief       Removes policy change notification listener from the Device Policy Manager
+ * @details     This API must be called if interaction with the Device
+ *              Policy Manager is no longer required.
+ * @since_tizen 3.0
+ * @param[in]   handle Device Policy Client Handle
+ * @param[in]   name Policy policy name to subscribe
+ * @param[in]   callback handler to be invoked
+ * @param[in]   user_data User specified data passed to the listener
+ * @return      None
+ * @pre         The handle must be created by dpm_create_client()
+ * @see         dpm_create_client()
+ * @see         dpm_add_policy_change_listener()
+ */
+DPM_API void dpm_remove_policy_change_listener(dpm_client_h handle, const char* name, int id);
+/**
  * @}
  */
 
index 670f955..70192c6 100644 (file)
@@ -18,6 +18,7 @@
 
 namespace {
 
+const std::string POLICY_NOTIFICATION_PROVIDER = "Server::subscribeNotification";
 const std::string POLICY_MANAGER_ADDRESS = "/tmp/.device-policy-manager";
 
 } // namespace
@@ -52,3 +53,33 @@ void DevicePolicyClient::disconnect() noexcept
 {
     client.reset();
 }
+
+int DevicePolicyClient::subscribePolicyChange(const std::string& name,
+                                              const PolicyChangeListener& listener,
+                                              void* data)
+{
+    auto listenerDispatcher = [listener, data](const std::string& policy, int value) {
+        listener(policy.c_str(), value, data);
+    };
+
+    return client->subscribe<std::string, int>(POLICY_NOTIFICATION_PROVIDER,
+                                               name, listenerDispatcher);
+}
+
+void DevicePolicyClient::unsubscribePolicyChange(const std::string& name, int subscriberId)
+{
+}
+
+int DevicePolicyClient::connectSignal(const std::string& name,
+                                      const PolicySignalHandler& handler, void* data)
+{
+    auto signalDispatcher = [handler, data](const std::string& signal) {
+        handler(signal.c_str(), data);
+    };
+
+    return client->subscribe<std::string>(POLICY_NOTIFICATION_PROVIDER, name, signalDispatcher);
+}
+
+void DevicePolicyClient::disconnectSignal(const std::string& name, int signalId)
+{
+}
index ec121af..a152d40 100644 (file)
 
 #include <string>
 #include <memory>
+#include <functional>
 
 #include "rmi/client.h"
 
+typedef std::function<void(const char*, int, void*)> PolicyChangeListener;
+typedef std::function<void(const char*, void*)> PolicySignalHandler;
+
 class DevicePolicyClient {
 public:
     typedef std::unique_ptr<rmi::Client> PolicyControlContext;
@@ -33,6 +37,12 @@ public:
     int connect(const std::string& address) noexcept;
     void disconnect() noexcept;
 
+    int subscribePolicyChange(const std::string& name, const PolicyChangeListener& listener, void* data);
+    void unsubscribePolicyChange(const std::string& name, int subscriberId);
+
+    int connectSignal(const std::string& name, const PolicySignalHandler& handler, void* data);
+    void disconnectSignal(const std::string& name, int signalId);
+
     template<typename Policy, typename... Args>
     Policy createPolicyInterface(Args&&... args) noexcept
     {
index 45c98c8..76ba85d 100644 (file)
@@ -25,6 +25,8 @@ const std::string POLICY_MANAGER_ADDRESS = "/tmp/.device-policy-manager";
 Server::Server()
 {
     service.reset(new rmi::Service(POLICY_MANAGER_ADDRESS));
+
+    service->registerParametricMethod(this, (FileDescriptor)(Server::subscribeNotification)(std::string));
 }
 
 Server::~Server()
@@ -42,6 +44,11 @@ void Server::terminate()
     service->stop();
 }
 
+FileDescriptor Server::subscribeNotification(const std::string& name)
+{
+    return FileDescriptor(service->subscribeNotification(name), true);
+}
+
 Server& Server::instance()
 {
     static Server _instance_;
index b652629..33ad207 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "client-manager.h"
 
+#include "file-descriptor.h"
 #include "rmi/service.h"
 
 class Server {
@@ -37,6 +38,8 @@ public:
         return *service;
     }
 
+    FileDescriptor subscribeNotification(const std::string& name);
+
     static Server& instance();
 
 private:
index c27390f..ace39c0 100644 (file)
@@ -25,6 +25,7 @@
 #include <utility>
 
 #include "data-type.h"
+#include "file-descriptor.h"
 #include "rmi/service.h"
 #include "rmi/client.h"
 #include "audit/logger.h"
@@ -43,6 +44,15 @@ public:
         service->registerMethod(this, (String)(TestServer::method2)(String, String));
         service->registerMethod(this, (String)(TestServer::method3)(String, String, String));
         service->registerMethod(this, (String)(TestServer::method4)(String, String, String, String));
+
+        service->registerMethod(this, (FileDescriptor)(TestServer::signalProvider)(std::string));
+        service->registerMethod(this, (FileDescriptor)(TestServer::policyNotificationProvider)(std::string));
+
+        service->registerNonparametricMethod(this, (int)(TestServer::sendSignal)());
+        service->registerNonparametricMethod(this, (int)(TestServer::sendPolicyChangeNotification)());
+
+        service->createNotification("TestPolicyChanged");
+        service->createNotification("TestSignal");
     }
 
     void run()
@@ -74,6 +84,28 @@ public:
         return String("Method4 result");
     }
 
+    int sendPolicyChangeNotification()
+    {
+        service->notify("TestPolicyChanged", 1234);
+        return 0;
+    }
+
+    int sendSignal()
+    {
+        service->notify("TestSignal");
+        return 0;
+    }
+
+    FileDescriptor signalProvider(const std::string& name)
+    {
+        return service->subscribeNotification(name);
+    }
+
+    FileDescriptor policyNotificationProvider(const std::string& name)
+    {
+        return service->subscribeNotification(name);
+    }
+
 private:
     std::unique_ptr<rmi::Service> service;
 };
@@ -86,8 +118,21 @@ public:
 
     void connect()
     {
+        auto policyChangedListener = [](const std::string& name, int value) {
+            std::cout << "Policy Changed: " << name << " : " << value << std::endl;
+        };
+
+        auto policySignalListener = [](const std::string& name) {
+            std::cout << "Signal Triggered" << std::endl;
+        };
+
         client.reset(new rmi::Client(IPC_TEST_ADDRESS));
         client->connect();
+
+        client->subscribe<std::string, int>("TestServer::policyNotificationProvider",
+                                            "TestPolicyChanged", policyChangedListener);
+        client->subscribe<std::string>("TestServer::signalProvider",
+                                       "TestSignal", policySignalListener);
     }
 
     void disconnect()
@@ -115,12 +160,32 @@ public:
         return client->methodCall<String>("TestServer::method4", arg1, arg2, arg3, arg4);
     }
 
+    void requestSignal()
+    {
+        signalTriggered = false;
+        client->methodCall<int>("TestServer::sendSignal");
+        while (!signalTriggered) {
+            ::sleep(1);
+        }
+    }
+
+    void requestPolicyChangeNotification()
+    {
+        policyChangeNotificationTriggered = false;
+        client->methodCall<int>("TestServer::sendPolicyChangeNotification");
+        while (!policyChangeNotificationTriggered) {
+            sleep(1);
+        }
+    }
+
     String invalidMethod(String& arg)
     {
         return client->methodCall<String>("TestServer::invalidMethod", arg);
     }
 
 private:
+    volatile bool signalTriggered;
+    volatile bool policyChangeNotificationTriggered;
     std::unique_ptr<rmi::Client> client;
 };
 
@@ -196,6 +261,7 @@ public:
     {
         addTest(IpcTestSuite::connectionTest);
         addTest(IpcTestSuite::remoteMethodCallTest);
+        addTest(IpcTestSuite::notificationTest);
     }
 
     void setup()
@@ -232,6 +298,21 @@ public:
         }
     }
 
+    void notificationTest()
+    {
+        try {
+            TestClient client;
+            client.connect();
+
+            client.requestSignal();
+            client.requestPolicyChangeNotification();
+
+            client.disconnect();
+        } catch (runtime::Exception& e) {
+            ERROR(e.what());
+        }
+    }
+
     void remoteMethodCallTest()
     {
         try {
@@ -248,6 +329,11 @@ public:
             String result3 = client.method3(param1, param2, param3);
             String result4 = client.method4(param1, param2, param3, param4);
 
+            client.requestSignal();
+            client.requestPolicyChangeNotification();
+
+            sleep(5);
+
             client.disconnect();
         } catch (runtime::Exception& e) {
             ERROR(e.what());