[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / dbus / dbus-tizen.cpp
1 /*
2  * Copyright 2019  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://www.apache.org/licenses/LICENSE-2.0
9
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/accessibility/bridge/accessibility-common.h>
19 #include <dali/internal/accessibility/bridge/dbus/dbus.h>
20
21 // EXTERNAL INCLUDES
22 #include <iostream>
23 #include <mutex>
24 #include <sstream>
25
26 #include <Ecore_Input.h>
27 #include <Eldbus.h>
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/dali-adaptor-common.h>
31
32 #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
33
34 #undef EINA_FALSE
35 #undef EINA_TRUE
36 #define EINA_TRUE static_cast<Eina_Bool>(1)
37 #define EINA_FALSE static_cast<Eina_Bool>(0)
38
39 //#define DBUS_DEBUG(...) do { DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); } while (0)
40
41 std::atomic<unsigned int>                       DBus::detail::CallId::LastId{0};
42 static std::function<void(const char*, size_t)> debugPrinter;
43 static std::mutex                               debugLock;
44
45 thread_local std::string                DBus::DBusServer::currentObjectPath;
46 thread_local DBusWrapper::ConnectionPtr DBus::DBusServer::currentConnection;
47
48 void DBus::setDebugPrinter(std::function<void(const char*, size_t)> printer)
49 {
50   std::lock_guard<std::mutex> lock(debugLock);
51   debugPrinter = std::move(printer);
52 }
53
54 void DBus::debugPrint(const char* file, size_t line, const char* format, ...)
55 {
56   std::function<void(const char*, size_t)> debugPrintFunc;
57   {
58     std::lock_guard<std::mutex> lock(debugLock);
59     if(!debugPrinter)
60       return;
61     debugPrintFunc = debugPrinter;
62   }
63   std::vector<char> buf(4096);
64   int               offset;
65   while(true)
66   {
67     offset = snprintf(buf.data(), buf.size(), "%s:%u: ", file, static_cast<unsigned int>(line));
68     if(offset < 0)
69       return;
70     if(static_cast<size_t>(offset) < buf.size())
71       break;
72     buf.resize(offset + 1);
73   }
74
75   while(true)
76   {
77     va_list args;
78     va_start(args, format);
79     int z = vsnprintf(buf.data() + offset, buf.size() - offset, format, args);
80     va_end(args);
81     if(z < 0)
82       return;
83     bool done = static_cast<size_t>(z) + static_cast<size_t>(offset) < buf.size();
84     buf.resize(static_cast<size_t>(z) + static_cast<size_t>(offset));
85     if(done)
86       break;
87   }
88   debugPrintFunc(buf.data(), buf.size());
89 }
90
91 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByName(const std::string& name)
92 {
93   return DBUS_W->eldbus_address_connection_get_impl(name);
94 }
95
96 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByType(ConnectionType connectionType)
97 {
98   return DBUS_W->eldbus_connection_get_impl(connectionType);
99 }
100
101 DBus::DBusClient::DBusClient(std::string busName, std::string pathName, std::string interfaceName, ConnectionType tp)
102 : DBusClient(std::move(busName), std::move(pathName), std::move(interfaceName), getDBusConnectionByType(tp))
103 {
104 }
105
106 DBus::DBusClient::DBusClient(std::string busName, std::string pathName, std::string interfaceName, const DBusWrapper::ConnectionPtr& conn)
107 {
108   if(!conn)
109     connectionState->connection = getDBusConnectionByType(ConnectionType::SESSION);
110   else
111     connectionState->connection = conn;
112
113   if(!connectionState->connection)
114   {
115     DALI_LOG_ERROR("DBusClient connection is not ready\n");
116     return;
117   }
118
119   connectionState->object = DBUS_W->eldbus_object_get_impl(connectionState->connection, busName.c_str(), pathName.c_str());
120   if(connectionState->object)
121   {
122     connectionState->proxy = DBUS_W->eldbus_proxy_get_impl(connectionState->object, interfaceName);
123     if(interfaceName != DBUS_INTERFACE_PROPERTIES)
124     {
125       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_get_impl(connectionState->object, DBUS_INTERFACE_PROPERTIES);
126     }
127     else
128     {
129       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_copy_impl(connectionState->proxy);
130     }
131   }
132   connectionInfo                = std::make_shared<ConnectionInfo>();
133   connectionInfo->busName       = std::move(busName);
134   connectionInfo->pathName      = std::move(pathName);
135   connectionInfo->interfaceName = std::move(interfaceName);
136 }
137
138 DBus::DBusServer::DBusServer(ConnectionType tp)
139 : DBus::DBusServer(DBus::getDBusConnectionByType(tp))
140 {
141 }
142
143 DBus::DBusServer::DBusServer(const DBusWrapper::ConnectionPtr& conn)
144 {
145   if(!conn)
146     connection = getDBusConnectionByType(ConnectionType::SESSION);
147   else
148     connection = conn;
149 }
150
151 DBus::DBusInterfaceDescription::DBusInterfaceDescription(std::string interfaceName)
152 : interfaceName(std::move(interfaceName))
153 {
154 }
155
156 void DBus::DBusServer::addInterface(const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback)
157 {
158   DBUS_W->add_interface_impl(fallback, pathName, connection, destructorObject->destructors, dscr.interfaceName, dscr.methods, dscr.properties, dscr.signals);
159 }
160
161 std::string DBus::DBusServer::getBusName() const
162 {
163   return getConnectionName(connection);
164 }
165
166 std::string DBus::getConnectionName(const DBusWrapper::ConnectionPtr& c)
167 {
168   return DBUS_W->eldbus_connection_unique_name_get_impl(c);
169 }
170
171 void DBus::requestBusName(const DBusWrapper::ConnectionPtr& conn, const std::string& bus)
172 {
173   DBUS_W->eldbus_name_request_impl(conn, bus);
174 }
175
176 void DBus::releaseBusName(const DBusWrapper::ConnectionPtr& conn, const std::string& bus)
177 {
178   DBUS_W->eldbus_name_release_impl(conn, bus);
179 }
180
181 bool DBus::DBusClient::getFromEinaValue(const _Eina_Value* v, void* dst)
182 {
183   return eina_value_get(const_cast<Eina_Value*>(v), dst);
184 }
185
186 static std::unique_ptr<DBusWrapper> InstalledWrapper;
187
188 struct DefaultDBusWrapper : public DBusWrapper
189 {
190   constexpr static int ELDBUS_CALL_TIMEOUT = 1000;
191
192   DefaultDBusWrapper()
193   {
194   }
195
196   ~DefaultDBusWrapper()
197   {
198   }
199
200 #define DEFINE_GS(name, eldbus_name, unref_call)                                                   \
201   static eldbus_name* get(const std::shared_ptr<name>& a)                                          \
202   {                                                                                                \
203     return static_cast<name##Impl*>(a.get())->Value;                                               \
204   }                                                                                                \
205   static eldbus_name* release(const std::shared_ptr<name>& a)                                      \
206   {                                                                                                \
207     auto z                                   = static_cast<name##Impl*>(a.get())->Value;           \
208     static_cast<name##Impl*>(a.get())->Value = nullptr;                                            \
209     return z;                                                                                      \
210   }                                                                                                \
211   template<typename... ARGS>                                                                       \
212   static std::shared_ptr<name> create(const eldbus_name* v, ARGS&&... args)                        \
213   {                                                                                                \
214     return std::make_shared<name##Impl>(const_cast<eldbus_name*>(v), std::forward<ARGS>(args)...); \
215   }
216
217 #define DEFINE_TYPE(name, eldbus_name, unref_call)                                     \
218   struct name##Impl : public name                                                      \
219   {                                                                                    \
220     eldbus_name* Value       = nullptr;                                                \
221     bool         EraseOnExit = false;                                                  \
222     name##Impl(eldbus_name* Value, bool EraseOnExit = false): Value(Value),            \
223                                                               EraseOnExit(EraseOnExit) \
224     {                                                                                  \
225     }                                                                                  \
226     ~name##Impl()                                                                      \
227     {                                                                                  \
228       if(EraseOnExit && Value)                                                         \
229       {                                                                                \
230         unref_call;                                                                    \
231       }                                                                                \
232     }                                                                                  \
233   };                                                                                   \
234   DEFINE_GS(name, eldbus_name, unref_call)
235
236   struct ConnectionImpl : public Connection
237   {
238     Eldbus_Connection* Value       = nullptr;
239     bool               EraseOnExit = false;
240     ConnectionImpl(Eldbus_Connection* Value, bool EraseOnExit = false)
241     : Value(Value),
242       EraseOnExit(EraseOnExit)
243     {
244       ecore_event_init();
245       eldbus_init();
246     }
247
248     ~ConnectionImpl()
249     {
250       if(EraseOnExit && Value)
251       {
252         eldbus_connection_unref(Value);
253       }
254       eldbus_shutdown();
255       ecore_event_shutdown();
256     }
257   };
258
259   struct MessageIterImpl : public MessageIter
260   {
261     Eldbus_Message_Iter *Value = nullptr, *Parent = nullptr;
262     bool                 EraseOnExit = false;
263     MessageIterImpl(Eldbus_Message_Iter* Value, Eldbus_Message_Iter* Parent, bool EraseOnExit = false)
264     : Value(Value),
265       Parent(Parent),
266       EraseOnExit(EraseOnExit)
267     {
268     }
269
270     ~MessageIterImpl()
271     {
272       if(EraseOnExit && Value && Parent)
273       {
274         eldbus_message_iter_container_close(Parent, Value);
275       }
276     }
277   };
278
279   DEFINE_GS(Connection, Eldbus_Connection, )
280   DEFINE_GS(MessageIter, Eldbus_Message_Iter, )
281   DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref(Value))
282   DEFINE_TYPE(Proxy, Eldbus_Proxy, )
283   DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref(Value))
284   DEFINE_TYPE(Pending, Eldbus_Pending, )
285   DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
286 #undef DEFINE_TYPE
287
288   std::shared_ptr<Connection> eldbus_address_connection_get_impl(const std::string& addr) override
289   {
290     eldbus_init();
291     auto p = eldbus_address_connection_get(addr.c_str());
292     auto w = create(p, true);
293     eldbus_shutdown();
294     return w;
295   }
296
297 #define eldbus_message_iter_arguments_append_impl_basic(type, sig)                            \
298   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, type src) override \
299   {                                                                                           \
300     eldbus_message_iter_arguments_append(get(it), #sig, src);                                 \
301   }                                                                                           \
302   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, type& dst) override    \
303   {                                                                                           \
304     return eldbus_message_iter_get_and_next(get(it), (#sig)[0], &dst);                        \
305   }
306
307   // clang-format off
308   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
309   eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
310   eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
311   eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
312   eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
313   eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
314   eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
315   eldbus_message_iter_arguments_append_impl_basic(double, d)
316   // clang-format on
317
318 #undef eldbus_message_iter_arguments_append_impl_basic
319
320                   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, bool src) override
321   {
322     eldbus_message_iter_arguments_append(get(it), "b", src ? 1 : 0);
323   }
324
325   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, bool& dst) override
326   {
327     unsigned char q;
328     auto          z = eldbus_message_iter_get_and_next(get(it), 'b', &q);
329     dst             = q != 0;
330     return z;
331   }
332
333   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, const std::string& src) override
334   {
335     eldbus_message_iter_arguments_append(get(it), "s", src.c_str());
336   }
337
338   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, std::string& dst) override
339   {
340     auto        iter = get(it);
341     const char* q;
342     if(!eldbus_message_iter_get_and_next(iter, 's', &q))
343     {
344       if(!eldbus_message_iter_get_and_next(iter, 'o', &q))
345       {
346         return false;
347       }
348     }
349     dst = q;
350     return true;
351   }
352
353   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, const ObjectPath& src) override
354   {
355     eldbus_message_iter_arguments_append(get(it), "o", src.value.c_str());
356   }
357
358   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, ObjectPath& dst) override
359   {
360     const char* q;
361     if(!eldbus_message_iter_get_and_next(get(it), 'o', &q))
362     {
363       return false;
364     }
365     dst.value = q;
366     return true;
367   }
368
369   MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr& it, int type, const std::string& sig) override
370   {
371     auto z = eldbus_message_iter_container_new(get(it), type, !sig.empty() ? sig.c_str() : NULL);
372     return create(z, get(it), true);
373   }
374
375   MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr& it, int type) override
376   {
377     Eldbus_Message_Iter* entry;
378     if(!eldbus_message_iter_get_and_next(get(it), type, &entry))
379     {
380       return {};
381     }
382     return create(entry, get(it), false);
383   }
384
385   MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr& msg, bool) override
386   {
387     return create(eldbus_message_iter_get(get(msg)), nullptr, false);
388   }
389
390   MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr& proxy, const std::string& funcName)
391   {
392     return create(eldbus_proxy_method_call_new(get(proxy), funcName.c_str()));
393   }
394
395   MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr& proxy, const MessagePtr& msg) override
396   {
397     return create(eldbus_proxy_send_and_block(get(proxy), release(msg), ELDBUS_CALL_TIMEOUT));
398   }
399
400   bool eldbus_message_error_get_impl(const MessagePtr& msg, std::string& name, std::string& text) override
401   {
402     const char *errname, *errmsg;
403     if(eldbus_message_error_get(get(msg), &errname, &errmsg))
404     {
405       name = errname;
406       text = errmsg;
407       return true;
408     }
409     return false;
410   }
411
412   std::string eldbus_message_signature_get_impl(const MessagePtr& msg) override
413   {
414     return eldbus_message_signature_get(get(msg));
415   }
416
417   static void callAsyncCb(void* data, const Eldbus_Message* msg, Eldbus_Pending* pending)
418   {
419     auto d = static_cast<SendCallback*>(data);
420     (*d)(create(msg, false));
421   }
422
423   static void pendingFreeCb(void* data, const void*)
424   {
425     auto d = static_cast<SendCallback*>(data);
426     delete d;
427   }
428
429   static void listenerCallbackFree(void* data, const void*)
430   {
431     auto d = static_cast<std::function<void(const Eldbus_Message* msg)>*>(data);
432     delete d;
433   }
434
435   PendingPtr eldbus_proxy_send_impl(const ProxyPtr& proxy, const MessagePtr& msg, const SendCallback& callback) override
436   {
437     auto cb      = new SendCallback{callback};
438     auto pending = eldbus_proxy_send(get(proxy), release(msg), callAsyncCb, cb, ELDBUS_CALL_TIMEOUT);
439     if(pending)
440     {
441       eldbus_pending_free_cb_add(pending, pendingFreeCb, cb);
442     }
443     else
444     {
445       delete cb;
446     }
447     return create(pending, false);
448   }
449
450   std::string eldbus_proxy_interface_get_impl(const ProxyPtr& proxy) override
451   {
452     return eldbus_proxy_interface_get(get(proxy));
453   }
454
455   static void listenerCallback(void* data, const Eldbus_Message* msg)
456   {
457     auto p = static_cast<std::function<void(const Eldbus_Message* msg)>*>(data);
458     (*p)(msg);
459   }
460
461   void eldbus_proxy_signal_handler_add_impl(const ProxyPtr& proxy, const std::string& member, const std::function<void(const MessagePtr&)>& cb) override
462   {
463     auto tmp = new std::function<void(const Eldbus_Message* msg)>{
464       [cb](const Eldbus_Message* msg) {
465         cb(create(msg, false));
466       }};
467     auto handler = eldbus_proxy_signal_handler_add(get(proxy), member.c_str(), listenerCallback, tmp);
468     if(handler)
469     {
470       eldbus_proxy_free_cb_add(get(proxy), listenerCallbackFree, tmp);
471     }
472     else
473     {
474       delete tmp;
475     }
476   }
477
478   std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr& iter) override
479   {
480     return eldbus_message_iter_signature_get(get(iter));
481   }
482
483   MessagePtr eldbus_message_method_return_new_impl(const MessagePtr& msg) override
484   {
485     return create(eldbus_message_method_return_new(get(msg)));
486   }
487
488   MessagePtr eldbus_message_error_new_impl(const MessagePtr& msg, const std::string& err, const std::string& txt) override
489   {
490     return create(eldbus_message_error_new(get(msg), err.c_str(), txt.c_str()));
491   }
492
493   PendingPtr eldbus_connection_send_impl(const ConnectionPtr& conn, const MessagePtr& msg) override
494   {
495     return create(eldbus_connection_send(get(conn), get(msg), NULL, NULL, -1));
496   }
497
498   MessagePtr eldbus_message_signal_new_impl(const std::string& path, const std::string& iface, const std::string& name) override
499   {
500     return create(eldbus_message_signal_new(path.c_str(), iface.c_str(), name.c_str()));
501   }
502
503   MessagePtr eldbus_message_ref_impl(const MessagePtr& msg) override
504   {
505     return create(eldbus_message_ref(get(msg)), true);
506   }
507
508   ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override
509   {
510     Eldbus_Connection_Type eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
511
512     switch(type)
513     {
514       case ConnectionType::SYSTEM:
515       {
516         eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
517         break;
518       }
519       case ConnectionType::SESSION:
520       {
521         eldbusType = ELDBUS_CONNECTION_TYPE_SESSION;
522         break;
523       }
524     }
525
526     auto p = eldbus_connection_get(eldbusType);
527     if(!p)
528     {
529       DALI_LOG_ERROR("cannot get dbus connection\n");
530       return NULL;
531     }
532     auto w = create(p, true);
533     return w;
534   }
535
536   std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr& conn) override
537   {
538     return eldbus_connection_unique_name_get(get(conn));
539   }
540
541   ObjectPtr eldbus_object_get_impl(const ConnectionPtr& conn, const std::string& bus, const std::string& path) override
542   {
543     return create(eldbus_object_get(get(conn), bus.c_str(), path.c_str()), true);
544   }
545
546   ProxyPtr eldbus_proxy_get_impl(const ObjectPtr& obj, const std::string& interface) override
547   {
548     return create(eldbus_proxy_get(get(obj), interface.c_str()), false);
549   }
550
551   ProxyPtr eldbus_proxy_copy_impl(const ProxyPtr& ptr) override
552   {
553     return create(get(ptr), false);
554   }
555
556   void eldbus_name_request_impl(const ConnectionPtr& conn, const std::string& bus) override
557   {
558     eldbus_name_request(get(conn), bus.c_str(), ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE, nullptr, nullptr);
559   }
560
561   void eldbus_name_release_impl(const ConnectionPtr& conn, const std::string& bus) override
562   {
563     eldbus_name_release(get(conn), bus.c_str(), nullptr, nullptr);
564   }
565
566   struct Implementation
567   {
568     Eldbus_Service_Interface_Desc             dsc;
569     std::vector<std::vector<Eldbus_Arg_Info>> argsInfos;
570     std::vector<Eldbus_Method>                methods;
571     std::vector<Eldbus_Signal>                signals;
572     std::vector<Eldbus_Property>              properties;
573
574     std::unordered_map<std::string, DBusWrapper::MethodInfo>   methodsMap;
575     std::unordered_map<std::string, DBusWrapper::PropertyInfo> propertiesMap;
576     std::unordered_map<unsigned int, DBusWrapper::SignalInfo>  signalsMap;
577
578     DBusWrapper::ConnectionWeakPtr connection;
579   };
580
581   struct GlobalEntries
582   {
583     static GlobalEntries& Get()
584     {
585       static GlobalEntries instance;
586       return instance;
587     }
588
589     Implementation* Find(const Eldbus_Service_Interface* iface)
590     {
591       Implementation*             impl = nullptr;
592       std::lock_guard<std::mutex> lock(globalEntriesMutex);
593       auto                        it = globalEntries.find(iface);
594       if(it != globalEntries.end())
595       {
596         impl = it->second.get();
597       }
598       return impl;
599     }
600
601     void Add(const Eldbus_Service_Interface* iface, std::unique_ptr<Implementation> impl)
602     {
603       std::lock_guard<std::mutex> lock(globalEntriesMutex);
604       globalEntries[iface] = std::move(impl);
605     }
606
607     void Erase(const Eldbus_Service_Interface* iface)
608     {
609       std::lock_guard<std::mutex> lock(globalEntriesMutex);
610       globalEntries.erase(iface);
611     }
612
613   private:
614     std::unordered_map<const Eldbus_Service_Interface*, std::unique_ptr<Implementation>> globalEntries;
615     std::mutex                                                                           globalEntriesMutex;
616   };
617
618 #undef EINA_FALSE
619 #undef EINA_TRUE
620 #define EINA_FALSE static_cast<Eina_Bool>(0)
621 #define EINA_TRUE static_cast<Eina_Bool>(1)
622
623   static Eina_Bool property_get_callback(const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter, const Eldbus_Message* message, Eldbus_Message** error)
624   {
625     Implementation* impl = GlobalEntries::Get().Find(iface);
626     if(!impl)
627     {
628       return EINA_FALSE;
629     }
630
631     auto it = impl->propertiesMap.find(propertyName);
632     if(it == impl->propertiesMap.end() || !it->second.getCallback)
633     {
634       return EINA_FALSE;
635     }
636
637     auto connection = impl->connection.lock();
638     if(!connection)
639     {
640       return EINA_FALSE;
641     }
642
643     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
644     auto                                  reply = it->second.getCallback(create(message, false), create(iter, nullptr, false));
645     if(!reply.empty())
646     {
647       if(error)
648       {
649         *error = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", reply.c_str());
650       }
651       return EINA_FALSE;
652     }
653
654     return EINA_TRUE;
655   }
656
657   static Eldbus_Message* property_set_callback(const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter, const Eldbus_Message* message)
658   {
659     Implementation* impl = GlobalEntries::Get().Find(iface);
660     if(!impl)
661     {
662       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown interface");
663       return ret;
664     }
665     auto it = impl->propertiesMap.find(propertyName);
666     if(it == impl->propertiesMap.end() || !it->second.setCallback)
667     {
668       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown setter");
669       return ret;
670     }
671     auto connection = impl->connection.lock();
672     if(!connection)
673     {
674       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Connection lost");
675       return ret;
676     }
677
678     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
679     auto                                  reply = it->second.setCallback(create(message, false), create(iter, nullptr, false));
680
681     Eldbus_Message* ret = nullptr;
682     if(!reply.empty())
683     {
684       ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", reply.c_str());
685     }
686     else
687     {
688       ret = eldbus_message_method_return_new(message);
689     }
690     return ret;
691   }
692
693   static Eldbus_Message* method_callback(const Eldbus_Service_Interface* iface, const Eldbus_Message* message)
694   {
695     Implementation* impl = GlobalEntries::Get().Find(iface);
696     if(!impl)
697     {
698       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown interface");
699       return ret;
700     }
701     std::string memberName = eldbus_message_member_get(message);
702     auto        it         = impl->methodsMap.find(memberName);
703     if(it == impl->methodsMap.end())
704     {
705       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Unknown method");
706       return ret;
707     }
708     auto connection = impl->connection.lock();
709     if(!connection)
710     {
711       auto ret = eldbus_message_error_new(message, "org.freedesktop.DBus.Error.Failed", "Connection lost");
712       return ret;
713     }
714     DBus::DBusServer::CurrentObjectSetter currentObjectSetter(connection, eldbus_message_path_get(message));
715     auto                                  reply = it->second.callback(create(message));
716     return release(reply);
717   }
718
719   void add_interface_impl(bool                                fallback,
720                           const std::string&                  pathName,
721                           const ConnectionPtr&                connection,
722                           std::vector<std::function<void()>>& destructors,
723                           const std::string&                  interfaceName,
724                           std::vector<MethodInfo>&            dscrMethods,
725                           std::vector<PropertyInfo>&          dscrProperties,
726                           std::vector<SignalInfo>&            dscrSignals) override
727   {
728     std::vector<Eldbus_Method>                                                    methods;
729     std::vector<Eldbus_Signal>                                                    signals;
730     std::vector<Eldbus_Property>                                                  properties;
731     std::vector<std::vector<Eldbus_Arg_Info>>                                     argsInfos;
732     std::unordered_map<std::string, DBus::DBusInterfaceDescription::MethodInfo>   methodsMap;
733     std::unordered_map<std::string, DBus::DBusInterfaceDescription::PropertyInfo> propertiesMap;
734     std::unordered_map<unsigned int, DBus::DBusInterfaceDescription::SignalInfo>  signalsMap;
735
736     DBUS_DEBUG("interface %s path %s on bus %s", interfaceName.c_str(), pathName.c_str(), DBus::getConnectionName(connection).c_str());
737     auto makeArgInfo = [&](const std::vector<std::pair<std::string, std::string>>& input) {
738       argsInfos.push_back({});
739       auto& dst = argsInfos.back();
740       for(auto& s : input)
741       {
742         auto a = Strings.add(s.first);
743         auto b = Strings.add(s.second);
744         dst.push_back({a, b});
745       }
746       dst.push_back({nullptr, nullptr});
747       return dst.data();
748     };
749     for(auto& ee : dscrMethods)
750     {
751       auto key = ee.memberName;
752       DBUS_DEBUG("adding method %s", ee.memberName.c_str());
753       for(auto& r : ee.in)
754       {
755         DBUS_DEBUG("in %s '%s'", r.first.c_str(), r.second.c_str());
756       }
757       for(auto& r : ee.out)
758       {
759         DBUS_DEBUG("out %s '%s'", r.first.c_str(), r.second.c_str());
760       }
761       auto& e = (methodsMap[key] = std::move(ee));
762       methods.push_back({});
763       auto& m  = methods.back();
764       m.member = e.memberName.c_str();
765       m.in     = makeArgInfo(e.in);
766       m.out    = makeArgInfo(e.out);
767       m.cb     = method_callback;
768       m.flags  = 0;
769     }
770     for(auto& ee : dscrProperties)
771     {
772       auto key = ee.memberName;
773       DBUS_DEBUG("adding property %s", ee.memberName.c_str());
774       auto& e = (propertiesMap[key] = std::move(ee));
775       properties.push_back({});
776       auto& m    = properties.back();
777       m.name     = e.memberName.c_str();
778       m.type     = e.typeSignature.c_str();
779       m.get_func = e.getCallback ? property_get_callback : nullptr;
780       m.set_func = e.setCallback ? property_set_callback : nullptr;
781       m.flags    = 0;
782     }
783     dscrMethods.clear();
784     dscrProperties.clear();
785     dscrSignals.clear();
786
787     methods.push_back({nullptr, nullptr, nullptr, nullptr, 0});
788     signals.push_back({nullptr, nullptr, 0});
789     properties.push_back({nullptr, nullptr, nullptr, nullptr, 0});
790
791     auto impl = std::unique_ptr<Implementation>(new Implementation{
792       {interfaceName.c_str(),
793        methods.data(),
794        signals.data(),
795        properties.data(),
796        nullptr,
797        nullptr},
798       std::move(argsInfos),
799       std::move(methods),
800       std::move(signals),
801       std::move(properties),
802       std::move(methodsMap),
803       std::move(propertiesMap),
804       std::move(signalsMap),
805       connection});
806
807     auto v = fallback ? eldbus_service_interface_fallback_register(get(connection), pathName.c_str(), &impl->dsc) : eldbus_service_interface_register(get(connection), pathName.c_str(), &impl->dsc);
808     DALI_ASSERT_ALWAYS(v && "Eldbus register failed!");
809     GlobalEntries::Get().Add(v, std::move(impl));
810     DBUS_DEBUG("registering interface %p (%d)", v, fallback ? 1 : 0);
811     destructors.push_back([=]() {
812       DBUS_DEBUG("unregistering interface %p", v);
813       GlobalEntries::Get().Erase(v);
814       eldbus_service_interface_unregister(v);
815     });
816   }
817
818   static void listenerEventChangedCallback(void* data, Eldbus_Proxy* proxy EINA_UNUSED, void* event)
819   {
820     auto p = static_cast<std::function<void(Eldbus_Proxy_Event_Property_Changed*)>*>(data);
821     (*p)(static_cast<Eldbus_Proxy_Event_Property_Changed*>(event));
822   }
823
824   static void ProxyEventCallbackDelCb(void* data, const void* obj)
825   {
826     auto d = static_cast<std::function<void(Eldbus_Proxy_Event_Property_Changed*)>*>(data);
827     delete d;
828   }
829
830   void add_property_changed_event_listener_impl(const ProxyPtr& proxy, const std::string& interface, const std::string& name, std::function<void(const Eina_Value*)> cb) override
831   {
832     auto callbackLambdaPtr = new std::function<void(Eldbus_Proxy_Event_Property_Changed * epc)>{
833       [cb, name, interface](Eldbus_Proxy_Event_Property_Changed* ev) {
834         const char* ifc = eldbus_proxy_interface_get(ev->proxy);
835         if(ev->name && ev->name == name && ifc && interface == ifc)
836         {
837           cb(ev->value);
838         }
839       }};
840     auto p = get(proxy);
841     eldbus_proxy_event_callback_add(p, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, listenerEventChangedCallback, callbackLambdaPtr);
842     eldbus_proxy_free_cb_add(p, ProxyEventCallbackDelCb, callbackLambdaPtr);
843   }
844 };
845
846 DBusWrapper* DBusWrapper::Installed()
847 {
848   if(!InstalledWrapper)
849   {
850     InstalledWrapper.reset(new DefaultDBusWrapper);
851   }
852   return InstalledWrapper.get();
853 }
854
855 void DBusWrapper::Install(std::unique_ptr<DBusWrapper> w)
856 {
857   InstalledWrapper = std::move(w);
858 }