+ mAccessibilityStatusClient.property<bool>("ScreenReaderEnabled").asyncGet([this](DBus::ValueOrError<bool> msg) {
+ if(!msg)
+ {
+ DALI_LOG_ERROR("Get ScreenReaderEnabled property error: %s\n", msg.getError().message.c_str());
+ if(msg.getError().errorType == DBus::ErrorType::INVALID_REPLY)
+ {
+ if(!mReadScreenReaderEnabledTimer)
+ {
+ mReadScreenReaderEnabledTimer = Dali::Timer::New(RETRY_INTERVAL);
+ mReadScreenReaderEnabledTimer.TickSignal().Connect(this, &BridgeImpl::ReadScreenReaderEnabledTimerCallback);
+ }
+ mReadScreenReaderEnabledTimer.Start();
+ }
+ return;
+ }
+
+ if(mReadScreenReaderEnabledTimer)
+ {
+ mReadScreenReaderEnabledTimer.Stop();
+ mReadScreenReaderEnabledTimer.Reset();
+ }
+
+ mIsScreenReaderEnabled = std::get<0>(msg);
+ SwitchBridge();
+ });
+ }
+
+ void EmitScreenReaderEnabledSignal()
+ {
+ if (mIsScreenReaderEnabled)
+ {
+ mScreenReaderEnabledSignal.Emit();
+ }
+ else
+ {
+ mScreenReaderDisabledSignal.Emit();
+ }
+ }
+
+ void ListenScreenReaderEnabledProperty()
+ {
+ mAccessibilityStatusClient.addPropertyChangedEvent<bool>("ScreenReaderEnabled", [this](bool res) {
+ mIsScreenReaderEnabled = res;
+ EmitScreenReaderEnabledSignal();
+ SwitchBridge();
+ });
+ }
+
+ void ReadAndListenProperties()
+ {
+ ReadIsEnabledProperty();
+ ListenIsEnabledProperty();
+
+ ReadScreenReaderEnabledProperty();
+ ListenScreenReaderEnabledProperty();
+ }
+
+ bool InitializeAccessibilityStatusClient()
+ {
+ mAccessibilityStatusClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
+
+ if (!mAccessibilityStatusClient)
+ {
+ DALI_LOG_ERROR("Accessibility Status DbusClient is not ready\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool InitializeTimerCallback()
+ {
+ if ( InitializeAccessibilityStatusClient() )
+ {
+ ReadAndListenProperties();
+ return false;
+ }
+ return true;
+ }
+
+ bool OnIdleSignal()
+ {
+ if ( InitializeAccessibilityStatusClient() )
+ {
+ ReadAndListenProperties();
+ mIdleCallback = NULL;
+ return false;
+ }
+
+ if(!mInitializeTimer)
+ {
+ mInitializeTimer = Dali::Timer::New(RETRY_INTERVAL);
+ mInitializeTimer.TickSignal().Connect(this, &BridgeImpl::InitializeTimerCallback);
+ }
+ mInitializeTimer.Start();
+
+ mIdleCallback = NULL;
+ return false;
+ }
+
+ /**
+ * @copydoc Dali::Accessibility::Bridge::Initialize()
+ */
+ void Initialize() override
+ {
+ if ( InitializeAccessibilityStatusClient() )
+ {
+ ReadAndListenProperties();
+ return;
+ }
+
+ // Initialize failed. Try it again on Idle
+ if( Dali::Adaptor::IsAvailable() )
+ {
+ Dali::Adaptor& adaptor = Dali::Adaptor::Get();
+ if( NULL == mIdleCallback )
+ {
+ mIdleCallback = MakeCallback( this, &BridgeImpl::OnIdleSignal );
+ adaptor.AddIdle( mIdleCallback, true );
+ }
+ }
+ }
+
+ /**
+ * @copydoc Dali::Accessibility::Bridge::GetScreenReaderEnabled()
+ */
+ bool GetScreenReaderEnabled() override
+ {
+ return mIsScreenReaderEnabled;
+ }
+
+ /**
+ * @copydoc Dali::Accessibility::Bridge::IsEnabled()
+ */
+ bool IsEnabled() override
+ {
+ return mIsEnabled;
+ }
+
+ Address EmbedSocket(const Address& plug, const Address& socket) override
+ {
+ auto client = CreateSocketClient(socket);
+ auto reply = client.method<Address(Address)>("Embed").call(plug);
+
+ if(!reply)
+ {
+ DALI_LOG_ERROR("Failed to embed socket %s: %s", socket.ToString().c_str(), reply.getError().message.c_str());
+ return {};
+ }
+
+ return std::get<0>(reply.getValues());
+ }
+
+ void EmbedAtkSocket(const Address& plug, const Address& socket) override
+ {
+ auto client = CreateSocketClient(socket);
+
+ client.method<void(std::string)>("Embedded").call(ATSPI_PREFIX_PATH + plug.GetPath());
+ }
+
+ void UnembedSocket(const Address& plug, const Address& socket) override
+ {
+ auto client = CreateSocketClient(socket);
+
+ client.method<void(Address)>("Unembed").call(plug);
+ }
+
+private:
+ DBus::DBusClient CreateSocketClient(const Address& socket)
+ {
+ return {socket.GetBus(), ATSPI_PREFIX_PATH + socket.GetPath(), Accessible::GetInterfaceName(AtspiInterface::SOCKET), mConnectionPtr};
+ }
+}; // BridgeImpl
+
+namespace // unnamed namespace