Added performance logging back into adaptor build 45/167745/4
authorDavid Steele <david.steele@samsung.com>
Fri, 19 Jan 2018 13:31:13 +0000 (13:31 +0000)
committerDavid Steele <david.steele@samsung.com>
Fri, 19 Jan 2018 15:51:48 +0000 (15:51 +0000)
Fixed minor issues with build files

Change-Id: I73867cf404b955620a38365570dcc1ef6cf22616

build/tizen/adaptor/Makefile.am
dali/internal/network/common/automation.cpp [new file with mode: 0644]
dali/internal/network/common/network-performance-client.cpp [new file with mode: 0644]
dali/internal/network/common/network-performance-protocol.cpp [new file with mode: 0644]
dali/internal/network/common/network-performance-server.cpp [new file with mode: 0644]
dali/internal/network/file.list
dali/internal/system/common/performance-server.h
dali/internal/window-system/file.list
dali/internal/window-system/tizen/display-connection-impl-tizen.cpp [deleted file]

index 48b6b7c..f5171f1 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017 Samsung Electronics Co., Ltd.
+# Copyright (c) 2018 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.
@@ -70,9 +70,14 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
 
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
 endif
 
-#                   $(adaptor_accessibility_tizen_common_src_files)
+endif
+
+
 if MOBILE_PROFILE
 LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(adaptor_accessibility_common_src_files) \
@@ -111,9 +116,13 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
 
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
+endif
+
 endif
 
-#                   $(adaptor_accessibility_tizen_common_src_files)
 
 if IVI_PROFILE
 LIBDALI_ADAPTOR_LA_SOURCES = \
@@ -152,9 +161,14 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(devel_api_text_abstraction_src_files) \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
+
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
+endif
+
 endif
 
-#                  $(adaptor_accessibility_tizen_common_src_files)
 
 if TV_PROFILE
 LIBDALI_ADAPTOR_LA_SOURCES = \
@@ -192,6 +206,12 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(devel_api_text_abstraction_src_files) \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
+
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
+endif
+
 endif
 
 if COMMON_PROFILE
@@ -230,9 +250,14 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(devel_api_text_abstraction_src_files) \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
+
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
+endif
+
 endif
 
-#                  $(adaptor_accessibility_tizen_common_src_files)
 
 
 if WEARABLE_PROFILE
@@ -273,8 +298,15 @@ LIBDALI_ADAPTOR_LA_SOURCES = \
                   $(devel_api_text_abstraction_src_files) \
                   $(static_libraries_glyphy_src_files) \
                   $(static_libraries_libunibreak_src_files)
+
+if ENABLE_NETWORK_LOGGING
+LIBDALI_ADAPTOR_LA_SOURCES += \
+                  $(adaptor_performance_logging_src_files)
+endif
+
 endif
 
+
 # Package doc
 package_doxy_dir = ../../../doc
 include ../../../doc/file.list
diff --git a/dali/internal/network/common/automation.cpp b/dali/internal/network/common/automation.cpp
new file mode 100644 (file)
index 0000000..91e535d
--- /dev/null
@@ -0,0 +1,373 @@
+
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/network/common/automation.h>
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <iomanip>
+#include <stdio.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/debug.h>
+
+
+namespace  // un-named namespace
+{
+
+const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
+
+class JsonPropertyValue
+{
+public:
+  JsonPropertyValue( const std::string& str )
+  {
+    std::size_t strLength = str.length();
+
+    mString.reserve( strLength );
+    for( std::size_t i = 0; i < strLength; ++i )
+    {
+      const char c = str[i];
+      if( (c != '[') && c != ']')
+      {
+        mString.push_back( c );
+      }
+    }
+
+  }
+  std::string GetString() const
+  {
+    return mString;
+  }
+  float GetFloat() const
+  {
+    return atof( mString.c_str() );
+  }
+  int GetInt()
+  {
+    return atoi( mString.c_str() );
+  }
+  bool GetBoolean()
+  {
+    return (GetInt() != 0);
+  }
+
+  Dali::Vector2 GetVector2()
+  {
+    Dali::Vector2 vec2;
+
+    int count = sscanf( mString.c_str(),"%f,%f",&vec2.x,&vec2.y );
+    if( count != 2 )
+    {
+      DALI_LOG_ERROR("Bad format\n");
+    }
+    return vec2;
+  }
+
+  Dali::Vector3 GetVector3()
+  {
+    Dali::Vector3 vec3;
+
+    int count = sscanf( mString.c_str(),"%f,%f,%f",&vec3.x,&vec3.y,&vec3.z );
+    if( count != 3 )
+    {
+      DALI_LOG_ERROR("Bad format\n");
+    }
+    return vec3;
+  }
+
+  Dali::Vector4 GetVector4()
+  {
+    Dali::Vector4 vec4;
+
+    int count = sscanf( mString.c_str(),"%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w );
+    if( count != 4 )
+    {
+      DALI_LOG_ERROR("Bad format\n");
+    }
+    return vec4;
+  }
+
+private:
+  std::string mString;
+
+};
+
+void SetProperty( Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue )
+{
+  Dali::Property::Type type = handle.GetPropertyType( propertyId );
+  switch( type )
+  {
+  case Dali::Property::FLOAT:
+  {
+    float val = propertyValue.GetFloat();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::INTEGER:
+  {
+    int val = propertyValue.GetInt();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::BOOLEAN:
+  {
+    bool val = propertyValue.GetBoolean();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::STRING:
+  {
+    std::string str = propertyValue.GetString();
+    handle.SetProperty( propertyId, Dali::Property::Value( str ) );
+    break;
+  }
+  case Dali::Property::VECTOR2:
+  {
+    Dali::Vector2 val = propertyValue.GetVector2();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::VECTOR3:
+  {
+    Dali::Vector3 val = propertyValue.GetVector3();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  case Dali::Property::VECTOR4:
+  {
+    Dali::Vector4 val = propertyValue.GetVector4();
+    handle.SetProperty( propertyId, Dali::Property::Value( val ) );
+    break;
+  }
+  default:
+  {
+    break;
+  }
+  }
+}
+
+int SetProperties( const std::string& setPropertyMessage )
+{
+  std::istringstream iss( setPropertyMessage );
+  std::string token;
+  getline( iss, token, '|' ); // swallow command name
+  while( getline( iss, token, '|' ) )
+  {
+    std::string actorId, propName, propValue;
+    if( token.compare( "---" ) != 0 )
+    {
+      std::istringstream propss( token );
+      getline( propss, actorId, ';' );
+      getline( propss, propName, ';' );
+      getline( propss, propValue );
+
+      Dali::Actor root = Dali::Stage::GetCurrent().GetRootLayer();
+      int id = atoi( actorId.c_str() );
+      Dali::Actor a = root.FindChildById( id );
+      if( a )
+      {
+        // lookup by name for custom properties
+        int propId = a.GetPropertyIndex( propName );
+        if( propId > 0 )
+        {
+          JsonPropertyValue pv( propValue );
+          SetProperty( a, propId, pv );
+        }
+
+      }
+    }
+  }
+
+  return 0;
+}
+
+
+}; //   un-named namespace
+
+inline std::string Quote( const std::string& in )
+{
+  return (std::string( "\"" ) + in + std::string( "\"" ));
+}
+
+template<class T>
+std::string ToString( T i )
+{
+  std::stringstream ss;
+  std::string s;
+  ss << i;
+  s = ss.str();
+
+  return s;
+}
+
+
+// currently rotations are output in Euler format ( may change)
+void AppendPropertyNameAndValue( Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
+{
+  // get the property name and the value as a string
+  std::string propertyName( handle.GetPropertyName( propertyIndex ) );
+
+  // Apply quotes around the property name
+  outputStream << "\"" << propertyName << "\"" << ",";
+
+  // Convert value to a string
+  std::ostringstream valueStream;
+  Dali::Property::Value value = handle.GetProperty( propertyIndex );
+  valueStream << value;
+  std::string valueString = valueStream.str();
+
+  if( value.GetType() == Dali::Property::STRING )
+  {
+    // Escape the string (to ensure valid json)
+    // Write out quotes, escapes and control characters using unicode syntax \uXXXX
+    std::ostringstream escapedValue;
+    for( std::string::iterator c = valueString.begin() ; c != valueString.end(); ++c )
+    {
+      if( *c == '"' )
+      {
+        escapedValue << "\\\"";
+      }
+      else if( *c == '\\' )
+      {
+        escapedValue << "\\\\";
+      }
+      else if( '\x00' <= *c && *c <= '\x1f' )
+      {
+        escapedValue << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(*c);
+      }
+      else
+      {
+        escapedValue << *c;
+      }
+    }
+
+    valueString = escapedValue.str();
+  }
+
+  outputStream << "\"" << valueString << "\"";
+}
+
+bool ExcludeProperty( int propIndex )
+{
+  return (propIndex == Dali::Actor::Property::NAME    ||
+
+      // all of these are repeat properties of values in vectors....
+      // We don't really need these in the UI
+      propIndex == Dali::Actor::Property::ANCHOR_POINT_X || propIndex == Dali::Actor::Property::ANCHOR_POINT_Y || propIndex == Dali::Actor::Property::ANCHOR_POINT_Z || propIndex == Dali::Actor::Property::PARENT_ORIGIN_X
+      || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z || propIndex == Dali::Actor::Property::COLOR_RED || propIndex == Dali::Actor::Property::COLOR_GREEN
+      || propIndex == Dali::Actor::Property::COLOR_BLUE || propIndex == Dali::Actor::Property::COLOR_ALPHA|| propIndex == Dali::Actor::Property::POSITION_X || propIndex == Dali::Actor::Property::POSITION_Y
+      || propIndex == Dali::Actor::Property::POSITION_Z|| propIndex == Dali::Actor::Property::SIZE_WIDTH|| propIndex == Dali::Actor::Property::SIZE_HEIGHT || propIndex == Dali::Actor::Property::SCALE_X || propIndex == Dali::Actor::Property::SCALE_Y
+      || propIndex == Dali::Actor::Property::SCALE_Z || propIndex == Dali::Actor::Property::SIZE_DEPTH);
+}
+
+std::string DumpJson( Dali::Actor actor, int level )
+{
+  // All the information about this actor
+  std::ostringstream msg;
+  msg << "{ " << Quote( "Name" ) << " : " << Quote( actor.GetName() ) << ", " << Quote( "level" ) << " : " << level << ", " << Quote( "id" ) << " : " << actor.GetId() << ", " << Quote( "IsVisible" )
+      << " : " << actor.IsVisible() << ", " << Quote( "IsSensitive" ) << " : " << actor.IsSensitive();
+
+  msg << ", " << Quote( "properties" ) << ": [ ";
+
+  Dali::Property::IndexContainer indices;
+  actor.GetPropertyIndices( indices );
+
+  Dali::Property::IndexContainer::Iterator iter = indices.Begin();
+  int numCustom = 0;
+  for( ; iter != indices.End() ; iter++ )
+  {
+    int i = *iter;
+    if( !ExcludeProperty( i ) )
+    {
+      if( numCustom++ != 0 )
+      {
+        msg << ", ";
+      }
+      msg << "[";
+
+      AppendPropertyNameAndValue( actor, i,msg );
+
+      msg << "]";
+    }
+  }
+  msg << "]";
+  msg << ", " << Quote( "children" ) << " : [ ";
+
+  // Recursively dump all the children as well
+  for( unsigned int i = 0 ; i < actor.GetChildCount() ; ++i )
+  {
+    if( i )
+    {
+      msg << " , ";
+    }
+    msg << DumpJson( actor.GetChildAt( i ), level + 1 );
+  }
+  msg << "] }";
+
+  return msg.str();
+}
+
+std::string GetActorTree()
+{
+  Dali::Actor actor = Dali::Stage::GetCurrent().GetRootLayer();
+  std::string str = DumpJson( actor, 0 );
+  return str;
+}
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace Automation
+{
+
+void SetProperty( const std::string& message )
+{
+  // check the set property length is within range
+  if( message.length() > MAX_SET_PROPERTY_STRING_LENGTH )
+  {
+    DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
+    return;
+  }
+
+  SetProperties( message );
+}
+
+void DumpScene( unsigned int clientId, ClientSendDataInterface* sendData )
+{
+  char buf[32];
+  std::string json = GetActorTree();
+  int length = json.length();
+  snprintf( buf, 32, "%d\n", length );
+  std::string header( buf );
+  json = buf + json;
+  sendData->SendData( json.c_str(), json.length(), clientId );
+}
+
+} // namespace Automation
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
diff --git a/dali/internal/network/common/network-performance-client.cpp b/dali/internal/network/common/network-performance-client.cpp
new file mode 100644 (file)
index 0000000..2a1c301
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/network/common/network-performance-client.h>
+
+// EXTERNAL INCLUDES
+#include <stdio.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/internal/network/common/socket-interface.h>
+#include <dali/internal/network/common/network-performance-protocol.h>
+#include <dali/internal/network/common/automation.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+const float MICROSECONDS_TO_SECOND = 1e-6;
+const char UNKNOWN_CMD[]= "Command or parameter invalid, type help for list of commands\n";
+
+
+/**
+ * helper class to store data along with the automation callback.
+ */
+class AutomationCallback: public CallbackBase
+{
+public:
+
+  /**
+   * instead of using templates, or having different callback classes for each callback
+   * we use a command id that decides which static function to call on the Automation class.
+   */
+  enum CommandId
+  {
+    UNKNOWN_COMMAND,
+    SET_PROPERTY,
+    DUMP_SCENE
+  };
+
+  AutomationCallback(  unsigned int clientId, ClientSendDataInterface& sendDataInterface )
+  :CallbackBase( reinterpret_cast< void* >( this ),
+                 NULL, // we get the dispatcher to call function directly
+                 reinterpret_cast< CallbackBase::Dispatcher>( &AutomationCallback::Dispatcher) ),
+  mSendDataInterface( sendDataInterface ),
+  mCommandId( UNKNOWN_COMMAND ),
+  mClientId( clientId )
+  {}
+
+  void AssignSetPropertyCommand( std::string setPropertyCommand )
+  {
+    mCommandId = SET_PROPERTY;
+    mPropertyCommand = setPropertyCommand;
+  }
+  void AssignDumpSceneCommand()
+  {
+     mCommandId = DUMP_SCENE;
+  }
+
+  void RunCallback()
+  {
+    switch( mCommandId )
+    {
+      case SET_PROPERTY:
+      {
+        Automation::SetProperty( mPropertyCommand );
+        break;
+      }
+      case DUMP_SCENE:
+      {
+        Automation::DumpScene( mClientId, &mSendDataInterface);
+        break;
+      }
+      default:
+      {
+        DALI_ASSERT_DEBUG( 0 && "Unknown command");
+        break;
+      }
+    }
+  }
+  static void Dispatcher( CallbackBase& base )
+  {
+    AutomationCallback& automationCallback( static_cast< AutomationCallback& >( base) );
+    automationCallback.RunCallback();
+  }
+
+private:
+
+  std::string mPropertyCommand;                   ///< property command
+  ClientSendDataInterface& mSendDataInterface;    ///< Abstract client send data interface
+  CommandId mCommandId;                           ///< command id
+  const unsigned int mClientId;                   ///< client id
+};
+
+} // unnamed namespace
+
+NetworkPerformanceClient::NetworkPerformanceClient(  pthread_t* thread,
+                                                     SocketInterface *socket,
+                                                     unsigned int clientId,
+                                                     TriggerEventFactoryInterface& triggerEventFactory,
+                                                     ClientSendDataInterface& sendDataInterface,
+                                                     SocketFactoryInterface& socketFactory )
+: mThread( thread ),
+  mSocket( socket ),
+  mMarkerBitmask( PerformanceMarker::FILTERING_DISABLED ),
+  mTriggerEventFactory( triggerEventFactory ),
+  mSendDataInterface( sendDataInterface ),
+  mSocketFactoryInterface( socketFactory ),
+  mClientId( clientId ),
+  mConsoleClient(false)
+{
+
+}
+
+NetworkPerformanceClient::~NetworkPerformanceClient()
+{
+  if( mSocket->SocketIsOpen() )
+  {
+    mSocket->CloseSocket();
+  }
+  mSocketFactoryInterface.DestroySocket( mSocket );
+}
+
+unsigned int NetworkPerformanceClient::GetId() const
+{
+  return mClientId;
+}
+
+SocketInterface& NetworkPerformanceClient::GetSocket()
+{
+  return *mSocket;
+}
+
+bool NetworkPerformanceClient::WriteSocket( const void* buffer, unsigned int bufferSizeInBytes )
+{
+  return mSocket->Write( buffer, bufferSizeInBytes );
+}
+
+bool NetworkPerformanceClient::TransmitMarker( const PerformanceMarker& marker, const char* const description )
+{
+  if( ! marker.IsFilterEnabled( mMarkerBitmask ) )
+  {
+    return true;
+  }
+  if( mConsoleClient )
+  {
+    // write out the time stamp
+    char buffer[64];
+    double usec = marker.GetTimeStamp().microseconds;
+    int size = snprintf( buffer, sizeof(buffer),"%.6f (seconds), %s\n",
+                         usec * MICROSECONDS_TO_SECOND,
+                         description );
+
+   return mSocket->Write( buffer, size );
+
+  }
+
+
+  // todo serialize the data
+  return false;
+}
+
+void NetworkPerformanceClient::ExitSelect()
+{
+  mSocket->ExitSelect();
+}
+
+pthread_t* NetworkPerformanceClient::GetThread()
+{
+  return mThread;
+}
+
+void NetworkPerformanceClient::ProcessCommand( char* buffer, unsigned int bufferSizeInBytes )
+{
+  // if connected via console, then strip off the carriage return, and switch to console mode
+  if( buffer[ bufferSizeInBytes - 1] == '\n')
+  {
+    buffer[ bufferSizeInBytes - 1] = 0;
+    mConsoleClient = true;
+  }
+  unsigned int param(0);
+  std::string stringParam;
+  PerformanceProtocol::CommandId commandId( PerformanceProtocol::UNKNOWN_COMMAND );
+
+  bool ok =  PerformanceProtocol::GetCommandId( buffer, bufferSizeInBytes, commandId, param, stringParam );
+  if( !ok )
+  {
+    WriteSocket( UNKNOWN_CMD, sizeof(UNKNOWN_CMD) );
+    return;
+  }
+  std::string response;
+
+  switch( commandId )
+  {
+    case PerformanceProtocol::HELP_MESSAGE:
+    {
+      response = PerformanceProtocol::GetHelpMessage();
+      break;
+    }
+
+    case PerformanceProtocol::ENABLE_TIME_MARKER_BIT_MASK:
+    {
+      mMarkerBitmask  = static_cast<  PerformanceMarker::MarkerFilter >( param );
+      response = "enable time marker ";
+      break;
+    }
+
+    case PerformanceProtocol::DUMP_SCENE_GRAPH:
+    {
+      // this needs to be run on the main thread, use the trigger event....
+      AutomationCallback* callback = new AutomationCallback( mClientId, mSendDataInterface );
+      callback->AssignDumpSceneCommand();
+
+      // create a trigger event that automatically deletes itself after the callback has run in the main thread
+      TriggerEventInterface *interface = mTriggerEventFactory.CreateTriggerEvent( callback, TriggerEventInterface::DELETE_AFTER_TRIGGER );
+
+      // asynchronous call, the call back will be run sometime later on the main thread
+      interface->Trigger();
+      break;
+    }
+
+    case PerformanceProtocol::SET_PROPERTIES:
+    {
+      // this needs to be run on the main thread, use the trigger event....
+      AutomationCallback* callback = new AutomationCallback( mClientId, mSendDataInterface );
+      callback->AssignSetPropertyCommand( stringParam );
+
+      // create a trigger event that automatically deletes itself after the callback has run in the main thread
+      TriggerEventInterface *interface = mTriggerEventFactory.CreateTriggerEvent( callback, TriggerEventInterface::DELETE_AFTER_TRIGGER );
+
+      // asynchronous call, the call back will be run sometime later on the main thread
+      interface->Trigger();
+      break;
+    }
+
+    case PerformanceProtocol::LIST_METRICS_AVAILABLE:
+    case PerformanceProtocol::ENABLE_METRIC:
+    case PerformanceProtocol::DISABLE_METRIC:
+    {
+      response="Metrics currently not supported";
+      break;
+    }
+    default:
+    {
+      response = UNKNOWN_CMD;
+      break;
+    }
+  }
+  if( ! response.empty() )
+  {
+    // add a carriage return for console clients
+    if( mConsoleClient )
+    {
+      response+="\n";
+    }
+    WriteSocket( response.c_str(), response.length()  );
+  }
+}
+
+
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
diff --git a/dali/internal/network/common/network-performance-protocol.cpp b/dali/internal/network/common/network-performance-protocol.cpp
new file mode 100644 (file)
index 0000000..5b28773
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+// CLASS HEADER
+#include <dali/internal/network/common/network-performance-protocol.h>
+
+// EXTERNAL INCLUDES
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace Dali
+{
+
+namespace PerformanceProtocol
+{
+
+namespace
+{
+
+/**
+ * Command parameter type
+ */
+enum PARAMETER_TYPE
+{
+  NO_PARAMS,
+  UNSIGNED_INT,
+  STRING
+};
+
+/**
+ * Command information structure
+ */
+struct CommandInfo
+{
+  CommandId     cmdId;
+  CommandString cmdString;
+  PARAMETER_TYPE paramType;
+};
+
+/**
+ * Command lookup table
+ */
+CommandInfo CommandLookup[]=
+{
+  {  HELP_MESSAGE               , "help"               ,NO_PARAMS     },
+  {  ENABLE_METRIC              , "enable_metric"      ,UNSIGNED_INT  },
+  {  DISABLE_METRIC             , "disable_metric"     ,UNSIGNED_INT  },
+  {  LIST_METRICS_AVAILABLE     , "list_metrics"       ,NO_PARAMS     },
+  {  ENABLE_TIME_MARKER_BIT_MASK, "set_marker",         UNSIGNED_INT  },
+  {  DUMP_SCENE_GRAPH           , "dump_scene"         ,NO_PARAMS     },
+  {  SET_PROPERTIES             , "set_properties"     ,STRING        },
+  {  UNKNOWN_COMMAND            , "unknown"            ,NO_PARAMS     }
+};
+const unsigned int CommandLookupLength = sizeof( CommandLookup ) /sizeof( CommandInfo );
+
+#define GREEN  "\033[01;32m"
+#define NORMAL  "\e[m"
+#define PARAM "\033[22;32m"
+#define YELLOW "\033[01;33m"
+
+const char* const helpMsg =
+    YELLOW
+    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+    "  Dali performance console                           \n"
+    "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" NORMAL
+    GREEN " list_metrics " NORMAL " - list available metrics\n"
+    GREEN " enable_metric " PARAM " metricId" NORMAL " - enable a metric \n"
+    GREEN " disable_metric " PARAM " metricId" NORMAL " - disable a metric\n\n"
+    GREEN " set_marker " PARAM " value " NORMAL "-output Dali markers\n"
+    "            : Bit 0  = V_SYNC (1)\n"
+    "            : Bit 1  = Update task (2)\n"
+    "            : Bit 2  = Render task (4) \n"
+    "            : Bit 3  = Event Processing task (8)\n"
+    "            : Bit 4  = SwapBuffers (16)\n"
+    "            : Bit 5  = Life cycle events  (32)\n"
+    "            : Bit 6  = Resource event (64)\n"
+    "\n"
+    GREEN " set_properties " NORMAL " - set an actor property command. Format:\n\n"
+    GREEN " set_properties " PARAM "|ActorIndex;Property;Value|" NORMAL ", e.g: \n"
+    GREEN " set_properties " PARAM "|178;Size;[ 144.0, 144.0, 144.0 ]|178;Color;[ 1.0, 1,0, 1.0 ]|\n"
+    "\n"
+    GREEN " dump_scene" NORMAL " - dump the current scene in json format\n";
+
+} // un-named namespace
+
+bool GetCommandId( const char* const commandString, unsigned int lengthInBytes, CommandId& commandId, unsigned int& intParam, std::string& stringParam  )
+{
+  commandId = UNKNOWN_COMMAND;
+  intParam = 0;
+
+  // the command list is small so just do a O(n) search for the commandID.
+  for( unsigned int i = 0 ; i < CommandLookupLength; ++i )
+  {
+    if( strncmp( commandString, CommandLookup[i].cmdString ,strlen(CommandLookup[i].cmdString  )) == 0 )
+    {
+      commandId = CommandLookup[i].cmdId;
+
+      // if the command has a parameter read it
+      if( CommandLookup[i].paramType ==  UNSIGNED_INT)
+      {
+        int count = sscanf(commandString,"%*s %d",&intParam);
+        if( count != 1 )
+        {
+          // missing parameter
+          return false;
+        }
+      }
+      else if (CommandLookup[i].paramType == STRING )
+      {
+        char* charParam( NULL );
+        // allocates the character array
+        int count = sscanf(commandString,"%*s %ms",&charParam);
+        if( count != 1 )
+        {
+          // missing parameter
+          return false;
+        }
+        stringParam = std::string( charParam);
+        free(charParam);
+      }
+      return true;
+    }
+  }
+  // not found
+  return false;
+}
+
+bool GetCommandString( CommandId commandId, CommandString& commandString )
+{
+  for( unsigned int i = 0; i < CommandLookupLength; ++i)
+  {
+    if( CommandLookup[ i ].cmdId == commandId )
+    {
+      strncpy( commandString,  CommandLookup[ i ].cmdString, strlen(CommandLookup[ i ].cmdString) );
+      return true;
+    }
+  }
+  strncpy( commandString, CommandLookup[ UNKNOWN_COMMAND ].cmdString, MAX_COMMAND_STRING_LENGTH);
+  return false;
+}
+
+const char* const GetHelpMessage()
+{
+  return helpMsg;
+}
+
+
+} // namespace PerformanceProtocol
+
+} // namespace Dali
diff --git a/dali/internal/network/common/network-performance-server.cpp b/dali/internal/network/common/network-performance-server.cpp
new file mode 100644 (file)
index 0000000..fcd11bf
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/network/common/network-performance-server.h>
+
+
+// INTERNAL INCLUDES
+#include <dali/internal/system/common/performance-marker.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace // un-named namespace
+{
+const unsigned int SERVER_PORT = 3031;
+const unsigned int MAXIMUM_PORTS_TO_TRY = 10; ///< if port in use, try up to SERVER_PORT + 10
+const unsigned int CONNECTION_BACKLOG = 2;   ///<  maximum length of the queue of pending connections.
+const unsigned int SOCKET_READ_BUFFER_SIZE = 4096;
+typedef Vector< NetworkPerformanceClient*> ClientList;
+
+/**
+ * POD passed to client thread on startup
+ */
+struct ClientThreadInfo
+{
+  NetworkPerformanceServer* server;
+  NetworkPerformanceClient* client;
+};
+}
+
+NetworkPerformanceServer::NetworkPerformanceServer( AdaptorInternalServices& adaptorServices,
+                                                    const EnvironmentOptions& logOptions )
+: mTriggerEventFactory( adaptorServices.GetTriggerEventFactoryInterface() ),
+  mSocketFactory( adaptorServices.GetSocketFactoryInterface() ),
+  mLogOptions( logOptions ),
+  mServerThread( 0 ),
+  mListeningSocket( NULL ),
+  mClientUniqueId( 0 ),
+  mClientCount( 0 ),
+  mLogFunctionInstalled( false )
+{
+}
+
+NetworkPerformanceServer::~NetworkPerformanceServer()
+{
+  Stop();
+
+  if( mLogFunctionInstalled )
+  {
+    mLogOptions.UnInstallLogFunction();
+  }
+}
+
+void NetworkPerformanceServer::Start()
+{
+  // start a thread to listen for incoming connection requests
+  if (! mServerThread )
+  {
+    if( mListeningSocket )
+    {
+      mSocketFactory.DestroySocket( mListeningSocket );
+    }
+    mListeningSocket = mSocketFactory.NewSocket( SocketInterface::TCP);
+    mListeningSocket->ReuseAddress( true );
+
+    bool bound = false;
+    unsigned int basePort = 0;
+
+    // try a small range of ports, so if multiple Dali apps are running you can select
+    // which one to connect to
+    while( !bound && ( basePort <  MAXIMUM_PORTS_TO_TRY ))
+    {
+      bound = mListeningSocket->Bind( SERVER_PORT + basePort );
+      if( !bound )
+      {
+        basePort++;
+      }
+    }
+    if(!bound )
+    {
+      DALI_LOG_ERROR("Failed to bind to a port \n");
+      return;
+    }
+
+    mListeningSocket->Listen( CONNECTION_BACKLOG );
+
+    // start a thread which will block waiting for new connections
+    int error = pthread_create( &mServerThread, NULL, ConnectionListenerFunc, this );
+    DALI_ASSERT_ALWAYS( !error && "pthread create failed" );
+
+    Dali::Integration::Log::LogMessage(Integration::Log::DebugInfo, "~~~ NetworkPerformanceServer started on port %d ~~~ \n",  SERVER_PORT + basePort);
+
+  }
+}
+void NetworkPerformanceServer::Stop()
+{
+  if( !mServerThread )
+  {
+    return;
+  }
+
+  if( mListeningSocket )
+  {
+    // close the server thread to prevent any new connections
+    mListeningSocket->ExitSelect();
+  }
+
+  // wait for the thread to exit.
+  void* exitValue;
+  pthread_join( mServerThread, &exitValue );
+
+  if( mListeningSocket )
+  {
+    // close the socket
+    mListeningSocket->CloseSocket();
+  }
+
+  mSocketFactory.DestroySocket( mListeningSocket );
+
+  mListeningSocket = NULL;
+
+  // this will tell all client threads to quit
+  StopClients();
+
+}
+
+bool NetworkPerformanceServer::IsRunning() const
+{
+  if (mServerThread )
+  {
+    return true;
+  }
+  return false;
+}
+
+void NetworkPerformanceServer::ClientThread( NetworkPerformanceClient* client )
+{
+  mClientCount++;
+
+  SocketInterface& socket( client->GetSocket() );
+
+  for( ;; )
+  {
+    SocketInterface::SelectReturn ret = socket.Select();
+
+    if( ret == SocketInterface::DATA_AVAILABLE )
+    {
+     // Read
+      char buffer[ SOCKET_READ_BUFFER_SIZE ];
+      unsigned int  bytesRead;
+
+      bool ok  = socket.Read( buffer, sizeof( buffer ) , bytesRead);
+      if( ok && ( bytesRead > 0) )
+      {
+        client->ProcessCommand( buffer, bytesRead );
+      }
+      else   // if bytesRead == 0, then client closed connection, if ok == false then an error
+      {
+        DeleteClient( client );
+        return;
+      }
+    }
+    else // ret == QUIT or ERROR
+    {
+      DeleteClient( client);
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::ConnectionListener()
+{
+  // install Dali logging function for this thread
+  if( !mLogFunctionInstalled )
+  {
+    mLogOptions.InstallLogFunction();
+    mLogFunctionInstalled = true;
+  }
+
+  for( ;; )
+  {
+    // this will block, waiting for a client to connect
+    // or for mListeningSocket->ExitSelect() to be called
+
+    SocketInterface::SelectReturn ret = mListeningSocket->Select();
+
+    if( ret == SocketInterface::DATA_AVAILABLE )
+    {
+      SocketInterface* clientSocket = mListeningSocket->Accept();
+
+      // new connection made, spawn a thread to handle it
+      pthread_t* clientThread = new pthread_t();
+
+      NetworkPerformanceClient* client = AddClient( clientSocket, clientThread );
+
+      ClientThreadInfo* info = new ClientThreadInfo;
+      info->client = client;
+      info->server = this;
+
+      int error = pthread_create( clientThread, NULL, ClientThreadFunc, info );
+      DALI_ASSERT_ALWAYS( !error && "pthread create failed" );
+
+    }
+    else // ret == SocketInterface::QUIT or SocketInterface::ERROR
+    {
+      return;
+    }
+  }
+}
+
+void* NetworkPerformanceServer::ClientThreadFunc( void* data )
+{
+  ClientThreadInfo* info = static_cast<ClientThreadInfo*>( data );
+  info->server->ClientThread( info->client );
+  delete info;
+  return NULL;
+}
+
+NetworkPerformanceClient* NetworkPerformanceServer::AddClient( SocketInterface* clientSocket, pthread_t* clientThread )
+{
+  // This function is only called from the listening thread
+  NetworkPerformanceClient* client= new NetworkPerformanceClient( clientThread,
+                                                                  clientSocket,
+                                                                  mClientUniqueId++,
+                                                                  mTriggerEventFactory,
+                                                                  *this,
+                                                                  mSocketFactory);
+
+  // protect the mClients list which can be accessed from multiple threads.
+  Mutex::ScopedLock lock( mClientListMutex );
+
+  mClients.PushBack( client );
+
+  return client;
+}
+
+void NetworkPerformanceServer::DeleteClient( NetworkPerformanceClient* client )
+{
+  // protect the mClients list while modifying
+  Mutex::ScopedLock lock( mClientListMutex );
+
+  // remove from the list, and delete it
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    if( (*iter) == client )
+    {
+      mClients.Erase( iter );
+      delete client;
+
+      // if there server is shutting down, it waits for client count to hit zero
+      mClientCount--;
+
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::SendData( const char* const data, unsigned int bufferSizeInBytes,unsigned int clientId )
+{
+  if( ! mClientCount )
+  {
+    return;
+  }
+
+  // prevent clients been added / deleted while transmiting data
+  Mutex::ScopedLock lock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    if( client->GetId() == clientId )
+    {
+      client->WriteSocket(data ,bufferSizeInBytes);
+      return;
+    }
+  }
+}
+
+void NetworkPerformanceServer::TransmitMarker( const PerformanceMarker& marker, const char* const description )
+{
+  if( ! IsRunning() )
+  {
+    return;
+  }
+  // prevent clients been added / deleted while transmiting data
+  Mutex::ScopedLock lock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    client->TransmitMarker( marker, description );
+  }
+}
+
+
+void NetworkPerformanceServer::StopClients()
+{
+  // prevent clients been added / deleted while stopping all clients
+  Mutex::ScopedLock lock( mClientListMutex );
+
+  for( ClientList::Iterator iter = mClients.Begin(); iter != mClients.End() ; ++iter )
+  {
+    NetworkPerformanceClient* client = (*iter);
+    // stop the client from waiting for new commands, and exit from it's thread
+    client->ExitSelect();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Adaptor
+
+} // namespace Dali
index f56123d..4590350 100644 (file)
@@ -3,4 +3,10 @@
 # module: network, backend: common
 adaptor_network_common_src_files=\
     ${adaptor_network_dir}/common/socket-factory.cpp \
-    ${adaptor_network_dir}/common/socket-impl.cpp
\ No newline at end of file
+    ${adaptor_network_dir}/common/socket-impl.cpp
+
+adaptor_performance_logging_src_files=\
+    $(adaptor_network_dir)/common/network-performance-protocol.cpp \
+    $(adaptor_network_dir)/common/network-performance-client.cpp \
+    $(adaptor_network_dir)/common/network-performance-server.cpp \
+    $(adaptor_network_dir)/common/automation.cpp
index b1a2452..2a6b386 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_ADAPTOR_PERFORMANCE_SERVER_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -124,7 +124,7 @@ private:
 
 #if defined(NETWORK_LOGGING_ENABLED)
   NetworkPerformanceServer mNetworkServer;                ///< network server
-  bool mNetworkControlEnabled;                          ///< Whether network control is enabled
+  bool mNetworkControlEnabled;                            ///< Whether network control is enabled
 #endif
 
   StatContextManager mStatContextManager;                 ///< Stat context manager
index 5fef61d..d272ee9 100644 (file)
@@ -11,16 +11,12 @@ adaptor_window_system_common_src_files=\
 
 # module: window-system, backend: tizen
 adaptor_window_system_tizen_src_files=\
-    ${adaptor_window_system_dir}/tizen/display-connection-impl-tizen.cpp
+    ${adaptor_window_system_dir}/tizen/native-render-surface-tizen.cpp
 
 # module: window-system, backend: tizen-mobile
 adaptor_window_system_tizen_mobile_src_files=\
     ${adaptor_window_system_dir}/tizen-mobile/native-render-surface-factory-mobile.cpp
 
-# module: window-system, backend: tizen
-adaptor_window_system_tizen_src_files=\
-    ${adaptor_window_system_dir}/tizen/native-render-surface-tizen.cpp
-
 # module: window-system, backend: tizen-wayland
 adaptor_window_system_tizen_wayland_src_files=\
     ${adaptor_window_system_dir}/tizen-wayland/display-connection-factory-ecore-wl.cpp \
diff --git a/dali/internal/window-system/tizen/display-connection-impl-tizen.cpp b/dali/internal/window-system/tizen/display-connection-impl-tizen.cpp
deleted file mode 100644 (file)
index 752f25e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- *
- */
-
-// CLASS HEADER
-#include <dali/internal/window-system/common/display-connection-impl.h>
-
-// EXTERNAL_HEADERS
-#include <tbm_bufmgr.h>
-#include <dali/integration-api/debug.h>
-
-// INTERNAL HEADERS
-#include <dali/integration-api/wayland/native-render-surface.h>
-#include <dali/internal/graphics/gles20/egl-implementation.h>
-
-namespace Dali
-{
-
-namespace Internal
-{
-
-namespace Adaptor
-{
-
-EGLNativeDisplayType DisplayConnection::GetNativeDisplay()
-{
-  return reinterpret_cast< EGLNativeDisplayType >( tbm_bufmgr_init( -1 ) );
-}
-
-void DisplayConnection::ReleaseNativeDisplay()
-{
-  if( mDisplay )
-  {
-    tbm_bufmgr_deinit( reinterpret_cast< tbm_bufmgr >( mDisplay ) );
-  }
-}
-
-} // namespace Adaptor
-
-} // namespace Internal
-
-} // namespace Dali