diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index c2ff661f..0612a997 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -75,7 +75,7 @@ jobs: run: > sudo apt update && - sudo apt install -y libsqlite3-dev libcurl4-openssl-dev valgrind lcov clang libsystemd-dev libboost-all-dev libwebsocketpp-dev meson libcunit1 libcunit1-dev curl protobuf-compiler-grpc libgrpc-dev libgrpc++-dev + sudo apt install -y libsqlite3-dev libcurl4-openssl-dev valgrind lcov clang libsystemd-dev libboost-all-dev libwebsocketpp-dev meson libcunit1 libcunit1-dev curl protobuf-compiler-grpc libgrpc-dev libgrpc++-dev gdb - name: Install GStreamer run: | @@ -590,7 +590,7 @@ jobs: PATH=$GITHUB_WORKSPACE/install/usr/bin:${PATH} LD_LIBRARY_PATH=$GITHUB_WORKSPACE/install/usr/lib:$GITHUB_WORKSPACE/install/usr/lib/wpeframework/plugins:${LD_LIBRARY_PATH} GTEST_OUTPUT="json:$(pwd)/rdkL1TestResults.json" - RdkServicesL1Test && + gdb -ex "run" -ex "bt" --args RdkServicesL1Test && cp -rf $(pwd)/rdkL1TestResults.json $GITHUB_WORKSPACE/rdkL1TestResultsWithoutValgrind.json && rm -rf $(pwd)/rdkL1TestResults.json diff --git a/Miracast/CMakeLists.txt b/Miracast/CMakeLists.txt index c0cf475e..0d547316 100644 --- a/Miracast/CMakeLists.txt +++ b/Miracast/CMakeLists.txt @@ -16,4 +16,4 @@ # limitations under the License. add_subdirectory(MiracastService) -add_subdirectory(MiracastPlayer) +add_subdirectory(MiracastPlayer) \ No newline at end of file diff --git a/Miracast/MiracastPlayer/CMakeLists.txt b/Miracast/MiracastPlayer/CMakeLists.txt index f5e8fcbe..5777fc9c 100644 --- a/Miracast/MiracastPlayer/CMakeLists.txt +++ b/Miracast/MiracastPlayer/CMakeLists.txt @@ -17,71 +17,103 @@ set(PLUGIN_NAME MiracastPlayer) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) +set(PLUGIN_IMPLEMENTATION ${MODULE_NAME}Implementation) -set(PLUGIN_MIRACAST_STARTUPORDER "" CACHE STRING "To configure startup order of MiracastPlayer plugin") +set(PLUGIN_MIRACASTPLAYER_STARTUPORDER "" CACHE STRING "To configure startup order of MiracastPlayer plugin") +set(PLUGIN_MIRACASTPLAYER_AUTOSTART "false" CACHE STRING "Automatically start MiracastPlayer plugin") + +add_definitions(-DMIRACAST_PLAYER_API_VERSION_NUMBER_MAJOR=2) +add_definitions(-DMIRACAST_PLAYER_API_VERSION_NUMBER_MINOR=0) +add_definitions(-DMIRACAST_PLAYER_API_VERSION_NUMBER_PATCH=0) + +set(MIRACAST_PLAYER_IMPLEMENTATION ${PLUGIN_NAME}Implementation) +add_definitions(-DPLUGIN_MIRACAST_PLAYER_IMPLEMENTATION_NAME="${MIRACAST_PLAYER_IMPLEMENTATION}") find_package(${NAMESPACE}Plugins REQUIRED) find_package(IARMBus) find_package(GLIB REQUIRED) - -find_package(WPEFrameworkSecurityUtil) -if(NOT WPEFRAMEWORK_SECURITYUTIL_FOUND) - add_definitions(-DSECURITY_TOKEN_ENABLED=0) -endif() - +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(${NAMESPACE}Definitions REQUIRED) +find_package(CompileSettingsDebug CONFIG REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(GSTREAMERBASE REQUIRED gstreamer-app-1.0) find_package(GStreamer REQUIRED) -find_library(GLIB_LIBRARY NAMES glib-2.0) +find_library(GLIB_LIBRARY NAMES glib-2.0 ) + +if (USE_THUNDER_R4) + find_package(${NAMESPACE}COM REQUIRED) +else () + find_package(${NAMESPACE}Protocols REQUIRED) +endif (USE_THUNDER_R4) -add_library(${MODULE_NAME} SHARED Module.cpp MiracastPlayer.cpp ../common/MiracastLogger.cpp ../common/MiracastCommon.cpp RTSP/MiracastRTSPMsg.cpp) +add_library(${MODULE_NAME} SHARED MiracastPlayer.cpp Module.cpp) + +set_target_properties(${MODULE_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) + +target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) + +include_directories(../../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${NAMESPACE}Definitions::${NAMESPACE}Definitions) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +add_library(${PLUGIN_IMPLEMENTATION} SHARED Module.cpp MiracastPlayerImplementation.cpp ../common/MiracastLogger.cpp ../common/MiracastCommon.cpp RTSP/MiracastRTSPMsg.cpp) + +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) + +set_target_properties(${PLUGIN_IMPLEMENTATION} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) +set_source_files_properties(MiracastPlayer.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") + +if (USE_THUNDER_R4) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}COM::${NAMESPACE}COM) +else () +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}Protocols::${NAMESPACE}Protocols) +endif (USE_THUNDER_R4) if (RDK_SERVICES_L1_TEST) - target_sources(${MODULE_NAME} + target_sources(${PLUGIN_IMPLEMENTATION} PRIVATE Test/MiracastGstPlayer.cpp ) else() - target_sources(${MODULE_NAME} + target_sources(${PLUGIN_IMPLEMENTATION} PRIVATE Generic/MiracastGstPlayer.cpp ) endif() -set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) -set_source_files_properties(MiracastPlayer.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -target_include_directories(${MODULE_NAME} PRIVATE ./) -target_include_directories(${MODULE_NAME} PRIVATE ../common) -target_include_directories(${MODULE_NAME} PRIVATE RTSP) -target_include_directories(${MODULE_NAME} PRIVATE ../../helpers) -target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${GSTREAMER_INCLUDES}) -target_include_directories(${MODULE_NAME} PRIVATE ${GSTREAMERBASE_INCLUDE_DIRS}) - -#target_compile_options(${MODULE_NAME} PRIVATE -Wno-error -fpermissive -Os -pipe -g -feliminate-unused-debug-types -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed) -#target_compile_options(${MODULE_NAME} PRIVATE -DENABLE_MIRACAST_PLAYER_TEST_NOTIFIER) - -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) -target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES}) -target_link_libraries(${MODULE_NAME} PRIVATE ${GSTREAMER_LIBRARIES}) -target_link_libraries(${MODULE_NAME} PRIVATE ${GSTREAMERBASE_LIBRARIES}) -target_link_libraries(${MODULE_NAME} PRIVATE -lpthread) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ./) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ../common) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE RTSP) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ../../helpers) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_INCLUDE_DIRS}) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${GLIB_INCLUDE_DIRS}) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${GSTREAMER_INCLUDES}) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${GSTREAMERBASE_INCLUDE_DIRS}) + +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${GLIB_LIBRARIES}) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${GSTREAMER_LIBRARIES}) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${GSTREAMERBASE_LIBRARIES}) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE -lpthread) if(WPEFRAMEWORK_SECURITYUTIL_FOUND) - target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}SecurityUtil) + target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}SecurityUtil) endif() if(NOT RDK_SERVICES_L1_TEST AND NOT RDK_SERVICE_L2_TEST) - target_link_libraries(${MODULE_NAME} PRIVATE MiracastPlayerHal) + target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE MiracastPlayerHal) endif() -install(TARGETS ${MODULE_NAME} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) +install(TARGETS ${PLUGIN_IMPLEMENTATION} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) -write_config(${PLUGIN_NAME}) +write_config(${PLUGIN_NAME}) \ No newline at end of file diff --git a/Miracast/MiracastPlayer/Generic/MiracastGstPlayer.cpp b/Miracast/MiracastPlayer/Generic/MiracastGstPlayer.cpp index cb03ca65..cf388331 100644 --- a/Miracast/MiracastPlayer/Generic/MiracastGstPlayer.cpp +++ b/Miracast/MiracastPlayer/Generic/MiracastGstPlayer.cpp @@ -391,7 +391,7 @@ void MiracastGstPlayer::onFirstVideoFrameCallback(GstElement* object, guint arg0 MIRACASTLOG_TRACE("Exiting..!!!"); } -void MiracastGstPlayer::notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, eM_PLAYER_REASON_CODE state_reason_code ) +void MiracastGstPlayer::notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, MiracastPlayerReasonCode state_reason_code ) { MIRACASTLOG_TRACE("Entering..!!!"); if ( nullptr != m_rtsp_reference_instance ) @@ -490,7 +490,7 @@ gboolean MiracastGstPlayer::appendPipelineBusMessage(GstBus * bus, GstMessage * g_free(info); GST_DEBUG_BIN_TO_DOT_FILE((GstBin *)self->m_append_pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "miracast_udpsrc2appsink_error"); gst_element_set_state(self->m_append_pipeline, GST_STATE_READY); - self->notifyPlaybackState(MIRACAST_GSTPLAYER_STATE_STOPPED,MIRACAST_PLAYER_REASON_CODE_GST_ERROR); + self->notifyPlaybackState(MIRACAST_GSTPLAYER_STATE_STOPPED,WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_GST_ERROR); } break; case GST_MESSAGE_STATE_CHANGED: @@ -551,7 +551,7 @@ gboolean MiracastGstPlayer::playbinPipelineBusMessage (GstBus * bus, GstMessage g_free(info); } GST_DEBUG_BIN_TO_DOT_FILE((GstBin *)self->m_playbin_pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "miracast_playbin2appSrc_error"); - self->notifyPlaybackState(MIRACAST_GSTPLAYER_STATE_STOPPED,MIRACAST_PLAYER_REASON_CODE_GST_ERROR); + self->notifyPlaybackState(MIRACAST_GSTPLAYER_STATE_STOPPED,WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_GST_ERROR); } break; case GST_MESSAGE_STATE_CHANGED: @@ -1042,4 +1042,9 @@ bool MiracastGstPlayer::stop() } MIRACASTLOG_TRACE("Exiting.."); return true; +} + +void MiracastGstPlayer::update_rtsp_capability_completion_status(bool state) +{ + /*NOP*/ } \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastGstPlayer.h b/Miracast/MiracastPlayer/MiracastGstPlayer.h index cb944c7b..769ebbda 100644 --- a/Miracast/MiracastPlayer/MiracastGstPlayer.h +++ b/Miracast/MiracastPlayer/MiracastGstPlayer.h @@ -63,6 +63,7 @@ class MiracastGstPlayer double getCurrentPosition(GstElement *pipeline = nullptr); bool get_player_statistics(); void print_pipeline_state(GstElement *pipeline = nullptr); + void update_rtsp_capability_completion_status(bool state); private: GstElement *m_append_pipeline{nullptr}; @@ -108,7 +109,7 @@ class MiracastGstPlayer bool createPipeline(); bool updateVideoSinkRectangle(void); static void onFirstVideoFrameCallback(GstElement* object, guint arg0, gpointer arg1,gpointer userdata); - void notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, eM_PLAYER_REASON_CODE state_reason_code = MIRACAST_PLAYER_REASON_CODE_SUCCESS ); + void notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, MiracastPlayerReasonCode state_reason_code = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_SUCCESS ); bool changePipelineState(GstElement* pipeline, GstState state) const; static void *playbackThread(void *ctx); diff --git a/Miracast/MiracastPlayer/MiracastPlayer.conf.in b/Miracast/MiracastPlayer/MiracastPlayer.conf.in index 05326042..394bc370 100644 --- a/Miracast/MiracastPlayer/MiracastPlayer.conf.in +++ b/Miracast/MiracastPlayer/MiracastPlayer.conf.in @@ -1,4 +1,12 @@ precondition = ["Platform"] callsign = "org.rdk.MiracastPlayer" -autostart = "false" +autostart = "@PLUGIN_MIRACASTPLAYER_AUTOSTART@" startuporder = "@PLUGIN_MIRACASTPLAYER_STARTUPORDER@" + +configuration = JSON() +rootobject = JSON() + +rootobject.add("mode", "@PLUGIN_MIRACASTPLAYER_MODE@") +rootobject.add("locator", "lib@PLUGIN_IMPLEMENTATION@.so") + +configuration.add("root", rootobject) \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastPlayer.config b/Miracast/MiracastPlayer/MiracastPlayer.config index 8e488c4a..33d2065a 100644 --- a/Miracast/MiracastPlayer/MiracastPlayer.config +++ b/Miracast/MiracastPlayer/MiracastPlayer.config @@ -1,7 +1,16 @@ -set (autostart false) +set (autostart ${PLUGIN_MIRACASTPLAYER_AUTOSTART}) set (preconditions Platform) set (callsign "org.rdk.MiracastPlayer") if(PLUGIN_MIRACASTPLAYER_STARTUPORDER) set (startuporder ${PLUGIN_MIRACASTPLAYER_STARTUPORDER}) endif() + +map() + key(root) + map() + kv(mode ${PLUGIN_MIRACASTPLAYER_MODE}) + kv(locator lib${PLUGIN_IMPLEMENTATION}.so) + end() +end() +ans(configuration) \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastPlayer.cpp b/Miracast/MiracastPlayer/MiracastPlayer.cpp index d0cdd772..d9bc3c6b 100644 --- a/Miracast/MiracastPlayer/MiracastPlayer.cpp +++ b/Miracast/MiracastPlayer/MiracastPlayer.cpp @@ -1,979 +1,195 @@ /** - * If not stated otherwise in this file or this component's LICENSE - * file the following copyright and licenses apply: - * - * Copyright 2023 RDK Management - * - * 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. - **/ +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ -#include -#include #include "MiracastPlayer.h" -#include -#include "UtilsIarm.h" -const short WPEFramework::Plugin::MiracastPlayer::API_VERSION_NUMBER_MAJOR = 1; -const short WPEFramework::Plugin::MiracastPlayer::API_VERSION_NUMBER_MINOR = 0; const string WPEFramework::Plugin::MiracastPlayer::SERVICE_NAME = "org.rdk.MiracastPlayer"; -static std::vector m_westerosEnvArgs; -using namespace std; - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 0 -#define API_VERSION_NUMBER_PATCH 1 - -#define SERVER_DETAILS "127.0.0.1:9998" -#define SYSTEM_CALLSIGN "org.rdk.System" -#define SYSTEM_CALLSIGN_VER SYSTEM_CALLSIGN ".1" -#define SECURITY_TOKEN_LEN_MAX 1024 -#define THUNDER_RPC_TIMEOUT 2000 - -/*Methods*/ -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_PLAY_REQUEST = "playRequest"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_STOP_REQUEST = "stopRequest"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_SET_PLAYER_STATE = "setPlayerState"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_SET_VIDEO_RECTANGLE = "setVideoRectangle"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_SET_VIDEO_FORMATS = "setVideoFormats"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_SET_AUDIO_FORMATS = "setAudioFormats"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_SET_RTSP_WAITTIMEOUT = "setRTSPWaitTimeOut"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_SET_LOG_LEVEL = "setLogging"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_SET_WESTEROS_ENVIRONMENT = "setWesterosEnvironment"; -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_PLAYER_UNSET_WESTEROS_ENVIRONMENT = "unsetWesterosEnvironment"; - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER -const string WPEFramework::Plugin::MiracastPlayer::METHOD_MIRACAST_TEST_NOTIFIER = "testNotifier"; -#endif - -#define EVT_ON_STATE_CHANGE "onStateChange" namespace WPEFramework { - namespace - { - static Plugin::Metadata metadata( - // Version (Major, Minor, Patch) - API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, - // Preconditions - {}, - // Terminations - {}, - // Controls - {}); - } - - namespace Plugin - { - SERVICE_REGISTRATION(MiracastPlayer, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - MiracastPlayer *MiracastPlayer::_instance = nullptr; - MiracastRTSPMsg *MiracastPlayer::m_miracast_rtsp_obj = nullptr; - - MiracastPlayer::MiracastPlayer() - : PluginHost::JSONRPC(), - m_isServiceInitialized(false), - m_isServiceEnabled(false) - { - LOGINFO("Entering..!!!"); - MiracastPlayer::_instance = this; - MIRACAST::logger_init("MiracastPlayer"); - Register(METHOD_MIRACAST_PLAYER_PLAY_REQUEST, &MiracastPlayer::playRequest, this); - Register(METHOD_MIRACAST_PLAYER_STOP_REQUEST, &MiracastPlayer::stopRequest, this); - Register(METHOD_MIRACAST_PLAYER_SET_PLAYER_STATE, &MiracastPlayer::setPlayerState, this); - Register(METHOD_MIRACAST_PLAYER_SET_VIDEO_RECTANGLE, &MiracastPlayer::setVideoRectangle, this); - Register(METHOD_MIRACAST_SET_VIDEO_FORMATS, &MiracastPlayer::setVideoFormats, this); - Register(METHOD_MIRACAST_SET_AUDIO_FORMATS, &MiracastPlayer::setAudioFormats, this); - Register(METHOD_MIRACAST_SET_RTSP_WAITTIMEOUT, &MiracastPlayer::setRTSPWaitTimeout, this); - Register(METHOD_MIRACAST_PLAYER_SET_LOG_LEVEL, &MiracastPlayer::setLogging, this); - Register(METHOD_MIRACAST_PLAYER_SET_WESTEROS_ENVIRONMENT, &MiracastPlayer::setWesterosEnvironment, this); - Register(METHOD_MIRACAST_PLAYER_UNSET_WESTEROS_ENVIRONMENT, &MiracastPlayer::unsetWesterosEnvironmentWrapper, this); - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER - Register(METHOD_MIRACAST_TEST_NOTIFIER, &MiracastPlayer::testNotifier, this); - m_isTestNotifierEnabled = false; -#endif /* ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER */ - LOGINFO("Exiting..!!!"); - } - - MiracastPlayer::~MiracastPlayer() - { - LOGINFO("Entering..!!!"); - MIRACAST::logger_deinit(); - LOGINFO("Exiting..!!!"); - } - - const string MiracastPlayer::Initialize(PluginHost::IShell *service) - { - string msg; - MIRACASTLOG_INFO("Entering..!!!"); - - if (!m_isServiceInitialized) - { - MiracastError ret_code = MIRACAST_OK; - m_miracast_rtsp_obj = MiracastRTSPMsg::getInstance(ret_code, this); - if (nullptr != m_miracast_rtsp_obj) - { - m_CurrentService = service; - m_GstPlayer = MiracastGstPlayer::getInstance(); - m_isServiceInitialized = true; - } - else - { - switch (ret_code) - { - case MIRACAST_RTSP_INIT_FAILED: - { - msg = "RTSP msg handler Init Failed"; - } - break; - default: - { - msg = "Unknown Error:Failed to obtain MiracastRTSPMsg Object"; - } - break; - } - } - } - - // On success return empty, to indicate there is no error text. - return msg; - } - - void MiracastPlayer::Deinitialize(PluginHost::IShell * /* service */) - { - MiracastPlayer::_instance = nullptr; - MIRACASTLOG_INFO("Entering..!!!"); - - if (m_isServiceInitialized) - { - MiracastRTSPMsg::destroyInstance(); - m_CurrentService = nullptr; - m_miracast_rtsp_obj = nullptr; - m_isServiceInitialized = false; - m_isServiceEnabled = false; - MIRACASTLOG_INFO("Done..!!!"); - } - MIRACASTLOG_INFO("Exiting..!!!"); - } - - string MiracastPlayer::Information() const - { - return (string("{\"service\": \"") + SERVICE_NAME + string("\"}")); - } - - uint32_t MiracastPlayer::playRequest(const JsonObject ¶meters, JsonObject &response) - { - RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; - bool success = false; - MIRACASTLOG_INFO("Entering..!!!"); - - if(parameters.HasLabel("device_parameters")) { - JsonObject device_parameters; - std::string source_dev_ip = "", - source_dev_mac = "", - source_dev_name = "", - sink_dev_ip = ""; - - device_parameters = parameters["device_parameters"].Object(); - - source_dev_ip = device_parameters["source_dev_ip"].String(); - source_dev_mac = device_parameters["source_dev_mac"].String(); - source_dev_name = device_parameters["source_dev_name"].String(); - sink_dev_ip = device_parameters["sink_dev_ip"].String(); - - strncpy( rtsp_hldr_msgq_data.source_dev_ip, source_dev_ip.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_ip)); - rtsp_hldr_msgq_data.source_dev_ip[sizeof(rtsp_hldr_msgq_data.source_dev_ip) - 1] = '\0'; - strncpy( rtsp_hldr_msgq_data.source_dev_mac, source_dev_mac.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_mac)); - rtsp_hldr_msgq_data.source_dev_mac[sizeof(rtsp_hldr_msgq_data.source_dev_mac) - 1] = '\0'; - strncpy( rtsp_hldr_msgq_data.source_dev_name, source_dev_name.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_name)); - rtsp_hldr_msgq_data.source_dev_name[sizeof(rtsp_hldr_msgq_data.source_dev_name) - 1] = '\0'; - strncpy( rtsp_hldr_msgq_data.sink_dev_ip, sink_dev_ip.c_str() , sizeof(rtsp_hldr_msgq_data.sink_dev_ip)); - rtsp_hldr_msgq_data.sink_dev_ip[sizeof(rtsp_hldr_msgq_data.sink_dev_ip) - 1] = '\0'; - - rtsp_hldr_msgq_data.state = RTSP_START_RECEIVE_MSGS; - success = true; - } - - if(parameters.HasLabel("video_rectangle")) { - JsonObject video_rectangle; - unsigned int startX = 0, - startY = 0, - width = 0, - height = 0; - - video_rectangle = parameters["video_rectangle"].Object(); - - startX = video_rectangle["X"].Number(); - startY = video_rectangle["Y"].Number(); - width = video_rectangle["W"].Number(); - height = video_rectangle["H"].Number(); - - if (( 0 < width ) && ( 0 < height )) - { - m_video_sink_rect.startX = startX; - m_video_sink_rect.startY = startY; - m_video_sink_rect.width = width; - m_video_sink_rect.height = height; - - rtsp_hldr_msgq_data.videorect = m_video_sink_rect; - - m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); - } - else{ - success = false; - } - } - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::stopRequest(const JsonObject ¶meters, JsonObject &response) - { - RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; - int64_t json_parsed_value; - eM_PLAYER_STOP_REASON_CODE stop_reason_code; - bool success = true; - - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfNumberParamNotFound(parameters, "reason_code"); - - getNumberParameter("reason_code", json_parsed_value); - stop_reason_code = static_cast(json_parsed_value); - - if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_EXIT == stop_reason_code ) - { - rtsp_hldr_msgq_data.stop_reason_code = MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_EXIT; - } - else if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_NEW_CONNECTION == stop_reason_code ) - { - rtsp_hldr_msgq_data.stop_reason_code = MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_NEW_CONNECTION; - } - else - { - success = false; - MIRACASTLOG_ERROR("!!! UNKNOWN STOP REASON CODE RECEIVED[%#04X] !!!",stop_reason_code); - response["message"] = "UNKNOWN STOP REASON CODE RECEIVED"; - } - - if ( success ) - { - rtsp_hldr_msgq_data.state = RTSP_TEARDOWN_FROM_SINK2SRC; - m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); - } - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::setPlayerState(const JsonObject ¶meters, JsonObject &response) - { - string player_state; - bool success = false; - MIRACASTLOG_INFO("Entering..!!!"); - if(parameters.HasLabel("state")) - { - RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; - getStringParameter("state", player_state); - success = true; - if (player_state == "STOP" || player_state == "stop") - { - rtsp_hldr_msgq_data.state = RTSP_TEARDOWN_FROM_SINK2SRC; - } - else if (player_state == "PLAY" || player_state == "play") - { - rtsp_hldr_msgq_data.state = RTSP_PLAY_FROM_SINK2SRC; - } - else if (player_state == "PAUSE" || player_state == "pause") - { - rtsp_hldr_msgq_data.state = RTSP_PAUSE_FROM_SINK2SRC; - } - else - { - MIRACASTLOG_ERROR("Invalid Player state[%s]",player_state.c_str()); - success = false; - } - - if (success) - { - m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); - } - } - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::setVideoRectangle(const JsonObject ¶meters, JsonObject &response) - { - RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; - bool success = false; - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfParamNotFound(parameters, "X"); - returnIfParamNotFound(parameters, "Y"); - returnIfParamNotFound(parameters, "W"); - returnIfParamNotFound(parameters, "H"); - - int startX = 0, - startY = 0, - width = 0, - height = 0; - - startX = parameters["X"].Number(); - startY = parameters["Y"].Number(); - width = parameters["W"].Number(); - height = parameters["H"].Number(); - - if (( 0 < width ) && ( 0 < height ) && - (( startX != m_video_sink_rect.startX ) || - ( startY != m_video_sink_rect.startY ) || - ( width != m_video_sink_rect.width ) || - ( height != m_video_sink_rect.height ))) - { - m_video_sink_rect.startX = startX; - m_video_sink_rect.startY = startY; - m_video_sink_rect.width = width; - m_video_sink_rect.height = height; - - rtsp_hldr_msgq_data.videorect = m_video_sink_rect; - rtsp_hldr_msgq_data.state = RTSP_UPDATE_VIDEO_RECT; - m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); - success = true; - } - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::setRTSPWaitTimeout(const JsonObject ¶meters, JsonObject &response) - { - bool success = false; - unsigned int request_time = 0, - response_time = 0; - - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfParamNotFound(parameters, "Request"); - returnIfParamNotFound(parameters, "Response"); - - request_time = parameters["Request"].Number(); - response_time = parameters["Response"].Number(); - - success = m_miracast_rtsp_obj->set_WFDRequestResponseTimeout( request_time , response_time ); - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::setLogging(const JsonObject ¶meters, JsonObject &response) - { - std::string log_level = ""; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - if (parameters.HasLabel("separate_logger")) - { - JsonObject separate_logger; - separate_logger = parameters["separate_logger"].Object(); - - if (separate_logger.HasLabel("status")) - { - std::string status = ""; - status = separate_logger["status"].String(); - - success = true; - - if (status == "ENABLE" || status == "enable") - { - std::string logfilename = ""; - logfilename = separate_logger["logfilename"].String(); - MIRACAST::enable_separate_logger(logfilename); - } - else if (status == "DISABLE" || status == "disable") - { - MIRACAST::disable_separate_logger(); - } - else - { - success = false; - } - } - } - - if (parameters.HasLabel("level")) - { - LogLevel level = FATAL_LEVEL; - getStringParameter("level", log_level); - success = true; - if (log_level == "FATAL" || log_level == "fatal") - { - level = FATAL_LEVEL; - } - else if (log_level == "ERROR" || log_level == "error") - { - level = ERROR_LEVEL; - } - else if (log_level == "WARNING" || log_level == "warning") - { - level = WARNING_LEVEL; - } - else if (log_level == "INFO" || log_level == "info") - { - level = INFO_LEVEL; - } - else if (log_level == "VERBOSE" || log_level == "verbose") - { - level = VERBOSE_LEVEL; - } - else if (log_level == "TRACE" || log_level == "trace") - { - level = TRACE_LEVEL; - } - else - { - success = false; - } - - if (success) - { - set_loglevel(level); - } - } - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastPlayer::setWesterosEnvironment(const JsonObject ¶meters, JsonObject &response) - { - std::string waylandDisplayName = ""; - bool success = false; - - if (!parameters.HasLabel("westerosArgs") || - parameters["westerosArgs"].Content() != WPEFramework::Core::JSON::Variant::type::ARRAY) - { - MIRACASTLOG_ERROR("No consent strings array in cache and Exiting..!!!"); - returnResponse(success); - } - - if (m_westerosEnvArgs.size() > 0) - { - unsetWesterosEnvironment(); - } - - JsonArray westerosArgs = parameters["westerosArgs"].Array(); - for (int i=0; i< westerosArgs.Length(); ++i) - { - if (westerosArgs[i].Content() != WPEFramework::Core::JSON::Variant::type::OBJECT) - { - MIRACASTLOG_ERROR("Arg string is not an object"); - continue; - } - - JsonObject envArg = westerosArgs[i].Object(); - if (!envArg.HasLabel("argName") || envArg["argName"].Content() != WPEFramework::Core::JSON::Variant::type::STRING || - !envArg.HasLabel("argValue") || envArg["argValue"].Content() != WPEFramework::Core::JSON::Variant::type::STRING) - { - std::string json; - envArg.ToString(json); - MIRACASTLOG_ERROR("Arguments are not valid [%s]", json.c_str()); - continue; - } - - std::string argName = envArg["argName"].String(); - std::string argValue = envArg["argValue"].String(); - - m_westerosEnvArgs.push_back(argName); - MIRACASTLOG_INFO("Configuring environment variable: %s=%s", argName.c_str(), argValue.c_str()); - if (0 == setenv(argName.c_str(), argValue.c_str(), 1)) - { - MIRACASTLOG_INFO("Success, setenv: [%s]=[%s] - strerrorno[%s]", argName.c_str(), argValue.c_str(), strerror(errno)); - } - else - { - MIRACASTLOG_ERROR("Failed, setenv for %s: [%s]", argName.c_str(), strerror(errno)); - } - - if ( "WAYLAND_DISPLAY" == argName ) - { - waylandDisplayName = std::move(argValue); - MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); - } - - char *value = getenv(argName.c_str()); - if (value != NULL) - { - MIRACASTLOG_INFO("Success, getenv: [%s]=[%s]", argName.c_str(), value); - } - else - { - MIRACASTLOG_ERROR("Failed to getenv variable: %s - strerrorno[%s]", argName.c_str(),strerror(errno)); - } - } - - if (!waylandDisplayName.empty()) - { - MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); - } - - std::string waylandDisplayOverrideName = MiracastCommon::parse_opt_flag("/opt/miracast_custom_westeros_name"); - if (!waylandDisplayOverrideName.empty()) - { - MIRACASTLOG_INFO("Wayland Display Name from Overrides: [%s]", waylandDisplayOverrideName.c_str()); - waylandDisplayName = std::move(waylandDisplayOverrideName); - } - - if (!waylandDisplayName.empty()) - { - if (0 == setenv("WAYLAND_DISPLAY", waylandDisplayName.c_str(), 1)) - { - MIRACASTLOG_INFO("Success, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); - success = true; - } - else - { - MIRACASTLOG_ERROR("Failed, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); - } - } - else - { - MIRACASTLOG_ERROR("Failed to get Wayland Display Name"); - success = false; - unsetWesterosEnvironment(); - } - - returnResponse(success); - } - - uint32_t MiracastPlayer::unsetWesterosEnvironmentWrapper(const JsonObject ¶meters, JsonObject &response) - { - unsetWesterosEnvironment(); - returnResponse(true); - } - - void MiracastPlayer::unsetWesterosEnvironment(void) - { - MIRACASTLOG_TRACE("Entering..!!!"); - for (const auto& argName : m_westerosEnvArgs) - { - if (0 == unsetenv(argName.c_str())) - { - MIRACASTLOG_INFO("Success, unsetenv for [%s] - strerrorno[%s]", argName.c_str(), strerror(errno)); - } - else - { - MIRACASTLOG_ERROR("Failed, unsetenv for [%s] - strerrorno[%s]", argName.c_str(), strerror(errno)); - } - } - m_westerosEnvArgs.clear(); - MIRACASTLOG_TRACE("Exiting..!!!"); - } - - /** - * @brief This method used to set the videoformats for Miracast. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastPlayer::setVideoFormats(const JsonObject ¶meters, JsonObject &response) - { - JsonArray h264_codecs; - RTSP_WFD_VIDEO_FMT_STRUCT st_video_fmt = {0}; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfParamNotFound(parameters, "native"); - returnIfBooleanParamNotFound(parameters, "display_mode_supported"); - returnIfParamNotFound(parameters, "h264_codecs"); - - h264_codecs = parameters["h264_codecs"].Array(); - if (0 == h264_codecs.Length()) - { - MIRACASTLOG_WARNING("Got empty list of h264_codecs"); - returnResponse(false); - } - getNumberParameter("native", st_video_fmt.native); - getBoolParameter("display_mode_supported", st_video_fmt.preferred_display_mode_supported); - - JsonArray::Iterator index(h264_codecs.Elements()); - int64_t json_parsed_value; - - while (index.Next() == true) - { - if (Core::JSON::Variant::type::OBJECT == index.Current().Content()) - { - JsonObject codecs = index.Current().Object(); - - returnIfParamNotFound(codecs, "profile"); - returnIfParamNotFound(codecs, "level"); - returnIfParamNotFound(codecs, "cea_mask"); - returnIfParamNotFound(codecs, "vesa_mask"); - returnIfParamNotFound(codecs, "hh_mask"); - - getNumberParameterObject(codecs, "profile", json_parsed_value); - st_video_fmt.st_h264_codecs.profile = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "level", json_parsed_value); - st_video_fmt.st_h264_codecs.level = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "cea_mask", json_parsed_value); - st_video_fmt.st_h264_codecs.cea_mask = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "vesa_mask", json_parsed_value); - st_video_fmt.st_h264_codecs.vesa_mask = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "hh_mask", json_parsed_value); - st_video_fmt.st_h264_codecs.hh_mask = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "latency", json_parsed_value); - st_video_fmt.st_h264_codecs.latency = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "min_slice", json_parsed_value); - st_video_fmt.st_h264_codecs.min_slice = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "slice_encode", json_parsed_value); - st_video_fmt.st_h264_codecs.slice_encode = static_cast(json_parsed_value); - - if (codecs.HasLabel("video_frame_skip_support")) - { - bool video_frame_skip_support; - video_frame_skip_support = codecs["video_frame_skip_support"].Boolean(); - st_video_fmt.st_h264_codecs.video_frame_skip_support = video_frame_skip_support; - } - - if (codecs.HasLabel("max_skip_intervals")) - { - uint8_t max_skip_intervals; - getNumberParameterObject(codecs, "max_skip_intervals", max_skip_intervals); - st_video_fmt.st_h264_codecs.max_skip_intervals = max_skip_intervals; - } - - if (codecs.HasLabel("video_frame_rate_change_support")) - { - bool video_frame_rate_change_support; - video_frame_rate_change_support = codecs["video_frame_rate_change_support"].Boolean(); - st_video_fmt.st_h264_codecs.video_frame_rate_change_support = video_frame_rate_change_support; - } - } - else - MIRACASTLOG_WARNING("Unexpected variant type"); - } - success = m_miracast_rtsp_obj->set_WFDVideoFormat(st_video_fmt); - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - /** - * @brief This method used to set the audioformats for Miracast. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastPlayer::setAudioFormats(const JsonObject ¶meters, JsonObject &response) - { - JsonArray audio_codecs; - RTSP_WFD_AUDIO_FMT_STRUCT st_audio_fmt = {}; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfParamNotFound(parameters, "audio_codecs"); - - audio_codecs = parameters["audio_codecs"].Array(); - if (0 == audio_codecs.Length()) - { - MIRACASTLOG_WARNING("Got empty list of audio_codecs"); - returnResponse(false); - } - - JsonArray::Iterator index(audio_codecs.Elements()); - int64_t json_parsed_value; - - while (index.Next() == true) - { - if (Core::JSON::Variant::type::OBJECT == index.Current().Content()) - { - JsonObject codecs = index.Current().Object(); - - returnIfParamNotFound(codecs, "audio_format"); - returnIfParamNotFound(codecs, "modes"); - returnIfParamNotFound(codecs, "latency"); - - getNumberParameterObject(codecs, "audio_format", json_parsed_value); - st_audio_fmt.audio_format = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "modes", json_parsed_value); - st_audio_fmt.modes = static_cast(json_parsed_value); - - getNumberParameterObject(codecs, "latency", json_parsed_value); - st_audio_fmt.latency = static_cast(json_parsed_value); - } - else - MIRACASTLOG_WARNING("Unexpected variant type"); - } - success = m_miracast_rtsp_obj->set_WFDAudioCodecs(st_audio_fmt); - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER - /** - * @brief This method used to stop the client connection. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastPlayer::testNotifier(const JsonObject ¶meters, JsonObject &response) - { - MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - string client_mac,client_name,state; - string status; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - if ( false == m_isTestNotifierEnabled ) - { - if (parameters.HasLabel("setStatus")) - { - getStringParameter("setStatus", status); - if (status == "ENABLED" || status == "enabled") - { - if ( MIRACAST_OK == m_miracast_rtsp_obj->create_TestNotifier()) - { - m_isTestNotifierEnabled = true; - success = true; - } - else - { - MIRACASTLOG_ERROR("Failed to enable TestNotifier"); - response["message"] = "Failed to enable TestNotifier"; - } - } - else if (status == "DISABLED" || status == "disabled") - { - MIRACASTLOG_ERROR("TestNotifier not yet enabled. Unable to Disable it"); - response["message"] = "TestNotifier not yet enabled. Unable to Disable"; - } - } - else - { - MIRACASTLOG_ERROR("TestNotifier not yet enabled"); - response["message"] = "TestNotifier not yet enabled"; - } - } - else - { - if (parameters.HasLabel("setStatus")) - { - getStringParameter("setStatus", status); - if (status == "DISABLED" || status == "disabled") - { - m_miracast_rtsp_obj->destroy_TestNotifier(); - success = true; - m_isTestNotifierEnabled = false; - } - else if (status == "ENABLED" || status == "enabled") - { - MIRACASTLOG_ERROR("TestNotifier already enabled"); - response["message"] = "TestNotifier already enabled"; - success = false; - } - else - { - MIRACASTLOG_ERROR("Invalid status"); - response["message"] = "Invalid status"; - } - return success; - } - - returnIfStringParamNotFound(parameters, "state"); - returnIfStringParamNotFound(parameters, "mac"); - returnIfStringParamNotFound(parameters, "name"); - - if (parameters.HasLabel("state")) - { - getStringParameter("state", state); - } - - if (parameters.HasLabel("mac")) - { - getStringParameter("mac", client_mac); - } - - if (parameters.HasLabel("name")) - { - getStringParameter("name", client_name); - } - - if (client_mac.empty()||client_name.empty()) - { - MIRACASTLOG_ERROR("Invalid MAC/Name has passed"); - response["message"] = "Invalid MAC/Name has passed"; - } - else - { - strncpy( stMsgQ.src_dev_name, client_name.c_str(), sizeof(stMsgQ.src_dev_name)); - stMsgQ.src_dev_name[sizeof(stMsgQ.src_dev_name) - 1] = '\0'; - strncpy( stMsgQ.src_dev_mac_addr, client_mac.c_str(), sizeof(stMsgQ.src_dev_mac_addr)); - stMsgQ.src_dev_mac_addr[sizeof(stMsgQ.src_dev_mac_addr) - 1] = '\0'; - - MIRACASTLOG_INFO("Given 'NAME, MAC and state' are[%s-%s-%s]", - client_name.c_str(), - client_mac.c_str(), - state.c_str()); - - success = true; - - if (state == "STATE_CHANGE" || state == "state_change") - { - int64_t json_parsed_value; - eMIRA_PLAYER_STATES player_state; - eM_PLAYER_REASON_CODE reason_code; - - returnIfNumberParamNotFound(parameters, "player_state"); - returnIfNumberParamNotFound(parameters, "reason_code"); - - getNumberParameter("player_state", json_parsed_value); - player_state = static_cast(json_parsed_value); - - getNumberParameter("reason_code", json_parsed_value); - reason_code = static_cast(json_parsed_value); - - MIRACASTLOG_INFO("Given 'player_state and reason_code' are[%#04X--%#04X]", - player_state, - reason_code); - - if (( MIRACAST_PLAYER_REASON_CODE_MAX_ERROR > reason_code ) && - ( MIRACAST_PLAYER_REASON_CODE_SUCCESS <= reason_code ) && - ( MIRACAST_PLAYER_STATE_PAUSED > player_state ) && - ( MIRACAST_PLAYER_STATE_IDLE <= player_state )) - { - stMsgQ.state = MIRACAST_PLAYER_TEST_NOTIFIER_STATE_CHANGED; - stMsgQ.player_state = player_state; - stMsgQ.reason_code = reason_code; - } - else - { - success = false; - MIRACASTLOG_ERROR("Invalid playerstate/reason_code passed"); - response["message"] = "Invalid playerstate/reason_code passed"; - } - } - else - { - success = false; - MIRACASTLOG_ERROR("Invalid state passed"); - response["message"] = "Invalid state passed"; - } - - if (success) - { - m_miracast_rtsp_obj->send_msgto_test_notifier_thread(stMsgQ); - } - } - } - - MIRACASTLOG_INFO("Exiting..!!!"); - - returnResponse(success); - } -#endif/*ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER*/ - - void MiracastPlayer::onStateChange(const std::string& client_mac, const std::string& client_name, eMIRA_PLAYER_STATES player_state, eM_PLAYER_REASON_CODE reason_code) - { - MIRACASTLOG_INFO("Entering..!!!"); - - JsonObject params; - params["mac"] = client_mac; - params["name"] = client_name; - params["state"] = stateDescription(player_state); - params["reason_code"] = std::to_string(reason_code); - params["reason"] = reasonDescription(reason_code); - if (0 == access("/opt/miracast_autoconnect", F_OK)) - { - char commandBuffer[768] = {0}; - snprintf( commandBuffer, - sizeof(commandBuffer), - "curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastService.1.updatePlayerState\", \"params\":{\"mac\": \"%s\",\"state\": \"%s\",\"reason_code\": %s}}' http://127.0.0.1:9998/jsonrpc &", - client_mac.c_str(), - stateDescription(player_state).c_str(), - std::to_string(reason_code).c_str()); - MIRACASTLOG_INFO("System Command [%s]",commandBuffer); - MiracastCommon::execute_SystemCommand( commandBuffer ); - - if ( MIRACAST_PLAYER_STATE_STOPPED == player_state ) - { - unsetWesterosEnvironment(); - } - } - else - { - sendNotify(EVT_ON_STATE_CHANGE, params); - } - MIRACASTLOG_INFO("Exiting..!!!"); - } - - std::string MiracastPlayer::stateDescription(eMIRA_PLAYER_STATES e) - { - switch (e) - { - case MIRACAST_PLAYER_STATE_IDLE: - return "IDLE"; - case MIRACAST_PLAYER_STATE_INITIATED: - return "INITIATED"; - case MIRACAST_PLAYER_STATE_INPROGRESS: - return "INPROGRESS"; - case MIRACAST_PLAYER_STATE_PLAYING: - return "PLAYING"; - case MIRACAST_PLAYER_STATE_STOPPED: - case MIRACAST_PLAYER_STATE_SELF_ABORT: - return "STOPPED"; - default: - return "Unimplemented state"; - } - } - - std::string MiracastPlayer::reasonDescription(eM_PLAYER_REASON_CODE e) - { - switch (e) - { - case MIRACAST_PLAYER_REASON_CODE_SUCCESS: - return "SUCCESS"; - case MIRACAST_PLAYER_REASON_CODE_APP_REQ_TO_STOP: - return "APP REQUESTED TO STOP."; - case MIRACAST_PLAYER_REASON_CODE_SRC_DEV_REQ_TO_STOP: - return "SRC DEVICE REQUESTED TO STOP."; - case MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR: - return "RTSP Failure."; - case MIRACAST_PLAYER_REASON_CODE_RTSP_TIMEOUT: - return "RTSP Timeout."; - case MIRACAST_PLAYER_REASON_CODE_RTSP_METHOD_NOT_SUPPORTED: - return "RTSP Method Not Supported."; - case MIRACAST_PLAYER_REASON_CODE_GST_ERROR: - return "GStreamer Failure."; - case MIRACAST_PLAYER_REASON_CODE_INT_FAILURE: - return "Internal Failure."; - case MIRACAST_PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ: - return "APP REQ TO STOP FOR NEW CONNECTION."; - default: - return "Unimplemented item."; - } - } - - } // namespace Plugin -} // namespace WPEFramework + namespace + { + static Plugin::Metadata metadata( + /* Version (Major, Minor, Patch) */ + MIRACAST_PLAYER_API_VERSION_NUMBER_MAJOR, MIRACAST_PLAYER_API_VERSION_NUMBER_MINOR, MIRACAST_PLAYER_API_VERSION_NUMBER_PATCH, + /* Preconditions */ + {}, + /* Terminations */ + {}, + /* Controls */ + {} + ); + } + + namespace Plugin + { + SERVICE_REGISTRATION(MiracastPlayer, MIRACAST_PLAYER_API_VERSION_NUMBER_MAJOR, MIRACAST_PLAYER_API_VERSION_NUMBER_MINOR, MIRACAST_PLAYER_API_VERSION_NUMBER_PATCH); + + MiracastPlayer* MiracastPlayer::_instance = nullptr; + + MiracastPlayer::MiracastPlayer() + : PluginHost::JSONRPC() + , mCurrentService(nullptr) + , mConnectionId(0) + , mMiracastPlayerImpl(nullptr) + , mMiracastPlayerNotification(this) + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer Constructor"))); + MiracastPlayer::_instance = this; + } + + MiracastPlayer::~MiracastPlayer() + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer Destructor"))); + MiracastPlayer::_instance = nullptr; + } + + const string MiracastPlayer::Initialize(PluginHost::IShell* service ) + { + string retStatus = ""; + + ASSERT(nullptr != service); + ASSERT(nullptr == mCurrentService); + ASSERT(nullptr == mMiracastPlayerImpl); + ASSERT(0 == mConnectionId); + + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Initialize: PID=%u"), getpid())); + + mCurrentService = service; + + if (nullptr != mCurrentService) + { + mCurrentService->AddRef(); + mCurrentService->Register(&mMiracastPlayerNotification); + + mMiracastPlayerImpl = mCurrentService->Root(mConnectionId, 5000, _T(PLUGIN_MIRACAST_PLAYER_IMPLEMENTATION_NAME)); + + if (nullptr != mMiracastPlayerImpl) + { + mConfigure = mMiracastPlayerImpl->QueryInterface(); + if (mConfigure) + { + uint32_t result = mConfigure->Configure(mCurrentService); + if(result != Core::ERROR_NONE) + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Initialize: Failed to Configure %s"), PLUGIN_MIRACAST_PLAYER_IMPLEMENTATION_NAME)); + retStatus = _T("MiracastPlayer plugin could not be initialised"); + } + else + { + /* Register for notifications */ + mMiracastPlayerImpl->Register(&mMiracastPlayerNotification); + /* Invoking Plugin API register to wpeframework */ + Exchange::JMiracastPlayer::Register(*this, mMiracastPlayerImpl); + } + mConfigure->Release(); + } + else + { + retStatus = _T("MiracastPlayer implementation did not provide a configuration interface"); + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Initialize: MiracastPlayerImpl[%s] does not provide a configuration interface"), PLUGIN_MIRACAST_PLAYER_IMPLEMENTATION_NAME)); + } + } + else + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Initialize: MiracastPlayerImpl[%s] object creation failed"), PLUGIN_MIRACAST_PLAYER_IMPLEMENTATION_NAME)); + retStatus = _T("MiracastPlayer plugin could not be initialised"); + } + } + else + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Initialize: service is not valid"))); + retStatus = _T("MiracastPlayer plugin could not be initialised"); + } + + if (0 != retStatus.length()) + { + Deinitialize(service); + } + + return retStatus; + } + + void MiracastPlayer::Deinitialize(PluginHost::IShell* service) + { + SYSLOG(Logging::Startup, (_T("MiracastPlayer::Deinitialize: PID=%u"), getpid())); + + ASSERT(mCurrentService == service); + ASSERT(0 == mConnectionId); + + if (nullptr != mMiracastPlayerImpl) + { + mMiracastPlayerImpl->Unregister(&mMiracastPlayerNotification); + Exchange::JMiracastPlayer::Unregister(*this); + + /* Stop processing: */ + RPC::IRemoteConnection* connection = nullptr; + if (nullptr != service) + { + connection = service->RemoteConnection(mConnectionId); + } + VARIABLE_IS_NOT_USED uint32_t result = mMiracastPlayerImpl->Release(); + + mMiracastPlayerImpl = nullptr; + + /* It should have been the last reference we are releasing, + * so it should endup in a DESTRUCTION_SUCCEEDED, if not we + * are leaking... */ + ASSERT(result == Core::ERROR_DESTRUCTION_SUCCEEDED); + + /* If this was running in a (container) process... */ + if (nullptr != connection) + { + /* Lets trigger the cleanup sequence for + * out-of-process code. Which will guard + * that unwilling processes, get shot if + * not stopped friendly :-) + */ + connection->Terminate(); + connection->Release(); + } + } + + if (nullptr != mCurrentService) + { + /* Make sure the Activated and Deactivated are no longer called before we start cleaning up.. */ + mCurrentService->Unregister(&mMiracastPlayerNotification); + mCurrentService->Release(); + mCurrentService = nullptr; + } + + mConnectionId = 0; + SYSLOG(Logging::Shutdown, (string(_T("MiracastPlayer de-initialised")))); + } + + string MiracastPlayer::Information() const + { + return("This MiracastPlayer Plugin Facilitates Miracast session like RTSP communication and GStreamer Playback"); + } + + void MiracastPlayer::Deactivated(RPC::IRemoteConnection* connection) + { + if (connection->Id() == mConnectionId) { + ASSERT(nullptr != mCurrentService); + LOGINFO("MiracastPlayer::Deactivated"); + Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(mCurrentService, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + } + } + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastPlayer.h b/Miracast/MiracastPlayer/MiracastPlayer.h index 57cad762..070b3ad6 100644 --- a/Miracast/MiracastPlayer/MiracastPlayer.h +++ b/Miracast/MiracastPlayer/MiracastPlayer.h @@ -1,116 +1,116 @@ /** - * If not stated otherwise in this file or this component's LICENSE - * file the following copyright and licenses apply: - * - * Copyright 2023 RDK Management - * - * 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. - **/ +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* 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. +**/ #pragma once -#include -#include - #include "Module.h" -#include "MiracastRTSPMsg.h" -#include "MiracastGstPlayer.h" +#include +#include +#include +#include +#include "UtilsLogging.h" +#include "tracing/Logging.h" +#include -using std::vector; namespace WPEFramework { namespace Plugin { - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class MiracastPlayer : public PluginHost::IPlugin, public PluginHost::JSONRPC, public MiracastPlayerNotifier + class MiracastPlayer : public PluginHost::IPlugin, public PluginHost::JSONRPC { - public: - // constants - static const short API_VERSION_NUMBER_MAJOR; - static const short API_VERSION_NUMBER_MINOR; - static const string SERVICE_NAME; - - // methods - static const string METHOD_MIRACAST_PLAYER_PLAY_REQUEST; - static const string METHOD_MIRACAST_PLAYER_STOP_REQUEST; - static const string METHOD_MIRACAST_PLAYER_SET_PLAYER_STATE; - static const string METHOD_MIRACAST_PLAYER_SET_VIDEO_RECTANGLE; - static const string METHOD_MIRACAST_SET_VIDEO_FORMATS; - static const string METHOD_MIRACAST_SET_AUDIO_FORMATS; - static const string METHOD_MIRACAST_SET_RTSP_WAITTIMEOUT; - static const string METHOD_MIRACAST_PLAYER_SET_LOG_LEVEL; - static const string METHOD_MIRACAST_PLAYER_SET_WESTEROS_ENVIRONMENT; - static const string METHOD_MIRACAST_PLAYER_UNSET_WESTEROS_ENVIRONMENT; - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER - static const string METHOD_MIRACAST_TEST_NOTIFIER; - uint32_t testNotifier(const JsonObject ¶meters, JsonObject &response); - bool m_isTestNotifierEnabled; -#endif /* ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER */ - - MiracastPlayer(); - virtual ~MiracastPlayer(); - virtual const string Initialize(PluginHost::IShell *shell) override; - virtual void Deinitialize(PluginHost::IShell *service) override; - virtual string Information() const override; - - void onStateChange(const std::string& client_mac, const std::string& client_name, eMIRA_PLAYER_STATES player_state, eM_PLAYER_REASON_CODE reason_code ) override; - - BEGIN_INTERFACE_MAP(MiracastPlayer) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - PluginHost::IShell *m_CurrentService; - static MiracastPlayer *_instance; - static MiracastRTSPMsg *m_miracast_rtsp_obj; - - private: - VIDEO_RECT_STRUCT m_video_sink_rect; - bool m_isServiceInitialized; - bool m_isServiceEnabled; - MiracastGstPlayer *m_GstPlayer; - MiracastRTSPMsg *m_rtsp_msg; - - uint32_t playRequest(const JsonObject ¶meters, JsonObject &response); - uint32_t stopRequest(const JsonObject ¶meters, JsonObject &response); - uint32_t setPlayerState(const JsonObject ¶meters, JsonObject &response); - uint32_t setVideoRectangle(const JsonObject ¶meters, JsonObject &response); - uint32_t setVideoFormats(const JsonObject ¶meters, JsonObject &response); - uint32_t setAudioFormats(const JsonObject ¶meters, JsonObject &response); - uint32_t setRTSPWaitTimeout(const JsonObject ¶meters, JsonObject &response); - uint32_t setLogging(const JsonObject ¶meters, JsonObject &response); - uint32_t setWesterosEnvironment(const JsonObject ¶meters, JsonObject &response); - uint32_t unsetWesterosEnvironmentWrapper(const JsonObject ¶meters, JsonObject &response); - void unsetWesterosEnvironment(void); - - std::string reasonDescription(eM_PLAYER_REASON_CODE); - std::string stateDescription(eMIRA_PLAYER_STATES); - - // We do not allow this plugin to be copied !! - MiracastPlayer(const MiracastPlayer &) = delete; - MiracastPlayer &operator=(const MiracastPlayer &) = delete; - }; + private: + class Notification : public RPC::IRemoteConnection::INotification, + public Exchange::IMiracastPlayer::INotification + { + private: + Notification() = delete; + Notification(const Notification&) = delete; + Notification& operator=(const Notification&) = delete; + + public: + explicit Notification(MiracastPlayer* parent) + : _parent(*parent) + { + ASSERT(parent != nullptr); + } + + virtual ~Notification() + { + } + + BEGIN_INTERFACE_MAP(Notification) + INTERFACE_ENTRY(Exchange::IMiracastPlayer::INotification) + INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) + END_INTERFACE_MAP + + void Activated(RPC::IRemoteConnection*) override + { + } + + void Deactivated(RPC::IRemoteConnection *connection) override + { + _parent.Deactivated(connection); + } + + void OnStateChange(const string &clientName , const string &clientMac , const Exchange::IMiracastPlayer::State playerState , const string &reasonCode , const Exchange::IMiracastPlayer::ReasonCode reasonDescription ) override + { + LOGINFO("=> clientName:[%s], clientMac:[%s], playerState:[%d], Reason:[%s]",clientName.c_str(), clientMac.c_str(), static_cast(playerState), reasonCode.c_str()); + Exchange::JMiracastPlayer::Event::OnStateChange(_parent, clientName, clientMac, playerState, reasonCode, reasonDescription); + } + + private: + MiracastPlayer& _parent; + }; // class Notification + + public: + MiracastPlayer(const MiracastPlayer&) = delete; + MiracastPlayer& operator=(const MiracastPlayer&) = delete; + + MiracastPlayer(); + virtual ~MiracastPlayer(); + + BEGIN_INTERFACE_MAP(MiracastPlayer) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_AGGREGATE(Exchange::IMiracastPlayer, mMiracastPlayerImpl) + END_INTERFACE_MAP + + /* IPlugin methods */ + const string Initialize(PluginHost::IShell* service) override; + void Deinitialize(PluginHost::IShell* service) override; + string Information() const override; + + private: + void Deactivated(RPC::IRemoteConnection* connection); + + private: /* members */ + PluginHost::IShell* mCurrentService{}; + uint32_t mConnectionId{}; + Exchange::IMiracastPlayer* mMiracastPlayerImpl{}; + Exchange::IConfiguration* mConfigure; + Core::Sink mMiracastPlayerNotification; + + public /* constants */: + static const string SERVICE_NAME; + + public /* members */: + static MiracastPlayer* _instance; + }; // class MiracastPlayer } // namespace Plugin -} // namespace WPEFramework +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastPlayerImplementation.cpp b/Miracast/MiracastPlayer/MiracastPlayerImplementation.cpp new file mode 100644 index 00000000..3739632f --- /dev/null +++ b/Miracast/MiracastPlayer/MiracastPlayerImplementation.cpp @@ -0,0 +1,580 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include + +#include "MiracastPlayerImplementation.h" + +#include "UtilsJsonRpc.h" +#include "UtilsIarm.h" + +#include "UtilsSynchroIarm.hpp" + +static std::vector m_envArgs; + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(MiracastPlayerImplementation, MIRACAST_PLAYER_API_VERSION_NUMBER_MAJOR, MIRACAST_PLAYER_API_VERSION_NUMBER_MINOR, MIRACAST_PLAYER_API_VERSION_NUMBER_PATCH); + MiracastPlayerImplementation *MiracastPlayerImplementation::_instance = nullptr; + MiracastRTSPMsg *MiracastPlayerImplementation::m_miracast_rtsp_obj = nullptr; + + MiracastPlayerImplementation::MiracastPlayerImplementation() + : _adminLock() + , mService(nullptr) + , m_isPluginInitialized(false) + { + LOGINFO("Call MiracastPlayerImplementation constructor"); + MiracastPlayerImplementation::_instance = this; + m_video_sink_rect = {0, 0, 1920, 1080}; // Default video rectangle + m_GstPlayer = nullptr; + MIRACAST::logger_init("MiracastPlayer"); + } + + MiracastPlayerImplementation::~MiracastPlayerImplementation() + { + LOGINFO("Call MiracastPlayerImplementation destructor"); + if (m_isPluginInitialized) + { + MiracastRTSPMsg::destroyInstance(); + m_miracast_rtsp_obj = nullptr; + m_GstPlayer = nullptr; + m_isPluginInitialized = false; + MIRACASTLOG_INFO("Done..!!!"); + } + if (nullptr != mService) + { + mService->Release(); + mService = nullptr; + } + MIRACAST::logger_deinit(); + MiracastPlayerImplementation::_instance = nullptr; + } + + /** + * Register a notification callback + */ + Core::hresult MiracastPlayerImplementation::Register(Exchange::IMiracastPlayer::INotification *notification) + { + MIRACASTLOG_TRACE("Entering ..."); + ASSERT(nullptr != notification); + + MIRACASTLOG_INFO("Register: notification = %p", notification); + _adminLock.Lock(); + + // Make sure we can't register the same notification callback multiple times + if (std::find(_miracastPlayerNotification.begin(), _miracastPlayerNotification.end(), notification) == _miracastPlayerNotification.end()) + { + _miracastPlayerNotification.push_back(notification); + notification->AddRef(); + } + else + { + MIRACASTLOG_ERROR("same notification is registered already"); + } + + _adminLock.Unlock(); + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + /** + * Unregister a notification callback + */ + Core::hresult MiracastPlayerImplementation::Unregister(Exchange::IMiracastPlayer::INotification *notification) + { + MIRACASTLOG_TRACE("Entering ..."); + Core::hresult status = Core::ERROR_GENERAL; + + ASSERT(nullptr != notification); + + _adminLock.Lock(); + + // we just unregister one notification once + auto itr = std::find(_miracastPlayerNotification.begin(), _miracastPlayerNotification.end(), notification); + if (itr != _miracastPlayerNotification.end()) + { + (*itr)->Release(); + MIRACASTLOG_INFO("Unregister notification"); + _miracastPlayerNotification.erase(itr); + status = Core::ERROR_NONE; + } + else + { + LOGERR("notification not found"); + } + + _adminLock.Unlock(); + MIRACASTLOG_TRACE("Exiting ..."); + return status; + } + + /* Helper methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastPlayerImplementation::unsetEnvArgumentsInternal(void) + { + MIRACASTLOG_TRACE("Entering ..."); + for (const auto& argName : m_envArgs) + { + if (0 == unsetenv(argName.c_str())) + { + MIRACASTLOG_INFO("Success, unsetenv for [%s] - strerrorno[%s]", argName.c_str(), strerror(errno)); + } + else + { + MIRACASTLOG_ERROR("Failed, unsetenv for [%s] - strerrorno[%s]", argName.c_str(), strerror(errno)); + } + } + m_envArgs.clear(); + MIRACASTLOG_TRACE("Exiting ..."); + } + + std::string MiracastPlayerImplementation::stateDescription(MiracastPlayerState e) + { + MIRACASTLOG_INFO("MiracastPlayer state [%#08X]", e); + switch (e) + { + case WPEFramework::Exchange::IMiracastPlayer::STATE_IDLE: + return "IDLE"; + case WPEFramework::Exchange::IMiracastPlayer::STATE_INITIATED: + return "INITIATED"; + case WPEFramework::Exchange::IMiracastPlayer::STATE_INPROGRESS: + return "INPROGRESS"; + case WPEFramework::Exchange::IMiracastPlayer::STATE_PLAYING: + return "PLAYING"; + case WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED: + return "STOPPED"; + default: + return "Unimplemented state"; + } + } + /* Helper and Internal methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + void MiracastPlayerImplementation::dispatchEvent(Event event, const ParamsType ¶ms) + { + Core::IWorkerPool::Instance().Submit(Job::Create(this, event, params)); + } + + void MiracastPlayerImplementation::Dispatch(Event event,const ParamsType& params) + { + _adminLock.Lock(); + + std::list::const_iterator index(_miracastPlayerNotification.begin()); + + switch (event) + { + case MIRACASTPLAYER_EVENT_ON_STATE_CHANGE: + { + string clientName; + string clientMac; + MiracastPlayerState playerState; + MiracastPlayerReasonCode reason; + string reasonCodeStr; + + if (const auto* tupleValue = boost::get>(¶ms)) + { + clientMac = std::get<0>(*tupleValue); + clientName = std::get<1>(*tupleValue); + playerState = std::get<2>(*tupleValue); + reason = std::get<3>(*tupleValue); + reasonCodeStr = std::to_string(reason); + MIRACASTLOG_INFO("Notifying PLAYER_STATE_CHANGE Event ClientMac[%s] ClientName[%s] PlayerState[%d] ReasonCode[%u]",clientMac.c_str(), clientName.c_str(), (int)playerState, (int)reason); + while (index != _miracastPlayerNotification.end()) + { + (*index)->OnStateChange(clientName , clientMac , playerState , reasonCodeStr, reason ); + ++index; + } + } + else + { + MIRACASTLOG_ERROR("MIRACASTPLAYER_EVENT_ON_STATE_CHANGE: Invalid parameters"); + } + } + break; + default: + MIRACASTLOG_WARNING("Event[%u] not handled", event); + break; + } + _adminLock.Unlock(); + } + + /* COMRPC Methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + uint32_t MiracastPlayerImplementation::Configure(PluginHost::IShell *service) + { + MIRACASTLOG_TRACE("Entering ..."); + uint32_t result = Core::ERROR_GENERAL; + + ASSERT(nullptr != service); + + mService = service; + + if (nullptr != mService) + { + mService->AddRef(); + if (!m_isPluginInitialized) + { + MiracastError ret_code = MIRACAST_OK; + m_miracast_rtsp_obj = MiracastRTSPMsg::getInstance(ret_code, this); + if (nullptr != m_miracast_rtsp_obj) + { + m_GstPlayer = MiracastGstPlayer::getInstance(); + m_isPluginInitialized = true; + result = Core::ERROR_NONE; + } + else + { + switch (ret_code) + { + case MIRACAST_RTSP_INIT_FAILED: + { + MIRACASTLOG_ERROR("RTSP handler Init Failed"); + } + break; + default: + { + MIRACASTLOG_ERROR("Unknown Error:Failed to obtain MiracastRTSPMsg Object"); + } + break; + } + } + } + } + MIRACASTLOG_TRACE("Exiting ..."); + return result; + } + + Core::hresult MiracastPlayerImplementation::PlayRequest(const DeviceParameters &deviceParam , const VideoRectangle videoRect , Result &result ) + { + RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; + bool isSuccessOrFailure = false; + MIRACASTLOG_TRACE("Entering ..."); + + strncpy( rtsp_hldr_msgq_data.source_dev_ip, deviceParam.sourceDeviceIP.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_ip)); + rtsp_hldr_msgq_data.source_dev_ip[sizeof(rtsp_hldr_msgq_data.source_dev_ip) - 1] = '\0'; + strncpy( rtsp_hldr_msgq_data.source_dev_mac, deviceParam.sourceDeviceMac.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_mac)); + rtsp_hldr_msgq_data.source_dev_mac[sizeof(rtsp_hldr_msgq_data.source_dev_mac) - 1] = '\0'; + strncpy( rtsp_hldr_msgq_data.source_dev_name, deviceParam.sourceDeviceName.c_str() , sizeof(rtsp_hldr_msgq_data.source_dev_name)); + rtsp_hldr_msgq_data.source_dev_name[sizeof(rtsp_hldr_msgq_data.source_dev_name) - 1] = '\0'; + strncpy( rtsp_hldr_msgq_data.sink_dev_ip, deviceParam.sinkDeviceIP.c_str() , sizeof(rtsp_hldr_msgq_data.sink_dev_ip)); + rtsp_hldr_msgq_data.sink_dev_ip[sizeof(rtsp_hldr_msgq_data.sink_dev_ip) - 1] = '\0'; + rtsp_hldr_msgq_data.state = RTSP_START_RECEIVE_MSGS; + + MIRACASTLOG_INFO("source_dev_ip[%s] source_dev_mac[%s] source_dev_name[%s] sink_dev_ip[%s] videoRect:[%d,%d,%d,%d]", + rtsp_hldr_msgq_data.source_dev_ip, rtsp_hldr_msgq_data.source_dev_mac, rtsp_hldr_msgq_data.source_dev_name, rtsp_hldr_msgq_data.sink_dev_ip, + videoRect.startX, videoRect.startY, videoRect.width, videoRect.height); + if (( 0 < videoRect.width ) && ( 0 < videoRect.height )) + { + m_video_sink_rect.startX = videoRect.startX; + m_video_sink_rect.startY = videoRect.startY; + m_video_sink_rect.width = videoRect.width; + m_video_sink_rect.height = videoRect.height; + + rtsp_hldr_msgq_data.videorect = m_video_sink_rect; + + m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + isSuccessOrFailure = true; + } + result.success = isSuccessOrFailure; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::StopRequest(const string &clientMac , const string &clientName , const int reasonCode , Result &result ) + { + RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; + bool isSuccessOrFailure = true; + MiracastPlayerStopReasonCode stopReasonCode = static_cast(reasonCode); + + MIRACASTLOG_TRACE("Entering ..."); + MIRACASTLOG_INFO("clientMac[%s] clientName[%s] reasonCode[%d]",clientMac.c_str(), clientName.c_str(), reasonCode); + switch (stopReasonCode) + { + case STOP_REASON_APP_REQ_FOR_EXIT: + case STOP_REASON_APP_REQ_FOR_NEW_CONNECTION: + { + rtsp_hldr_msgq_data.stop_reason_code = stopReasonCode; + + rtsp_hldr_msgq_data.state = RTSP_TEARDOWN_FROM_SINK2SRC; + m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + isSuccessOrFailure = true; + } + break; + default: + { + isSuccessOrFailure = false; + MIRACASTLOG_ERROR("!!! UNKNOWN STOP REASON CODE RECEIVED[%u] !!!",stopReasonCode); + result.message = "UNKNOWN STOP REASON CODE RECEIVED"; + } + break; + } + result.success = isSuccessOrFailure; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::SetVideoRectangle(const int startX , const int startY , const int width , const int height , Result &result ) + { + RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; + bool isSuccessOrFailure = false; + MIRACASTLOG_TRACE("Entering ..."); + + MIRACASTLOG_INFO("NewRect:[%d,%d,%d,%d] CurrentRect[%d,%d,%d,%d]", + startX, startY, width, height, + m_video_sink_rect.startX, m_video_sink_rect.startY,m_video_sink_rect.width, m_video_sink_rect.height); + + if (( 0 < width ) && ( 0 < height ) && + (( startX != m_video_sink_rect.startX ) || + ( startY != m_video_sink_rect.startY ) || + ( width != m_video_sink_rect.width ) || + ( height != m_video_sink_rect.height ))) + { + m_video_sink_rect.startX = startX; + m_video_sink_rect.startY = startY; + m_video_sink_rect.width = width; + m_video_sink_rect.height = height; + + rtsp_hldr_msgq_data.videorect = m_video_sink_rect; + rtsp_hldr_msgq_data.state = RTSP_UPDATE_VIDEO_RECT; + m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + isSuccessOrFailure = true; + } + else + { + MIRACASTLOG_ERROR("Invalid Video Rectangle Coords[%d,%d,%d,%d] or No Change in Coords[%d,%d,%d,%d]", + startX, startY, width, height, + m_video_sink_rect.startX, m_video_sink_rect.startY, m_video_sink_rect.width, m_video_sink_rect.height); + result.message = "Invalid Video Rectangle Coords"; + } + result.success = isSuccessOrFailure; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::SetWesterosEnvironment( IEnvArgumentsIterator * const westerosArgs , Result &result ) + { + std::string waylandDisplayName = ""; + bool isSuccessOrFailure = false; + if (westerosArgs) + { + Exchange::IMiracastPlayer::EnvArguments entry{}; + + while (westerosArgs->Next(entry) == true) + { + std::string argName = entry.argName; + std::string argValue = entry.argValue; + + m_envArgs.push_back(argName); + MIRACASTLOG_INFO("Configuring environment variable: %s=%s", argName.c_str(), argValue.c_str()); + if (0 == setenv(argName.c_str(), argValue.c_str(), 1)) + { + MIRACASTLOG_INFO("Success, setenv: [%s]=[%s] - strerrorno[%s]", argName.c_str(), argValue.c_str(), strerror(errno)); + } + else + { + MIRACASTLOG_ERROR("Failed, setenv for %s: [%s]", argName.c_str(), strerror(errno)); + } + + if ( "WAYLAND_DISPLAY" == argName ) + { + waylandDisplayName = std::move(argValue); + MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); + } + + char *value = getenv(argName.c_str()); + if (value != NULL) + { + MIRACASTLOG_INFO("Success, getenv: [%s]=[%s]", argName.c_str(), value); + } + else + { + MIRACASTLOG_ERROR("Failed to getenv variable: %s - strerrorno[%s]", argName.c_str(),strerror(errno)); + } + } + + if (!waylandDisplayName.empty()) + { + MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); + } + + std::string waylandDisplayOverrideName = MiracastCommon::parse_opt_flag("/opt/miracast_custom_westeros_name"); + if (!waylandDisplayOverrideName.empty()) + { + MIRACASTLOG_INFO("Wayland Display Name from Overrides: [%s]", waylandDisplayOverrideName.c_str()); + waylandDisplayName = std::move(waylandDisplayOverrideName); + } + + if (!waylandDisplayName.empty()) + { + if (0 == setenv("WAYLAND_DISPLAY", waylandDisplayName.c_str(), 1)) + { + MIRACASTLOG_INFO("Success, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); + isSuccessOrFailure = true; + } + else + { + MIRACASTLOG_ERROR("Failed, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); + } + } + else + { + MIRACASTLOG_ERROR("Failed, Missing Wayland Display Name"); + result.message = "Failed, Missing Wayland Display Name"; + isSuccessOrFailure = false; + unsetEnvArgumentsInternal(); + } + } + result.success = isSuccessOrFailure; + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::UnsetWesterosEnvironment(Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + unsetEnvArgumentsInternal(); + result.success = true; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::SetEnvArguments( IEnvArgumentsIterator * const envArgs , Result &result ) + { + std::string waylandDisplayName = ""; + bool isSuccessOrFailure = false; + if (envArgs) + { + Exchange::IMiracastPlayer::EnvArguments entry{}; + + while (envArgs->Next(entry) == true) + { + std::string argName = entry.argName; + std::string argValue = entry.argValue; + + m_envArgs.push_back(argName); + MIRACASTLOG_INFO("Configuring environment variable: %s=%s", argName.c_str(), argValue.c_str()); + if (0 == setenv(argName.c_str(), argValue.c_str(), 1)) + { + MIRACASTLOG_INFO("Success, setenv: [%s]=[%s] - strerrorno[%s]", argName.c_str(), argValue.c_str(), strerror(errno)); + } + else + { + MIRACASTLOG_ERROR("Failed, setenv for %s: [%s]", argName.c_str(), strerror(errno)); + } + + if ( "WAYLAND_DISPLAY" == argName ) + { + waylandDisplayName = std::move(argValue); + MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); + } + + char *value = getenv(argName.c_str()); + if (value != NULL) + { + MIRACASTLOG_INFO("Success, getenv: [%s]=[%s]", argName.c_str(), value); + } + else + { + MIRACASTLOG_ERROR("Failed to getenv variable: %s - strerrorno[%s]", argName.c_str(),strerror(errno)); + } + } + + if (!waylandDisplayName.empty()) + { + MIRACASTLOG_INFO("Wayland Display Name from App: [%s]", waylandDisplayName.c_str()); + } + + std::string waylandDisplayOverrideName = MiracastCommon::parse_opt_flag("/opt/miracast_custom_westeros_name"); + if (!waylandDisplayOverrideName.empty()) + { + MIRACASTLOG_INFO("Wayland Display Name from Overrides: [%s]", waylandDisplayOverrideName.c_str()); + waylandDisplayName = std::move(waylandDisplayOverrideName); + } + + if (!waylandDisplayName.empty()) + { + if (0 == setenv("WAYLAND_DISPLAY", waylandDisplayName.c_str(), 1)) + { + MIRACASTLOG_INFO("Success, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); + isSuccessOrFailure = true; + } + else + { + MIRACASTLOG_ERROR("Failed, setenv for WAYLAND_DISPLAY: [%s] - strerrorno[%s]", waylandDisplayName.c_str(), strerror(errno)); + } + } + else + { + MIRACASTLOG_ERROR("Failed, Missing Wayland Display Name"); + isSuccessOrFailure = false; + result.message = "Failed, Missing Wayland Display Name"; + unsetEnvArgumentsInternal(); + } + } + result.success = isSuccessOrFailure; + return Core::ERROR_NONE; + } + + Core::hresult MiracastPlayerImplementation::UnsetEnvArguments(Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + unsetEnvArgumentsInternal(); + result.success = true; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + /* COMRPC Methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* Events Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastPlayerImplementation::onStateChange(string client_mac, string client_name, MiracastPlayerState player_state, MiracastPlayerReasonCode reason_code ) + { + MIRACASTLOG_TRACE("Entering ..."); + + auto tupleParam = std::make_tuple(client_mac,client_name,player_state,reason_code); + + if (0 == access("/opt/miracast_autoconnect", F_OK)) + { + char commandBuffer[768] = {0}; + snprintf( commandBuffer, + sizeof(commandBuffer), + "curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastService.1.updatePlayerState\", \"params\":{\"mac\": \"%s\",\"state\": \"%s\",\"reason_code\": %s}}' http://127.0.0.1:9998/jsonrpc &", + client_mac.c_str(), + stateDescription(player_state).c_str(), + std::to_string(reason_code).c_str()); + MIRACASTLOG_INFO("System Command [%s]",commandBuffer); + MiracastCommon::execute_SystemCommand( commandBuffer ); + } + else + { + dispatchEvent(MIRACASTPLAYER_EVENT_ON_STATE_CHANGE, tupleParam); + } + + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED == player_state ) + { + unsetEnvArgumentsInternal(); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + /* Events End */ + /* ------------------------------------------------------------------------------------------------------- */ + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastPlayer/MiracastPlayerImplementation.h b/Miracast/MiracastPlayer/MiracastPlayerImplementation.h new file mode 100644 index 00000000..81af7bab --- /dev/null +++ b/Miracast/MiracastPlayer/MiracastPlayerImplementation.h @@ -0,0 +1,153 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* 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. +*/ + +#pragma once + +#include "Module.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "MiracastRTSPMsg.h" +#include "MiracastGstPlayer.h" + +#include "libIBus.h" + +using namespace WPEFramework; + +using MiracastPlayerState = WPEFramework::Exchange::IMiracastPlayer::State; +using MiracastPlayerReasonCode = WPEFramework::Exchange::IMiracastPlayer::ReasonCode; +using ParamsType = boost::variant>; + +namespace WPEFramework +{ + namespace Plugin + { + class MiracastPlayerImplementation : public Exchange::IMiracastPlayer, public Exchange::IConfiguration, public MiracastPlayerNotifier + { + public: + // We do not allow this plugin to be copied !! + MiracastPlayerImplementation(); + ~MiracastPlayerImplementation() override; + + static MiracastPlayerImplementation *instance(MiracastPlayerImplementation *MiracastPlayerImpl = nullptr); + + // We do not allow this plugin to be copied !! + MiracastPlayerImplementation(const MiracastPlayerImplementation &) = delete; + MiracastPlayerImplementation &operator=(const MiracastPlayerImplementation &) = delete; + + virtual void onStateChange(string client_mac, string client_name, MiracastPlayerState player_state, MiracastPlayerReasonCode reason_code ) override; + + BEGIN_INTERFACE_MAP(MiracastPlayerImplementation) + INTERFACE_ENTRY(Exchange::IMiracastPlayer) + INTERFACE_ENTRY(Exchange::IConfiguration) + END_INTERFACE_MAP + + public: + enum Event + { + MIRACASTPLAYER_EVENT_ON_STATE_CHANGE + }; + class EXTERNAL Job : public Core::IDispatch + { + protected: + Job(MiracastPlayerImplementation *MiracastPlayerImplementation, Event event, ParamsType ¶ms) + : _miracastPlayerImplementation(MiracastPlayerImplementation), _event(event), _params(params) + { + if (_miracastPlayerImplementation != nullptr) + { + _miracastPlayerImplementation->AddRef(); + } + } + + public: + Job() = delete; + Job(const Job &) = delete; + Job &operator=(const Job &) = delete; + ~Job() + { + if (_miracastPlayerImplementation != nullptr) + { + _miracastPlayerImplementation->Release(); + } + } + + public: + static Core::ProxyType Create(MiracastPlayerImplementation *miracastPlayerImplementation, Event event, ParamsType params) + { + #ifndef USE_THUNDER_R4 + return (Core::proxy_cast(Core::ProxyType::Create(miracastPlayerImplementation, event, params))); + #else + return (Core::ProxyType(Core::ProxyType::Create(miracastPlayerImplementation, event, params))); + #endif + } + virtual void Dispatch() + { + _miracastPlayerImplementation->Dispatch(_event, _params); + } + + private: + MiracastPlayerImplementation *_miracastPlayerImplementation; + const Event _event; + ParamsType _params; + }; + + + public: + uint32_t Configure(PluginHost::IShell* service) override; + + Core::hresult Register(Exchange::IMiracastPlayer::INotification *notification) override; + Core::hresult Unregister(Exchange::IMiracastPlayer::INotification *notification) override; + + Core::hresult PlayRequest(const DeviceParameters &deviceParam , const VideoRectangle videoRect , Result &result ) override; + Core::hresult StopRequest(const string &clientMac , const string &clientName , const int reasonCode , Result &result ) override; + Core::hresult SetVideoRectangle(const int startX , const int startY , const int width , const int height , Result &result ) override; + Core::hresult SetWesterosEnvironment( IEnvArgumentsIterator * const westerosArgs , Result &result ) override; + Core::hresult UnsetWesterosEnvironment(Result &result ) override; + Core::hresult SetEnvArguments( IEnvArgumentsIterator * const envArgs , Result &result ) override; + Core::hresult UnsetEnvArguments(Result &result ) override; + + private: + mutable Core::CriticalSection _adminLock; + PluginHost::IShell *mService; + std::list _miracastPlayerNotification; // List of registered notifications + PluginHost::IShell* _service; + MiracastGstPlayer *m_GstPlayer; + VIDEO_RECT_STRUCT m_video_sink_rect; + bool m_isPluginInitialized; + + void dispatchEvent(Event, const ParamsType ¶ms); + void Dispatch(Event event, const ParamsType ¶ms); + void unsetEnvArgumentsInternal(void); + std::string stateDescription(MiracastPlayerState e); + + public: + static MiracastPlayerImplementation *_instance; + static MiracastRTSPMsg *m_miracast_rtsp_obj; + + friend class Job; + }; + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.cpp b/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.cpp index 64306324..7e69f51d 100644 --- a/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.cpp +++ b/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.cpp @@ -21,15 +21,8 @@ #include MiracastRTSPMsg *MiracastRTSPMsg::m_rtsp_msg_obj{nullptr}; -static std::string empty_string = ""; -void RTSPMsgHandlerCallback(void *args); - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER -void MiracastPlayerTestNotifierThreadCallback(void *args); -#endif - -RTSP_MSG_FMT_TEMPLATE MiracastRTSPMsg::rtsp_msg_fmt_template[] = { +static RTSP_MSG_FMT_TEMPLATE m_rtsp_msg_fmt_template[] = { {RTSP_MSG_FMT_M1_RESPONSE, "RTSP/1.0 200 OK\r\nPublic: \"%s, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: %s\r\n\r\n"}, {RTSP_MSG_FMT_M2_REQUEST, "OPTIONS * RTSP/1.0\r\nRequire: %s\r\nCSeq: %s\r\n\r\n"}, {RTSP_MSG_FMT_M3_RESPONSE, "RTSP/1.0 200 OK\r\nContent-Length: %s\r\nContent-Type: text/parameters\r\nCSeq: %s\r\n\r\n%s"}, @@ -45,7 +38,7 @@ RTSP_MSG_FMT_TEMPLATE MiracastRTSPMsg::rtsp_msg_fmt_template[] = { {RTSP_MSG_FMT_REPORT_ERROR, "%sCSeq: %s\r\n\r\n"} }; -RTSP_PARSER_TEMPLATE MiracastRTSPMsg::rtsp_msg_parser_fields[] = { +static RTSP_PARSER_TEMPLATE m_rtsp_msg_parser_fields[] = { {RTSP_PARSER_FIELD_START, ""}, {RTSP_OPTIONS_REQ_FIELD, "OPTIONS * RTSP/1.0"}, @@ -85,9 +78,7 @@ RTSP_PARSER_TEMPLATE MiracastRTSPMsg::rtsp_msg_parser_fields[] = { {RTSP_PARSER_FIELD_END, ""}, }; -const int MiracastRTSPMsg::num_parse_fields = sizeof(rtsp_msg_parser_fields) / sizeof(rtsp_msg_parser_fields[0]); - -RTSP_ERRORCODE_TEMPLATE MiracastRTSPMsg::rtsp_msg_error_codes[] = { +static RTSP_ERRORCODE_TEMPLATE m_rtsp_msg_error_codes[] = { {RTSP_ERRORCODE_CONTINUE, "RTSP/1.0 100 Continue\r\n"}, {RTSP_ERRORCODE_OK, "RTSP/1.0 200 OK\r\n"}, @@ -141,6 +132,12 @@ RTSP_ERRORCODE_TEMPLATE MiracastRTSPMsg::rtsp_msg_error_codes[] = { {RTSP_ERRORCODE_OPTION_NOT_SUPPORTED, "RTSP/1.0 551 Option not supported\r\n"} }; +static const int m_num_parse_fields = sizeof(m_rtsp_msg_parser_fields) / sizeof(m_rtsp_msg_parser_fields[0]); + +static RTSP_WFD_VIDEO_FMT_STRUCT m_wfd_video_formats_st; +static RTSP_WFD_AUDIO_FMT_STRUCT m_wfd_audio_formats_st; + +void RTSPMsgHandlerCallback(void *args); MiracastRTSPMsg *MiracastRTSPMsg::getInstance(MiracastError &error_code , MiracastPlayerNotifier *player_notifier, MiracastThread *controller_thread_id) { @@ -277,10 +274,6 @@ MiracastRTSPMsg::~MiracastRTSPMsg() m_rtsp_msg_handler_thread = nullptr; } -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER - destroy_TestNotifier(); -#endif - Release_SocketAndEpollDescriptor(); } @@ -587,10 +580,10 @@ const char* MiracastRTSPMsg::get_RequestResponseFormat(RTSP_MSG_FMT_SINK2SRC for { MIRACASTLOG_TRACE("Entering..."); int index = static_cast(format_type) - static_cast(RTSP_MSG_FMT_M1_RESPONSE); - if (index >= 0 && index < static_cast(sizeof(rtsp_msg_fmt_template) / sizeof(rtsp_msg_fmt_template[0]))) + if (index >= 0 && index < static_cast(sizeof(m_rtsp_msg_fmt_template) / sizeof(m_rtsp_msg_fmt_template[0]))) { MIRACASTLOG_TRACE("Exiting..."); - return rtsp_msg_fmt_template[index].template_name; + return m_rtsp_msg_fmt_template[index].template_name; } MIRACASTLOG_TRACE("Exiting..."); return ""; @@ -600,10 +593,10 @@ const char* MiracastRTSPMsg::get_errorcode_string(RTSP_ERRORCODES error_code) { MIRACASTLOG_TRACE("Entering..."); int index = static_cast(error_code) - static_cast(RTSP_ERRORCODE_CONTINUE); - if (index >= 0 && index < static_cast(sizeof(rtsp_msg_error_codes) / sizeof(rtsp_msg_error_codes[0]))) + if (index >= 0 && index < static_cast(sizeof(m_rtsp_msg_error_codes) / sizeof(m_rtsp_msg_error_codes[0]))) { MIRACASTLOG_TRACE("Exiting..."); - return rtsp_msg_error_codes[index].string_fmt; + return m_rtsp_msg_error_codes[index].string_fmt; } MIRACASTLOG_TRACE("Exiting..."); return ""; @@ -613,10 +606,10 @@ const char* MiracastRTSPMsg::get_parser_field_by_index(RTSP_PARSER_FIELDS parse_ { MIRACASTLOG_TRACE("Entering..."); - if ( RTSP_PARSER_FIELD_START < parse_field && parse_field < num_parse_fields ) + if ( RTSP_PARSER_FIELD_START < parse_field && parse_field < m_num_parse_fields ) { - MIRACASTLOG_TRACE("Exiting with [%d][%s]...",parse_field,rtsp_msg_parser_fields[parse_field].string_fmt); - return rtsp_msg_parser_fields[parse_field].string_fmt; + MIRACASTLOG_TRACE("Exiting with [%d][%s]...",parse_field,m_rtsp_msg_parser_fields[parse_field].string_fmt); + return m_rtsp_msg_parser_fields[parse_field].string_fmt; } MIRACASTLOG_TRACE("Exiting..."); return ""; @@ -626,12 +619,12 @@ std::string MiracastRTSPMsg::get_parser_field_value(RTSP_PARSER_FIELDS parse_fie { MIRACASTLOG_TRACE("Entering [%#04X]...",parse_field); - if ( RTSP_PARSER_FIELD_START < parse_field && parse_field < num_parse_fields ) + if ( RTSP_PARSER_FIELD_START < parse_field && parse_field < m_num_parse_fields ) { - MIRACASTLOG_TRACE("parse_field[%#04X][%x]",parse_field,rtsp_msg_parser_fields[parse_field].member_variable_ptr); - if ( nullptr != rtsp_msg_parser_fields[parse_field].member_variable_ptr ){ + MIRACASTLOG_TRACE("parse_field[%#04X]",parse_field); + if ( nullptr != m_rtsp_msg_parser_fields[parse_field].member_variable_ptr ){ MIRACASTLOG_TRACE("Exiting..."); - return (this->*rtsp_msg_parser_fields[parse_field].member_variable_ptr).c_str(); + return (this->*m_rtsp_msg_parser_fields[parse_field].member_variable_ptr).c_str(); } } MIRACASTLOG_TRACE("Exiting..."); @@ -645,12 +638,12 @@ std::string MiracastRTSPMsg::get_parser_field_n_value_by_name(std::string reques while ( parse_field < RTSP_PARSER_FIELD_END ) { - if (0 == (request_field_name.compare(rtsp_msg_parser_fields[parse_field].string_fmt))) + if (0 == (request_field_name.compare(m_rtsp_msg_parser_fields[parse_field].string_fmt))) { MIRACASTLOG_TRACE("Inx[%d]request_field_name[%s]fmt[%s]", parse_field, request_field_name.c_str(), - rtsp_msg_parser_fields[parse_field].string_fmt); + m_rtsp_msg_parser_fields[parse_field].string_fmt); MIRACASTLOG_TRACE("Exiting..."); return get_parser_field_value(parse_field); } @@ -800,12 +793,13 @@ bool MiracastRTSPMsg::IsValidSequenceNumber(std::string& received_seq_num) return ret; } -void MiracastRTSPMsg::set_state( eMIRA_PLAYER_STATES state , bool send_notification , eM_PLAYER_REASON_CODE reason_code ) +void MiracastRTSPMsg::set_state( MiracastPlayerState state , bool send_notification , MiracastPlayerReasonCode reason_code ) { MIRACASTLOG_INFO("Entering [%d]notify[%u]reason[%u]...",state,send_notification,reason_code); m_current_state = state; - if (( MIRACAST_PLAYER_STATE_STOPPED == state )||( MIRACAST_PLAYER_STATE_SELF_ABORT == state )){ + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED == state ) + { stop_streaming(state); } @@ -824,7 +818,7 @@ void MiracastRTSPMsg::set_state( eMIRA_PLAYER_STATES state , bool send_notificat MIRACASTLOG_INFO("Exiting..."); } -eMIRA_PLAYER_STATES MiracastRTSPMsg::get_state(void) +MiracastPlayerState MiracastRTSPMsg::get_state(void) { return m_current_state; } @@ -1234,7 +1228,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_m1_msg_m2_send_request(std::string rt std::string m2_msg_req_sink2src = ""; MIRACASTLOG_INFO("M1 response sent"); - m2_msg_req_sink2src = generate_request_response_msg(RTSP_MSG_FMT_M2_REQUEST, empty_string, req_str); + m2_msg_req_sink2src = generate_request_response_msg(RTSP_MSG_FMT_M2_REQUEST, "", req_str); MIRACASTLOG_INFO("Sending the M2 request [%s]",m2_msg_req_sink2src.c_str()); status_code = send_rstp_msg(m_tcpSockfd, m2_msg_req_sink2src); @@ -1453,7 +1447,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_m4_response_back(std::string rtsp_m4_ } } - m4_msg_resp_sink2src = generate_request_response_msg( RTSP_MSG_FMT_M4_RESPONSE,seq_str,empty_string); + m4_msg_resp_sink2src = generate_request_response_msg( RTSP_MSG_FMT_M4_RESPONSE,seq_str,""); MIRACASTLOG_INFO("Sending the M4 response"); status_code = send_rstp_msg(m_tcpSockfd, m4_msg_resp_sink2src); @@ -1493,7 +1487,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_m5_msg_m6_send_request(std::string rt } } - m5_msg_resp_sink2src = generate_request_response_msg(RTSP_MSG_FMT_M5_RESPONSE, seq_str, empty_string); + m5_msg_resp_sink2src = generate_request_response_msg(RTSP_MSG_FMT_M5_RESPONSE, seq_str, ""); MIRACASTLOG_INFO("Sending the M5 response"); status_code = send_rstp_msg(m_tcpSockfd, m5_msg_resp_sink2src); @@ -1600,7 +1594,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_trigger_request_ack(std::string rtsp_ } else { - if ( MIRACAST_PLAYER_STATE_INPROGRESS == get_state()) + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_INPROGRESS == get_state()) { // It denotes response for M7 has received. status_code = RTSP_M1_M7_MSG_EXCHANGE_RECEIVED; @@ -1643,7 +1637,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_trigger_method_request(std::string rt else if (rtsp_msg_buffer.find(play_tag) != std::string::npos) { MIRACASTLOG_INFO("PLAY request from Source received"); - if ( MIRACAST_PLAYER_STATE_PLAYING == get_state()) + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_PLAYING == get_state()) { error_code = RTSP_ERRORCODE_METHOD_NOT_VALID; } @@ -1651,7 +1645,7 @@ RTSP_STATUS MiracastRTSPMsg::validate_rtsp_trigger_method_request(std::string rt else if (rtsp_msg_buffer.find(pause_tag) != std::string::npos) { MIRACASTLOG_INFO("PAUSE request from Source received"); - if ( MIRACAST_PLAYER_STATE_PAUSED == get_state()){ + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_PAUSED == get_state()){ error_code = RTSP_ERRORCODE_METHOD_NOT_VALID; } } @@ -1787,7 +1781,7 @@ RTSP_STATUS MiracastRTSPMsg::send_rtsp_reply_sink2src( RTSP_MSG_FMT_SINK2SRC req case RTSP_MSG_FMT_TRIGGER_METHODS_RESPONSE: { std::string rtsp_request_buffer = ""; - rtsp_request_buffer = generate_request_response_msg(req_fmt, received_seq_num , empty_string , error_code ); + rtsp_request_buffer = generate_request_response_msg(req_fmt, received_seq_num , "" , error_code ); MIRACASTLOG_INFO("Sending the RTSP Msg for [%#04X] format\n",req_fmt); status_code = send_rstp_msg(m_tcpSockfd, rtsp_request_buffer); @@ -1912,7 +1906,7 @@ MiracastError MiracastRTSPMsg::start_streaming( VIDEO_RECT_STRUCT video_rect ) if (!opt_flag_buffer.empty()) { MIRACASTLOG_INFO("#### updating state as PLAYING ####"); - set_state(MIRACAST_PLAYER_STATE_PLAYING , true ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_PLAYING , true ); } if (mcgstfile.is_open()) @@ -1954,16 +1948,15 @@ MiracastError MiracastRTSPMsg::start_streaming( VIDEO_RECT_STRUCT video_rect ) return MIRACAST_OK; } -MiracastError MiracastRTSPMsg::stop_streaming( eMIRA_PLAYER_STATES state ) +MiracastError MiracastRTSPMsg::stop_streaming( MiracastPlayerState state ) { MIRACASTLOG_TRACE("Entering..."); - if ((MIRACAST_PLAYER_STATE_STOPPED == state)|| - (MIRACAST_PLAYER_STATE_SELF_ABORT == state)) + if ( WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED == state ) { if (m_streaming_started) { - if (MIRACAST_PLAYER_STATE_SELF_ABORT == state) + if (false == m_rtsp_msg_hldr_running_state) { MiracastGstPlayer::destroyInstance(); MIRACASTLOG_INFO("MiracastGstPlayer instance destroyed..."); @@ -1998,18 +1991,19 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) RTSP_HLDR_MSGQ_STRUCT rtsp_message_data = {}; VIDEO_RECT_STRUCT video_rect_st = {0}; RTSP_STATUS status_code = RTSP_TIMEDOUT; - eM_PLAYER_REASON_CODE reason = MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR; + MiracastPlayerReasonCode reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_ERROR; std::string rtsp_msg_buffer; std::string client_mac = "", client_name = "", go_ip_addr = ""; - bool start_monitor_keep_alive_msg = false, - rtsp_msg_hldr_running_state = true; + bool start_monitor_keep_alive_msg = false; + + m_rtsp_msg_hldr_running_state = true; MIRACASTLOG_TRACE("Entering..."); - while ((nullptr != m_rtsp_msg_handler_thread)&&(true == rtsp_msg_hldr_running_state)) + while ((nullptr != m_rtsp_msg_handler_thread)&&(true == m_rtsp_msg_hldr_running_state)) { - set_state( MIRACAST_PLAYER_STATE_IDLE ); + set_state( WPEFramework::Exchange::IMiracastPlayer::STATE_IDLE ); MIRACASTLOG_TRACE("Waiting for Event ....."); m_rtsp_msg_handler_thread->receive_message(&rtsp_message_data, sizeof(rtsp_message_data), THREAD_RECV_MSG_INDEFINITE_WAIT); @@ -2018,9 +2012,8 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) if (RTSP_SELF_ABORT == rtsp_message_data.state) { MIRACASTLOG_INFO("RTSP_SELF_ABORT ACTION Received"); - rtsp_msg_hldr_running_state = false; - set_state(MIRACAST_PLAYER_STATE_STOPPED); - continue; + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED); + break; } if ( RTSP_START_RECEIVE_MSGS == rtsp_message_data.state ) @@ -2047,21 +2040,21 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) video_rect_st.width = rtsp_message_data.videorect.width; video_rect_st.height = rtsp_message_data.videorect.height; - set_state( MIRACAST_PLAYER_STATE_INITIATED , true ); + set_state( WPEFramework::Exchange::IMiracastPlayer::STATE_INITIATED , true ); if (MIRACAST_OK != initiate_TCP(rtsp_message_data.source_dev_ip)) { - set_state( MIRACAST_PLAYER_STATE_STOPPED , true , MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR ); + set_state( WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_ERROR ); continue; } } else { - set_state( MIRACAST_PLAYER_STATE_STOPPED , true , MIRACAST_PLAYER_REASON_CODE_INT_FAILURE ); + set_state( WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_INT_FAILURE ); MIRACASTLOG_ERROR("[%#04X] action received and not yet handled\n", rtsp_message_data.state); continue; } - set_state( MIRACAST_PLAYER_STATE_INPROGRESS , true ); + set_state( WPEFramework::Exchange::IMiracastPlayer::STATE_INPROGRESS , true ); set_wait_timeout(m_wfd_src_req_timeout); @@ -2097,7 +2090,7 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) status_code = RTSP_MSG_TEARDOWN_REQUEST; if ( RTSP_SELF_ABORT == rtsp_message_data.state ) { - rtsp_msg_hldr_running_state = false; + m_rtsp_msg_hldr_running_state = false; } rtsp_sink2src_request_msg_handling(RTSP_TEARDOWN_FROM_SINK2SRC); break; @@ -2117,50 +2110,52 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) start_monitor_keep_alive_msg = true; //start_streaming(video_rect_st); MIRACASTLOG_INFO("!!!! GstPlayer instance created, Waiting for first-frame !!!!"); + MiracastGstPlayer *MiracastGstPlayerObj = MiracastGstPlayer::getInstance(); + MiracastGstPlayerObj->update_rtsp_capability_completion_status( true ); } else { if (RTSP_INVALID_MSG_RECEIVED == status_code) { - reason = MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_ERROR; MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK INVALID RTSP MSG RECEIVED ####"); } else if (RTSP_MSG_FAILURE == status_code) { - reason = MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_ERROR; MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK RTSP SENT/RECV FAILED ####"); } else if ( RTSP_MSG_TEARDOWN_REQUEST == status_code ) { - if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_EXIT == rtsp_message_data.stop_reason_code ) + if ( STOP_REASON_APP_REQ_FOR_EXIT == rtsp_message_data.stop_reason_code ) { - reason = MIRACAST_PLAYER_REASON_CODE_APP_REQ_TO_STOP; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_APP_REQ_TO_STOP; MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-APP-EXIT APP REQUESTED TO STOP ON EXIT ####"); } - else if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_NEW_CONNECTION == rtsp_message_data.stop_reason_code ) + else if ( STOP_REASON_APP_REQ_FOR_NEW_CONNECTION == rtsp_message_data.stop_reason_code ) { - reason = MIRACAST_PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_NEW_SRC_DEV_CONNECT_REQ; MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-APP-STOP-ON-NEW-CONNECT APP REQUESTED TO STOP ON NEW CONNECTION ####"); } } else if ( RTSP_METHOD_NOT_SUPPORTED == status_code ) { - reason = MIRACAST_PLAYER_REASON_CODE_RTSP_METHOD_NOT_SUPPORTED; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_METHOD_NOT_SUPPORTED; MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK RTSP METHOD NOT SUPPORTED ####"); } else { - reason = MIRACAST_PLAYER_REASON_CODE_RTSP_TIMEOUT; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_RTSP_TIMEOUT; MIRACASTLOG_INFO("#### MCAST-TRIAGE-NOK RTSP RECV TIMEOUT ####"); } - set_state(MIRACAST_PLAYER_STATE_STOPPED , true , reason ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , reason ); } RTSP_STATUS socket_state; struct timespec start_time, current_time; int elapsed_seconds = 0; - reason = MIRACAST_PLAYER_REASON_CODE_SRC_DEV_REQ_TO_STOP; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_SRC_DEV_REQ_TO_STOP; clock_gettime(CLOCK_REALTIME, &start_time); @@ -2172,7 +2167,7 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) if (elapsed_seconds > m_wfd_src_session_timeout) { MIRACASTLOG_INFO("#### MCAST-TRIAGE-NOK RTSP M16 TIMEOUT[%d] ELAPSED[%d] ####",m_wfd_src_session_timeout,elapsed_seconds); - set_state(MIRACAST_PLAYER_STATE_STOPPED , true , reason ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , reason ); break; } @@ -2213,13 +2208,13 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) { MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK RTSP SENT/RECV FAILED ####"); } - set_state(MIRACAST_PLAYER_STATE_STOPPED , true , reason ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , reason ); break; } } else if (RTSP_MSG_FAILURE == socket_state) { - set_state(MIRACAST_PLAYER_STATE_STOPPED , true , reason ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , reason ); MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK RTSP SEND/RECV FAILED ####"); break; } @@ -2244,19 +2239,19 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) if (RTSP_SELF_ABORT == rtsp_message_data.state) { MIRACASTLOG_INFO("[RTSP_SELF_ABORT] Received"); - rtsp_msg_hldr_running_state = false; - set_state(MIRACAST_PLAYER_STATE_SELF_ABORT , true ); + m_rtsp_msg_hldr_running_state = false; + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true ); } else { if ( RTSP_PLAY_FROM_SINK2SRC == rtsp_message_data.state ) { - set_state(MIRACAST_PLAYER_STATE_PLAYING ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_PLAYING ); MIRACASTLOG_INFO("[RTSP_PLAY] ACTION Received"); } else if ( RTSP_PAUSE_FROM_SINK2SRC == rtsp_message_data.state ) { - set_state(MIRACAST_PLAYER_STATE_PAUSED ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_PAUSED ); MIRACASTLOG_INFO("[RTSP_PAUSE] ACTION Received"); } else if ( RTSP_TEARDOWN_FROM_SINK2SRC == rtsp_message_data.state ) @@ -2267,19 +2262,19 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) if ((RTSP_MSG_FAILURE == rtsp_sink2src_request_msg_handling(rtsp_message_data.state)) || (RTSP_TEARDOWN_FROM_SINK2SRC == rtsp_message_data.state)) { - reason = MIRACAST_PLAYER_REASON_CODE_SUCCESS; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_SUCCESS; start_monitor_keep_alive_msg = false; if (RTSP_TEARDOWN_FROM_SINK2SRC == rtsp_message_data.state) { - if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_EXIT == rtsp_message_data.stop_reason_code ) + if ( STOP_REASON_APP_REQ_FOR_EXIT == rtsp_message_data.stop_reason_code ) { - reason = MIRACAST_PLAYER_REASON_CODE_APP_REQ_TO_STOP; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_APP_REQ_TO_STOP; MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-APP-EXIT APP REQUESTED TO STOP ON EXIT ####"); } - else if ( MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_NEW_CONNECTION == rtsp_message_data.stop_reason_code ) + else if ( STOP_REASON_APP_REQ_FOR_NEW_CONNECTION == rtsp_message_data.stop_reason_code ) { - reason = MIRACAST_PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ; + reason = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_NEW_SRC_DEV_CONNECT_REQ; MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-APP-STOP-ON-NEW-CONNECT APP REQUESTED TO STOP ON NEW CONNECTION ####"); } else @@ -2291,7 +2286,7 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) { MIRACASTLOG_ERROR("!!! INVALID ACTION RECEIVED [%#04X] !!!",rtsp_message_data.state); } - set_state(MIRACAST_PLAYER_STATE_STOPPED , true , reason ); + set_state(WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED , true , reason ); } } break; @@ -2313,8 +2308,8 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) break; case RTSP_NOTIFY_GSTPLAYER_STATE: { - eMIRA_PLAYER_STATES state = MIRACAST_PLAYER_STATE_IDLE; - eM_PLAYER_REASON_CODE reason_code = MIRACAST_PLAYER_REASON_CODE_SUCCESS; + MiracastPlayerState state = WPEFramework::Exchange::IMiracastPlayer::STATE_IDLE; + MiracastPlayerReasonCode reason_code = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_SUCCESS; bool notifyGstPlayer = true; MIRACASTLOG_INFO("!!! RTSP_NOTIFY_GSTPLAYER_STATE[%#08X] !!!",rtsp_message_data.gst_player_state); @@ -2322,7 +2317,7 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) { case MIRACAST_GSTPLAYER_STATE_FIRST_VIDEO_FRAME_RECEIVED: { - state = MIRACAST_PLAYER_STATE_PLAYING; + state = WPEFramework::Exchange::IMiracastPlayer::STATE_PLAYING; MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-GST-PLAYING updating state as PLAYING ####"); std::string opt_flag_buffer = MiracastCommon::parse_opt_flag("/opt/miracast_skip_firstframe_callback"); if (!opt_flag_buffer.empty()) @@ -2333,7 +2328,7 @@ void MiracastRTSPMsg::RTSPMessageHandler_Thread(void *args) break; case MIRACAST_GSTPLAYER_STATE_STOPPED: { - state = MIRACAST_PLAYER_STATE_STOPPED; + state = WPEFramework::Exchange::IMiracastPlayer::STATE_STOPPED; reason_code = rtsp_message_data.state_reason_code; rtsp_sink2src_request_msg_handling(RTSP_TEARDOWN_FROM_SINK2SRC); start_monitor_keep_alive_msg = false; @@ -2383,121 +2378,4 @@ void RTSPMsgHandlerCallback(void *args) rtsp_msg_obj->RTSPMessageHandler_Thread(nullptr); } MIRACASTLOG_TRACE("Exiting..."); -} - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER -MiracastError MiracastRTSPMsg::create_TestNotifier(void) -{ - MiracastError error_code = MIRACAST_OK; - - m_test_notifier_thread = nullptr; - m_test_notifier_thread = new MiracastThread( MIRACAST_PLAYER_TEST_NOTIFIER_THREAD_NAME, - MIRACAST_PLAYER_TEST_NOTIFIER_THREAD_STACK, - MIRACAST_PLAYER_TEST_NOTIFIER_MSG_COUNT, - MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_SIZE, - reinterpret_cast(&MiracastPlayerTestNotifierThreadCallback), - this); - if ((nullptr == m_test_notifier_thread)|| - ( MIRACAST_OK != m_test_notifier_thread->start())) - { - if ( nullptr != m_test_notifier_thread ) - { - delete m_test_notifier_thread; - m_test_notifier_thread = nullptr; - } - error_code = MIRACAST_FAIL; - } - MIRACASTLOG_TRACE("Exiting..."); - return error_code; -} - -void MiracastRTSPMsg::destroy_TestNotifier() -{ - MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - - MIRACASTLOG_TRACE("Entering..."); - stMsgQ.state = MIRACAST_PLAYER_TEST_NOTIFIER_SHUTDOWN; - m_rtsp_msg_obj->send_msgto_test_notifier_thread(stMsgQ); - if (nullptr != m_test_notifier_thread) - { - delete m_test_notifier_thread; - m_test_notifier_thread = nullptr; - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastRTSPMsg::TestNotifier_Thread(void *args) -{ - MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - std::string device_name = "", - mac_address = "", - source_dev_ip = "", - sink_dev_ip = ""; - - MIRACASTLOG_TRACE("Entering..."); - - while ( nullptr != m_test_notifier_thread ) - { - memset( &stMsgQ , 0x00 , MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_SIZE ); - - MIRACASTLOG_TRACE("!!! WAITING FOR NEW ACTION !!!"); - - m_test_notifier_thread->receive_message(&stMsgQ, MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_SIZE , THREAD_RECV_MSG_INDEFINITE_WAIT); - - MIRACASTLOG_TRACE("!!! Received Action[%#08X] !!!", stMsgQ.state); - - device_name = stMsgQ.src_dev_name; - mac_address = stMsgQ.src_dev_mac_addr; - - switch (stMsgQ.state) - { - case MIRACAST_PLAYER_TEST_NOTIFIER_STATE_CHANGED: - { - MIRACASTLOG_TRACE("[MIRACAST_PLAYER_TEST_NOTIFIER_STATE_CHANGED]..."); - m_player_notify_handler->onStateChange( mac_address , - device_name , - stMsgQ.player_state, - stMsgQ.reason_code ); - } - break; - case MIRACAST_PLAYER_TEST_NOTIFIER_SHUTDOWN: - { - MIRACASTLOG_TRACE("[MIRACAST_PLAYER_TEST_NOTIFIER_SHUTDOWN]..."); - } - break; - default: - { - MIRACASTLOG_ERROR("[UNKNOWN STATE]..."); - } - break; - } - - if (MIRACAST_PLAYER_TEST_NOTIFIER_SHUTDOWN == stMsgQ.state) - { - break; - } - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastPlayerTestNotifierThreadCallback(void *args) -{ - MiracastRTSPMsg *miracast_rtsp_obj = (MiracastRTSPMsg *)args; - MIRACASTLOG_TRACE("Entering..."); - if ( nullptr != miracast_rtsp_obj ) - { - miracast_rtsp_obj->TestNotifier_Thread(nullptr); - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastRTSPMsg::send_msgto_test_notifier_thread(MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST stMsgQ) -{ - MIRACASTLOG_TRACE("Entering..."); - if (nullptr != m_test_notifier_thread) - { - m_test_notifier_thread->send_message(&stMsgQ, MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_SIZE); - } - MIRACASTLOG_TRACE("Exiting..."); -} -#endif /* ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER */ +} \ No newline at end of file diff --git a/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.h b/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.h index 822148e4..b391b8d5 100644 --- a/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.h +++ b/Miracast/MiracastPlayer/RTSP/MiracastRTSPMsg.h @@ -25,6 +25,11 @@ #include #include #include +#include + +using namespace WPEFramework; +using MiracastPlayerState = WPEFramework::Exchange::IMiracastPlayer::State; +using MiracastPlayerReasonCode = WPEFramework::Exchange::IMiracastPlayer::ReasonCode; #define MAX_EPOLL_EVENTS 64 #define RTSP_REQUEST_RECV_TIMEOUT ( 6 * ONE_SECOND_IN_MILLISEC ) @@ -45,7 +50,34 @@ typedef enum rtsp_status_e RTSP_KEEP_ALIVE_MSG_RECEIVED, RTSP_TIMEDOUT, RTSP_METHOD_NOT_SUPPORTED -} RTSP_STATUS; +} +RTSP_STATUS; + +typedef enum miracast_player_stop_reason_code_e +{ + STOP_REASON_APP_REQ_FOR_EXIT = 300, + STOP_REASON_APP_REQ_FOR_NEW_CONNECTION = 301 +} +MiracastPlayerStopReasonCode; + +typedef struct rtsp_hldr_msgq_st +{ + char source_dev_ip[24]; + char source_dev_mac[24]; + char sink_dev_ip[24]; + char source_dev_name[40]; + VIDEO_RECT_STRUCT videorect; + eCONTROLLER_FW_STATES state; + MiracastPlayerStopReasonCode stop_reason_code; + MiracastPlayerReasonCode state_reason_code; + eMIRA_GSTPLAYER_STATES gst_player_state; +} +RTSP_HLDR_MSGQ_STRUCT; + +#define RTSP_HANDLER_THREAD_NAME ("RTSP_MSG_HLDR") +#define RTSP_HANDLER_THREAD_STACK ( 512 * 1024) +#define RTSP_HANDLER_MSG_COUNT (2) +#define RTSP_HANDLER_MSGQ_SIZE (sizeof(RTSP_HLDR_MSGQ_STRUCT)) /* Default values*/ #define RTSP_DFLT_CONTENT_PROTECTION "none" @@ -387,161 +419,149 @@ typedef struct rtsp_wfd_audio_format_st } RTSP_WFD_AUDIO_FMT_STRUCT; +/** + * Abstract class for MiracastPlayer Notification. + */ +class MiracastPlayerNotifier +{ + public: + virtual void onStateChange(string client_mac, string client_name, MiracastPlayerState player_state, MiracastPlayerReasonCode reason_code ) = 0; +}; + class MiracastRTSPMsg { -public: - static MiracastRTSPMsg *getInstance(MiracastError &error_code , MiracastPlayerNotifier *player_notifier = nullptr , MiracastThread *controller_thread_id = nullptr); - static void destroyInstance(); - - bool IsWFDUnicastSupported(void); - bool set_WFDVideoFormat(RTSP_WFD_VIDEO_FMT_STRUCT st_video_fmt); - bool set_WFDAudioCodecs( RTSP_WFD_AUDIO_FMT_STRUCT st_audio_fmt ); - bool set_WFDClientRTPPorts(std::string client_rtp_ports); - bool set_WFDUIBCCapability(std::string uibc_caps); - bool set_WFDDisplayEDID(std::string wfd_display_edid); - bool set_WFDConnectorType(std::string wfd_connector_type); - bool set_WFDContentProtection(std::string content_protection); - bool set_WFDSecScreenSharing(std::string screen_sharing); - bool set_WFDPortraitDisplay(std::string portrait_display); - bool set_WFDSecRotation(std::string rotation); - bool set_WFDSecHWRotation(std::string hw_rotation); - bool set_WFDSecFrameRate(std::string framerate); - bool set_WFDPresentationURL(std::string URL); - bool set_WFDTransportProfile(std::string profile); - bool set_WFDStreamingPortNumber(std::string port_number); - bool set_WFDEnableDisableUnicast(bool enable_disable_unicast); - bool set_WFDSessionNumber(std::string session); - bool set_WFDRequestResponseTimeout( unsigned int request_timeout , unsigned int response_timeout ); - - eMIRA_PLAYER_STATES get_state(void); - - void send_msgto_rtsp_msg_hdler_thread(RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data); - MiracastError initiate_TCP(std::string goIP); - MiracastError start_streaming( VIDEO_RECT_STRUCT video_rect ); - MiracastError stop_streaming( eMIRA_PLAYER_STATES state ); - void RTSPMessageHandler_Thread(void *args); - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER - MiracastError create_TestNotifier(void); - void destroy_TestNotifier(); - void TestNotifier_Thread(void *args); - void send_msgto_test_notifier_thread(MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST stMsgQ); - MiracastThread *m_test_notifier_thread; -#endif /* ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER */ - - static std::string format_string(const char *fmt, const std::vector &args) - { - std::string result = fmt; - size_t arg_index = 0; - size_t arg_count = args.size(); - while (arg_index < arg_count) + public: + std::string m_wfd_content_protection; + std::string m_wfd_video_formats; + std::string m_wfd_audio_codecs; + std::string m_wfd_client_rtp_ports; + std::string m_wfd_uibc_capability; + std::string m_wfd_display_edid; + std::string m_wfd_connector_type; + + static MiracastRTSPMsg *getInstance(MiracastError &error_code , MiracastPlayerNotifier *player_notifier = nullptr , MiracastThread *controller_thread_id = nullptr); + static void destroyInstance(); + void send_msgto_rtsp_msg_hdler_thread(RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data); + void RTSPMessageHandler_Thread(void *args); + + private: + static MiracastRTSPMsg *m_rtsp_msg_obj; + MiracastThread *m_rtsp_msg_handler_thread; + MiracastThread *m_controller_thread; + MiracastPlayerNotifier *m_player_notify_handler; + + std::string m_connected_mac_addr; + std::string m_connected_device_name; + std::string m_wfd_sec_screensharing; + std::string m_wfd_sec_portrait_display; + std::string m_wfd_sec_rotation; + std::string m_wfd_sec_hw_rotation; + std::string m_wfd_sec_framerate; + std::string m_wfd_presentation_URL; + std::string m_wfd_transport_profile; + std::string m_wfd_streaming_port; + std::string m_wfd_session_number; + std::string m_current_sequence_number; + std::string m_src_dev_ip; + std::string m_sink_ip; + std::string m_getparameter_request; + + MiracastPlayerState m_current_state; + unsigned int m_wfd_src_req_timeout; + unsigned int m_wfd_src_res_timeout; + unsigned int m_current_wait_time_ms; + int m_tcpSockfd; + int m_epollfd; + int m_wfd_src_session_timeout; + + bool m_streaming_started; + bool m_rtsp_msg_hldr_running_state; + bool m_is_unicast; + bool m_getparameter_response_sent{false}; + + MiracastRTSPMsg(); + virtual ~MiracastRTSPMsg(); + MiracastRTSPMsg &operator=(const MiracastRTSPMsg &) = delete; + MiracastRTSPMsg(const MiracastRTSPMsg &) = delete; + + bool IsWFDUnicastSupported(void); + bool set_WFDVideoFormat(RTSP_WFD_VIDEO_FMT_STRUCT st_video_fmt); + bool set_WFDAudioCodecs( RTSP_WFD_AUDIO_FMT_STRUCT st_audio_fmt ); + bool set_WFDClientRTPPorts(std::string client_rtp_ports); + bool set_WFDUIBCCapability(std::string uibc_caps); + bool set_WFDDisplayEDID(std::string wfd_display_edid); + bool set_WFDConnectorType(std::string wfd_connector_type); + bool set_WFDContentProtection(std::string content_protection); + bool set_WFDSecScreenSharing(std::string screen_sharing); + bool set_WFDPortraitDisplay(std::string portrait_display); + bool set_WFDSecRotation(std::string rotation); + bool set_WFDSecHWRotation(std::string hw_rotation); + bool set_WFDSecFrameRate(std::string framerate); + bool set_WFDPresentationURL(std::string URL); + bool set_WFDTransportProfile(std::string profile); + bool set_WFDStreamingPortNumber(std::string port_number); + bool set_WFDEnableDisableUnicast(bool enable_disable_unicast); + bool set_WFDSessionNumber(std::string session); + bool set_WFDRequestResponseTimeout( unsigned int request_timeout , unsigned int response_timeout ); + + MiracastPlayerState get_state(void); + + MiracastError initiate_TCP(std::string goIP); + MiracastError start_streaming( VIDEO_RECT_STRUCT video_rect ); + MiracastError stop_streaming( MiracastPlayerState state ); + void set_state( MiracastPlayerState state , bool send_notification = false , MiracastPlayerReasonCode reason_code = WPEFramework::Exchange::IMiracastPlayer::REASON_CODE_SUCCESS ); + void store_srcsink_info( std::string client_name, std::string client_mac, std::string src_dev_ip, std::string sink_ip); + MiracastError create_RTSPThread(void); + void Release_SocketAndEpollDescriptor(void); + RTSP_STATUS validate_rtsp_m1_msg_m2_send_request(std::string rtsp_m1_msg_buffer); + RTSP_STATUS validate_rtsp_m2_request_ack(std::string rtsp_m1_response_ack_buffer); + RTSP_STATUS validate_rtsp_m3_response_back(std::string rtsp_m3_msg_buffer); + RTSP_STATUS validate_rtsp_m4_response_back(std::string rtsp_m4_msg_buffer); + RTSP_STATUS validate_rtsp_m5_msg_m6_send_request(std::string rtsp_m5_msg_buffer); + RTSP_STATUS validate_rtsp_m6_ack_m7_send_request(std::string rtsp_m6_ack_buffer); + RTSP_STATUS validate_rtsp_trigger_request_ack(std::string rtsp_trigger_req_ack_buffer , std::string received_seq_num ); + RTSP_STATUS validate_rtsp_post_m1_m7_xchange(std::string rtsp_post_m1_m7_xchange_buffer); + RTSP_STATUS rtsp_sink2src_request_msg_handling(eCONTROLLER_FW_STATES state); + RTSP_STATUS validate_rtsp_receive_buffer_handling(std::string rtsp_msg_buffer); + RTSP_STATUS validate_rtsp_generic_request_response( std::string rtsp_msg_buffer ); + RTSP_STATUS validate_rtsp_options_request( std::string rtsp_msg_buffer ); + RTSP_STATUS validate_rtsp_getparameter_request( std::string rtsp_msg_buffer ); + RTSP_STATUS validate_rtsp_setparameter_request( std::string rtsp_msg_buffer ); + RTSP_STATUS validate_rtsp_trigger_method_request(std::string rtsp_msg_buffer); + RTSP_STATUS send_rtsp_reply_sink2src( RTSP_MSG_FMT_SINK2SRC req_fmt , std::string received_seq_num = "" , RTSP_ERRORCODES error_code = RTSP_ERRORCODE_OK ); + const char *get_RequestResponseFormat(RTSP_MSG_FMT_SINK2SRC format_type); + const char* get_errorcode_string(RTSP_ERRORCODES error_code); + const char* get_parser_field_by_index(RTSP_PARSER_FIELDS parse_field); + std::string get_parser_field_value(RTSP_PARSER_FIELDS parse_field); + std::string get_parser_field_n_value_by_name(std::string request_field_name ); + std::string parse_received_parser_field_value(std::string rtsp_msg_buffer , RTSP_PARSER_FIELDS parse_field ); + std::string generate_request_response_msg(RTSP_MSG_FMT_SINK2SRC msg_fmt_needed, std::string received_session_no , std::string append_data1 , RTSP_ERRORCODES error_code = RTSP_ERRORCODE_OK ); + bool IsValidSequenceNumber(std::string& receivedSequenceNum); + std::string get_RequestSequenceNumber(void); + std::string generate_RequestSequenceNumber(void); + bool set_wait_timeout(unsigned int waittime_ms); + unsigned int get_wait_timeout(void); + RTSP_STATUS receive_buffer_timedOut(int sockfd, void *buffer, size_t buffer_len , unsigned int wait_time_ms = RTSP_REQUEST_RECV_TIMEOUT ); + bool wait_data_timeout(int m_Sockfd, unsigned int ms); + RTSP_STATUS send_rstp_msg(int sockfd, std::string rtsp_response_buffer); + MiracastError updateVideoRectangle( VIDEO_RECT_STRUCT videorect ); + int validateGetParameterContentLength(std::string& input); + + static std::string format_string(const char *fmt, const std::vector &args) { - size_t found = result.find("%s"); - if (found != std::string::npos) + std::string result = fmt; + size_t arg_index = 0; + size_t arg_count = args.size(); + while (arg_index < arg_count) { - result.replace(found, 2, args[arg_index]); + size_t found = result.find("%s"); + if (found != std::string::npos) + { + result.replace(found, 2, args[arg_index]); + } + ++arg_index; } - ++arg_index; - } - return result; - }; - -private: - static MiracastRTSPMsg *m_rtsp_msg_obj; - MiracastRTSPMsg(); - virtual ~MiracastRTSPMsg(); - MiracastRTSPMsg &operator=(const MiracastRTSPMsg &) = delete; - MiracastRTSPMsg(const MiracastRTSPMsg &) = delete; - - int m_tcpSockfd; - int m_epollfd; - unsigned int m_wfd_src_req_timeout; - unsigned int m_wfd_src_res_timeout; - unsigned int m_current_wait_time_ms; - int m_wfd_src_session_timeout; - eMIRA_PLAYER_STATES m_current_state; - - bool m_streaming_started; - - std::string m_connected_mac_addr; - std::string m_connected_device_name; - std::string m_wfd_video_formats; - std::string m_wfd_audio_codecs; - std::string m_wfd_client_rtp_ports; - std::string m_wfd_uibc_capability; - std::string m_wfd_display_edid; - std::string m_wfd_connector_type; - std::string m_wfd_content_protection; - std::string m_wfd_sec_screensharing; - std::string m_wfd_sec_portrait_display; - std::string m_wfd_sec_rotation; - std::string m_wfd_sec_hw_rotation; - std::string m_wfd_sec_framerate; - std::string m_wfd_presentation_URL; - std::string m_wfd_transport_profile; - std::string m_wfd_streaming_port; - bool m_is_unicast; - std::string m_wfd_session_number; - std::string m_current_sequence_number; - std::string m_src_dev_ip; - std::string m_sink_ip; - std::string m_getparameter_request; - bool m_getparameter_response_sent{false}; - RTSP_WFD_VIDEO_FMT_STRUCT m_wfd_video_formats_st; - RTSP_WFD_AUDIO_FMT_STRUCT m_wfd_audio_formats_st; - - static RTSP_MSG_FMT_TEMPLATE rtsp_msg_fmt_template[]; - static RTSP_ERRORCODE_TEMPLATE rtsp_msg_error_codes[]; - static RTSP_PARSER_TEMPLATE rtsp_msg_parser_fields[]; - static const int num_parse_fields; - - MiracastThread *m_rtsp_msg_handler_thread; - MiracastThread *m_controller_thread; - MiracastPlayerNotifier *m_player_notify_handler; - - void set_state( eMIRA_PLAYER_STATES state , bool send_notification = false , eM_PLAYER_REASON_CODE reason_code = MIRACAST_PLAYER_REASON_CODE_SUCCESS ); - void store_srcsink_info( std::string client_name, std::string client_mac, std::string src_dev_ip, std::string sink_ip); - - MiracastError create_RTSPThread(void); - void Release_SocketAndEpollDescriptor(void); - - RTSP_STATUS validate_rtsp_m1_msg_m2_send_request(std::string rtsp_m1_msg_buffer); - RTSP_STATUS validate_rtsp_m2_request_ack(std::string rtsp_m1_response_ack_buffer); - RTSP_STATUS validate_rtsp_m3_response_back(std::string rtsp_m3_msg_buffer); - RTSP_STATUS validate_rtsp_m4_response_back(std::string rtsp_m4_msg_buffer); - RTSP_STATUS validate_rtsp_m5_msg_m6_send_request(std::string rtsp_m5_msg_buffer); - RTSP_STATUS validate_rtsp_m6_ack_m7_send_request(std::string rtsp_m6_ack_buffer); - RTSP_STATUS validate_rtsp_trigger_request_ack(std::string rtsp_trigger_req_ack_buffer , std::string received_seq_num ); - RTSP_STATUS validate_rtsp_post_m1_m7_xchange(std::string rtsp_post_m1_m7_xchange_buffer); - RTSP_STATUS rtsp_sink2src_request_msg_handling(eCONTROLLER_FW_STATES state); - - RTSP_STATUS validate_rtsp_receive_buffer_handling(std::string rtsp_msg_buffer); - RTSP_STATUS validate_rtsp_generic_request_response( std::string rtsp_msg_buffer ); - RTSP_STATUS validate_rtsp_options_request( std::string rtsp_msg_buffer ); - RTSP_STATUS validate_rtsp_getparameter_request( std::string rtsp_msg_buffer ); - RTSP_STATUS validate_rtsp_setparameter_request( std::string rtsp_msg_buffer ); - RTSP_STATUS validate_rtsp_trigger_method_request(std::string rtsp_msg_buffer); - RTSP_STATUS send_rtsp_reply_sink2src( RTSP_MSG_FMT_SINK2SRC req_fmt , std::string received_seq_num = "" , RTSP_ERRORCODES error_code = RTSP_ERRORCODE_OK ); - - const char *get_RequestResponseFormat(RTSP_MSG_FMT_SINK2SRC format_type); - const char* get_errorcode_string(RTSP_ERRORCODES error_code); - const char* get_parser_field_by_index(RTSP_PARSER_FIELDS parse_field); - std::string get_parser_field_value(RTSP_PARSER_FIELDS parse_field); - std::string get_parser_field_n_value_by_name(std::string request_field_name ); - std::string parse_received_parser_field_value(std::string rtsp_msg_buffer , RTSP_PARSER_FIELDS parse_field ); - - std::string generate_request_response_msg(RTSP_MSG_FMT_SINK2SRC msg_fmt_needed, std::string received_session_no , std::string append_data1 , RTSP_ERRORCODES error_code = RTSP_ERRORCODE_OK ); - bool IsValidSequenceNumber(std::string& receivedSequenceNum); - std::string get_RequestSequenceNumber(void); - std::string generate_RequestSequenceNumber(void); - - bool set_wait_timeout(unsigned int waittime_ms); - unsigned int get_wait_timeout(void); - - RTSP_STATUS receive_buffer_timedOut(int sockfd, void *buffer, size_t buffer_len , unsigned int wait_time_ms = RTSP_REQUEST_RECV_TIMEOUT ); - bool wait_data_timeout(int m_Sockfd, unsigned int ms); - RTSP_STATUS send_rstp_msg(int sockfd, std::string rtsp_response_buffer); - MiracastError updateVideoRectangle( VIDEO_RECT_STRUCT videorect ); - int validateGetParameterContentLength(std::string& input); + return result; + }; }; #endif \ No newline at end of file diff --git a/Miracast/MiracastPlayer/Test/MiracastGstPlayer.cpp b/Miracast/MiracastPlayer/Test/MiracastGstPlayer.cpp index 355fb26f..284adfa9 100644 --- a/Miracast/MiracastPlayer/Test/MiracastGstPlayer.cpp +++ b/Miracast/MiracastPlayer/Test/MiracastGstPlayer.cpp @@ -30,6 +30,7 @@ #include "MiracastGstPlayer.h" MiracastGstPlayer *MiracastGstPlayer::m_GstPlayer{nullptr}; +static bool m_playbackThreadLoop = true; MiracastGstPlayer *MiracastGstPlayer::getInstance() { @@ -54,6 +55,7 @@ void MiracastGstPlayer::destroyInstance() MiracastGstPlayer::MiracastGstPlayer() { + gst_init(nullptr, nullptr); } MiracastGstPlayer::~MiracastGstPlayer() @@ -74,7 +76,20 @@ bool MiracastGstPlayer::launch(std::string& localip , std::string& streaming_por if ( nullptr != rtsp_instance ) { m_rtsp_reference_instance = rtsp_instance; - this->onFirstVideoFrameCallback(nullptr,0,0,this); + m_customQueueHandle = new MessageQueue(10,gstBufferReleaseCallback); + if (nullptr == m_customQueueHandle) + { + MIRACASTLOG_ERROR("Failed to create MessageQueue"); + return false; + } + if (0 != pthread_create(&m_playback_thread, nullptr, MiracastGstPlayer::playbackThread, this)) + { + MIRACASTLOG_ERROR("Failed to create playback thread"); + } + if (0 != pthread_create(&m_pushbuffer_handler_tid, nullptr, MiracastGstPlayer::pushbuffer_handler_thread, this)) + { + MIRACASTLOG_ERROR("Failed to create push buffer handler thread"); + } } return true; } @@ -91,8 +106,32 @@ bool MiracastGstPlayer::resume() bool MiracastGstPlayer::stop() { - destroyInstance(); - return true; + m_pushBufferLoop = false; + + if (m_customQueueHandle) + { + MIRACASTLOG_INFO("detaching MsgQ"); + m_customQueueHandle->detachQueue(); + + if(m_pushbuffer_handler_tid) + { + pthread_join(m_pushbuffer_handler_tid,nullptr); + m_pushbuffer_handler_tid = 0; + } + } + if (m_playback_thread) + { + m_playbackThreadLoop = false; + pthread_join(m_playback_thread,nullptr); + } + if (m_customQueueHandle) + { + MIRACASTLOG_INFO("Flushing MsgQ"); + delete m_customQueueHandle; + m_customQueueHandle = nullptr; + } + destroyInstance(); + return true; } void MiracastGstPlayer::onFirstVideoFrameCallback(GstElement* object, guint arg0, gpointer arg1,gpointer userdata) @@ -105,7 +144,7 @@ void MiracastGstPlayer::onFirstVideoFrameCallback(GstElement* object, guint arg0 MIRACASTLOG_TRACE("Exiting..!!!"); } -void MiracastGstPlayer::notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, eM_PLAYER_REASON_CODE state_reason_code ) +void MiracastGstPlayer::notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_state, MiracastPlayerReasonCode state_reason_code ) { MIRACASTLOG_TRACE("Entering..!!!"); if ( nullptr != m_rtsp_reference_instance ) @@ -120,3 +159,85 @@ void MiracastGstPlayer::notifyPlaybackState(eMIRA_GSTPLAYER_STATES gst_player_st } MIRACASTLOG_TRACE("Exiting..!!!"); } + +void MiracastGstPlayer::update_rtsp_capability_completion_status(bool state) +{ + MIRACASTLOG_TRACE("Entering..!!!"); + if (true == state) + { + MIRACASTLOG_INFO("RTSP Capability Status completed successfully"); + this->onFirstVideoFrameCallback(nullptr,0,0,this); + } + MIRACASTLOG_TRACE("Exiting..!!!"); +} + +void MiracastGstPlayer::gstBufferReleaseCallback(void* userParam) +{ + GstBuffer *gstBuffer; + gstBuffer = static_cast(userParam); + + if (nullptr != gstBuffer) + { + MIRACASTLOG_INFO("gstBuffer[%p]", static_cast(gstBuffer)); + gst_buffer_unref(gstBuffer); + gstBuffer = nullptr; + } +} + +void *MiracastGstPlayer::playbackThread(void *ctx) +{ + MiracastGstPlayer *self = (MiracastGstPlayer *)ctx; + MIRACASTLOG_TRACE("Entering..!!!"); + GstBuffer *new_buffer = nullptr; + while (self && m_playbackThreadLoop ) + { + usleep(50); + if (self->m_customQueueHandle) + { + new_buffer = gst_buffer_new_allocate(NULL, 128, NULL); + if (new_buffer) + { + MIRACASTLOG_INFO("new_buffer[%p]", static_cast(new_buffer)); + self->m_customQueueHandle->sendData(static_cast(new_buffer)); + } + else + { + MIRACASTLOG_ERROR("Failed to create new GstBuffer"); + } + } + } + MIRACASTLOG_TRACE("Exiting..!!!"); + pthread_exit(nullptr); +} + +void* MiracastGstPlayer::pushbuffer_handler_thread(void *ctx) +{ + MiracastGstPlayer *self = (MiracastGstPlayer *)ctx; + MIRACASTLOG_TRACE("Entering..!!!"); + void* buffer = nullptr; + GstBuffer *gstBuffer = nullptr; + if (self) + { + self->m_pushBufferLoop = true; + } + while (self && (self->m_pushBufferLoop)) + { + usleep(50); + buffer = nullptr; + self->m_customQueueHandle->ReceiveData(buffer); + + if (nullptr != buffer) + { + gstBuffer = static_cast(buffer); + MIRACASTLOG_INFO("Received buffer [%p]", static_cast(gstBuffer)); + gst_buffer_unref(gstBuffer); + gstBuffer = nullptr; + } + else + { + MIRACASTLOG_ERROR("Received buffer is NULL"); + } + } + MIRACASTLOG_TRACE("Exiting..!!!"); + pthread_exit(nullptr); +} \ No newline at end of file diff --git a/Miracast/MiracastService/CMakeLists.txt b/Miracast/MiracastService/CMakeLists.txt index e0977d4b..53d9c047 100644 --- a/Miracast/MiracastService/CMakeLists.txt +++ b/Miracast/MiracastService/CMakeLists.txt @@ -17,47 +17,82 @@ set(PLUGIN_NAME MiracastService) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) +set(PLUGIN_IMPLEMENTATION ${MODULE_NAME}Implementation) -set(PLUGIN_MIRACAST_STARTUPORDER "" CACHE STRING "To configure startup order of MiracastService plugin") +set(PLUGIN_MIRACASTSERVICE_STARTUPORDER "" CACHE STRING "To configure startup order of MiracastService plugin") +set(PLUGIN_MIRACASTSERVICE_AUTOSTART "false" CACHE STRING "Automatically start MiracastService plugin") + +add_definitions(-DMIRACAST_SERVICE_API_VERSION_NUMBER_MAJOR=2) +add_definitions(-DMIRACAST_SERVICE_API_VERSION_NUMBER_MINOR=0) +add_definitions(-DMIRACAST_SERVICE_API_VERSION_NUMBER_PATCH=0) + +set(MIRACAST_SERVICE_IMPLEMENTATION ${PLUGIN_NAME}Implementation) +add_definitions(-DPLUGIN_MIRACAST_SERVICE_IMPLEMENTATION_NAME="${MIRACAST_SERVICE_IMPLEMENTATION}") find_package(${NAMESPACE}Plugins REQUIRED) find_package(IARMBus) find_package(GLIB REQUIRED) - +find_package(${NAMESPACE}Plugins REQUIRED) +find_package(${NAMESPACE}Definitions REQUIRED) +find_package(CompileSettingsDebug CONFIG REQUIRED) find_package(WPEFrameworkSecurityUtil) -if(NOT WPEFRAMEWORK_SECURITYUTIL_FOUND) - add_definitions(-DSECURITY_TOKEN_ENABLED=0) -endif() find_library(GLIB_LIBRARY NAMES glib-2.0 ) -add_library(${MODULE_NAME} SHARED Module.cpp MiracastService.cpp ../common/MiracastCommon.cpp ../common/MiracastLogger.cpp MiracastController.cpp P2P/MiracastP2P.cpp) +if (USE_THUNDER_R4) + find_package(${NAMESPACE}COM REQUIRED) +else () + find_package(${NAMESPACE}Protocols REQUIRED) +endif (USE_THUNDER_R4) + +add_library(${MODULE_NAME} SHARED MiracastService.cpp Module.cpp) set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) + +target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) + +include_directories(../../helpers) + +target_link_libraries(${MODULE_NAME} PRIVATE CompileSettingsDebug::CompileSettingsDebug ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${NAMESPACE}Definitions::${NAMESPACE}Definitions) + +install(TARGETS ${MODULE_NAME} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) + +add_library(${PLUGIN_IMPLEMENTATION} SHARED MiracastServiceImplementation.cpp Module.cpp ../common/MiracastCommon.cpp ../common/MiracastLogger.cpp MiracastController.cpp P2P/MiracastP2P.cpp) + +target_link_libraries(${PLUGIN_IMPLEMENTATION} + PRIVATE + ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +set_target_properties(${PLUGIN_IMPLEMENTATION} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES) set_source_files_properties(MiracastService.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") -target_include_directories(${MODULE_NAME} PRIVATE ./) -target_include_directories(${MODULE_NAME} PRIVATE ../common) -target_include_directories(${MODULE_NAME} PRIVATE P2P) -target_include_directories(${MODULE_NAME} PRIVATE ../../helpers) -target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS}) +if (USE_THUNDER_R4) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}COM::${NAMESPACE}COM) +else () +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}Protocols::${NAMESPACE}Protocols) +endif (USE_THUNDER_R4) -#target_compile_options(${MODULE_NAME} PRIVATE -Wno-error -fpermissive -Os -pipe -g -feliminate-unused-debug-types -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed) -#target_compile_options(${MODULE_NAME} PRIVATE -DENABLE_MIRACAST_SERVICE_TEST_NOTIFIER) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ./) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ../common) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE P2P) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ../../helpers) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_INCLUDE_DIRS}) +target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${GLIB_INCLUDE_DIRS}) -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) -target_link_libraries(${MODULE_NAME} PRIVATE ${IARMBUS_LIBRARIES}) -target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES}) -target_link_libraries(${MODULE_NAME} PRIVATE -lpthread) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${NAMESPACE}Plugins::${NAMESPACE}Plugins) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_LIBRARIES}) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE ${GLIB_LIBRARIES}) +target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE -lpthread) if(NOT RDK_SERVICES_L1_TEST) - target_link_libraries(${MODULE_NAME} PRIVATE -lwpa_client) + target_link_libraries(${PLUGIN_IMPLEMENTATION} PRIVATE -lwpa_client) endif() -install(TARGETS ${MODULE_NAME} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) +install(TARGETS ${PLUGIN_IMPLEMENTATION} + DESTINATION lib/${STORAGE_DIRECTORY}/plugins) -write_config(${PLUGIN_NAME}) +write_config(${PLUGIN_NAME}) \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastController.cpp b/Miracast/MiracastService/MiracastController.cpp index e9590b76..2c7fae38 100644 --- a/Miracast/MiracastService/MiracastController.cpp +++ b/Miracast/MiracastService/MiracastController.cpp @@ -20,9 +20,6 @@ #include "MiracastController.h" void ControllerThreadCallback(void *args); -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER -void MiracastServiceTestNotifierThreadCallback(void *args); -#endif MiracastController *MiracastController::m_miracast_ctrl_obj{nullptr}; @@ -121,9 +118,6 @@ MiracastError MiracastController::destroy_ControllerFramework(void) { MIRACASTLOG_TRACE("Entering..."); -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - destroy_TestNotifier(); -#endif CONTROLLER_MSGQ_STRUCT controller_msgq_data = {0}; MIRACASTLOG_INFO("[MIRACAST_SERVICE_SHUTDOWN]"); controller_msgq_data.state = CONTROLLER_SELF_ABORT; @@ -597,7 +591,7 @@ MiracastError MiracastController::connect_device(std::string device_mac , std::s MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK P2P CONNECT FAILURE FOR DEVICE[%s - %s] ####",device_name.c_str(),device_mac.c_str()); if ( nullptr != m_notify_handler ) { - m_notify_handler->onMiracastServiceClientConnectionError( device_mac , device_name , MIRACAST_SERVICE_ERR_CODE_P2P_CONNECT_ERROR ); + m_notify_handler->onMiracastServiceClientConnectionError( device_mac , device_name , WPEFramework::Exchange::IMiracastService::REASON_CODE_P2P_CONNECT_FAILURE ); } } } @@ -944,7 +938,7 @@ void MiracastController::Controller_Thread(void *args) case CONTROLLER_GO_NEG_FAILURE: case CONTROLLER_GO_GROUP_FORMATION_FAILURE: { - eMIRACAST_SERVICE_ERR_CODE error_code = MIRACAST_SERVICE_ERR_CODE_GENERIC_FAILURE; + MiracastServiceReasonCode error_code = WPEFramework::Exchange::IMiracastService::REASON_CODE_GENERIC_FAILURE; if ( CONTROLLER_GO_GROUP_STARTED == controller_msgq_data.state ) { @@ -1061,7 +1055,7 @@ void MiracastController::Controller_Thread(void *args) { remove_ARPEntry(remote_address); remote_address.clear(); - MIRACASTLOG_ERROR("#### ARPING failed so clearing remote_address to report [MIRACAST_SERVICE_ERR_CODE_GENERIC_FAILURE] ####"); + MIRACASTLOG_ERROR("#### ARPING failed so clearing remote_address to report [WPEFramework::Exchange::IMiracastService::REASON_CODE_GENERIC_FAILURE] ####"); } } } @@ -1104,7 +1098,7 @@ void MiracastController::Controller_Thread(void *args) } else { - error_code = MIRACAST_SERVICE_ERR_CODE_GENERIC_FAILURE; + error_code = WPEFramework::Exchange::IMiracastService::REASON_CODE_GENERIC_FAILURE; session_restart_required = true; MIRACASTLOG_ERROR("!!!! Unable to get the Source Device IP and Terminating Group Here !!!!"); remove_P2PGroupInstance(); @@ -1114,12 +1108,12 @@ void MiracastController::Controller_Thread(void *args) { if ( CONTROLLER_GO_GROUP_FORMATION_FAILURE == controller_msgq_data.state ) { - error_code = MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_FORMATION_ERROR; + error_code = WPEFramework::Exchange::IMiracastService::REASON_CODE_P2P_GROUP_FORMATION_FAILURE; MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK CONTROLLER_GO_GROUP_FORMATION_FAILURE ####"); } else if ( CONTROLLER_GO_NEG_FAILURE == controller_msgq_data.state ) { - error_code = MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_NEGO_ERROR; + error_code = WPEFramework::Exchange::IMiracastService::REASON_CODE_P2P_GROUP_NEGOTIATION_FAILURE; MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK CONTROLLER_GO_NEG_FAILURE ####"); } @@ -1386,7 +1380,7 @@ void MiracastController::setP2PBackendDiscovery(bool is_enabled) MIRACASTLOG_TRACE("Exiting..."); } -void MiracastController::restart_session_discovery(std::string& mac_address) +void MiracastController::restart_session_discovery(const std::string& mac_address) { CONTROLLER_MSGQ_STRUCT controller_msgq_data = {0}; MIRACASTLOG_TRACE("Entering..."); @@ -1617,138 +1611,4 @@ void ControllerThreadCallback(void *args) miracast_ctrler_obj->Controller_Thread(nullptr); } MIRACASTLOG_TRACE("Exiting..."); -} - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - -MiracastError MiracastController::create_TestNotifier(void) -{ - MiracastError error_code = MIRACAST_OK; - - m_test_notifier_thread = nullptr; - MIRACASTLOG_TRACE("Entering..."); - m_test_notifier_thread = new MiracastThread( MIRACAST_SERVICE_TEST_NOTIFIER_THREAD_NAME, - MIRACAST_SERVICE_TEST_NOTIFIER_THREAD_STACK, - MIRACAST_SERVICE_TEST_NOTIFIER_MSG_COUNT, - MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_SIZE, - reinterpret_cast(&MiracastServiceTestNotifierThreadCallback), - this ); - if ((nullptr == m_test_notifier_thread)|| - ( MIRACAST_OK != m_test_notifier_thread->start())) - { - if ( nullptr != m_test_notifier_thread ) - { - delete m_test_notifier_thread; - m_test_notifier_thread = nullptr; - } - error_code = MIRACAST_FAIL; - } - MIRACASTLOG_TRACE("Exiting..."); - return error_code; -} - -void MiracastController::destroy_TestNotifier() -{ - MIRACASTLOG_TRACE("Entering..."); - MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - stMsgQ.state = MIRACAST_SERVICE_TEST_NOTIFIER_SHUTDOWN; - send_msgto_test_notifier_thread(stMsgQ); - if (nullptr != m_test_notifier_thread) - { - delete m_test_notifier_thread; - m_test_notifier_thread = nullptr; - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastController::TestNotifier_Thread(void *args) -{ - MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - std::string device_name = "", - mac_address = "", - source_dev_ip = "", - sink_dev_ip = ""; - - MIRACASTLOG_TRACE("Entering..."); - - while ( nullptr != m_test_notifier_thread ) - { - memset( &stMsgQ , 0x00 , MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_SIZE ); - - MIRACASTLOG_TRACE("!!! WAITING FOR NEW ACTION !!!\n"); - - m_test_notifier_thread->receive_message(&stMsgQ, MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_SIZE , THREAD_RECV_MSG_INDEFINITE_WAIT); - - MIRACASTLOG_TRACE("!!! Received Action[%#08X] !!!\n", stMsgQ.state); - - device_name = stMsgQ.src_dev_name; - mac_address = stMsgQ.src_dev_mac_addr; - - switch (stMsgQ.state) - { - case MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_REQUESTED: - { - MIRACASTLOG_TRACE("[MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_REQUESTED]..."); - m_notify_handler->onMiracastServiceClientConnectionRequest(mac_address, device_name); - } - break; - case MIRACAST_SERVICE_TEST_NOTIFIER_SHUTDOWN: - { - MIRACASTLOG_TRACE("[MIRACAST_SERVICE_TEST_NOTIFIER_SHUTDOWN]..."); - } - break; - case MIRACAST_SERVICE_TEST_NOTIFIER_LAUNCH_REQUESTED: - { - MIRACASTLOG_TRACE("[MIRACAST_SERVICE_TEST_NOTIFIER_LAUNCH_REQUESTED]..."); - source_dev_ip = stMsgQ.src_dev_ip_addr; - sink_dev_ip = stMsgQ.sink_ip_addr; - m_notify_handler->onMiracastServiceLaunchRequest( source_dev_ip, - mac_address, - device_name, - sink_dev_ip ); - } - break; - case MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_ERROR: - { - MIRACASTLOG_TRACE("[MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_ERROR]..."); - m_notify_handler->onMiracastServiceClientConnectionError( mac_address, - device_name , - stMsgQ.error_code ); - } - break; - default: - { - MIRACASTLOG_ERROR("[UNKNOWN STATE]..."); - } - break; - } - - if (MIRACAST_SERVICE_TEST_NOTIFIER_SHUTDOWN == stMsgQ.state) - { - break; - } - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastServiceTestNotifierThreadCallback(void *args) -{ - MiracastController *miracast_ctlr_obj = (MiracastController *)args; - MIRACASTLOG_TRACE("Entering [%#04X]...",miracast_ctlr_obj); - if ( nullptr != miracast_ctlr_obj ) - { - miracast_ctlr_obj->TestNotifier_Thread(nullptr); - } - MIRACASTLOG_TRACE("Exiting..."); -} - -void MiracastController::send_msgto_test_notifier_thread(MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST stMsgQ) -{ - MIRACASTLOG_TRACE("Entering..."); - if (nullptr != m_test_notifier_thread) - { - m_test_notifier_thread->send_message(&stMsgQ, MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_SIZE); - } - MIRACASTLOG_TRACE("Exiting..."); -} -#endif /* ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER */ +} \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastController.h b/Miracast/MiracastService/MiracastController.h index cd6c8d98..bde79154 100644 --- a/Miracast/MiracastService/MiracastController.h +++ b/Miracast/MiracastService/MiracastController.h @@ -37,13 +37,29 @@ #include #include "MiracastP2P.h" #include "MiracastLogger.h" +#include using namespace std; using namespace MIRACAST; +using namespace WPEFramework; +using MiracastServiceReasonCode = WPEFramework::Exchange::IMiracastService::ReasonCode; +using MiracastPlayerState = WPEFramework::Exchange::IMiracastService::PlayerState; #define THUNDER_REQ_THREAD_CLIENT_CONNECTION_WAITTIME (30) #define MAX_IFACE_NAME_LEN 16 +/** + * Abstract class for MiracastService Notification. + */ +class MiracastServiceNotifier +{ +public: + virtual void onMiracastServiceClientConnectionRequest(string client_mac, string client_name) = 0; + virtual void onMiracastServiceClientConnectionError(string client_mac, string client_name , MiracastServiceReasonCode reason_code ) = 0; + virtual void onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) = 0; + virtual void onStateChange(eMIRA_SERVICE_STATES state ) = 0; +}; + class MiracastController { public: @@ -69,17 +85,9 @@ class MiracastController void Controller_Thread(void *args); void notify_ConnectionRequest(std::string device_name,std::string device_mac); -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - MiracastThread *m_test_notifier_thread; - MiracastError create_TestNotifier(void); - void destroy_TestNotifier(); - void TestNotifier_Thread(void *args); - void send_msgto_test_notifier_thread( MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST stMsgQ ); -#endif /* ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER */ - MiracastError stop_discover_devices(bool isNotificationRequired = true); MiracastError set_WFDParameters(void); - void restart_session_discovery(std::string& mac_address); + void restart_session_discovery(const std::string& mac_address); void flush_current_session(void); void remove_P2PGroupInstance(void); void restart_session(bool start_discovering_enabled); @@ -89,7 +97,6 @@ class MiracastController std::string get_FriendlyName(void); void set_enable(bool is_enabled); void accept_client_connection(std::string is_accepted); - eMIRA_PLAYER_STATES m_ePlayer_state; void set_WFDSourceMACAddress(std::string MAC_Addr); void set_WFDSourceName(std::string device_name); diff --git a/Miracast/MiracastService/MiracastService.conf.in b/Miracast/MiracastService/MiracastService.conf.in index cc155cd7..1c6572b4 100644 --- a/Miracast/MiracastService/MiracastService.conf.in +++ b/Miracast/MiracastService/MiracastService.conf.in @@ -1,4 +1,12 @@ precondition = ["Platform"] callsign = "org.rdk.MiracastService" -autostart = "false" +autostart = "@PLUGIN_MIRACASTSERVICE_AUTOSTART@" startuporder = "@PLUGIN_MIRACASTSERVICE_STARTUPORDER@" + +configuration = JSON() +rootobject = JSON() + +rootobject.add("mode", "@PLUGIN_MIRACASTSERVICE_MODE@") +rootobject.add("locator", "lib@PLUGIN_IMPLEMENTATION@.so") + +configuration.add("root", rootobject) \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastService.config b/Miracast/MiracastService/MiracastService.config index fdadde07..703583b6 100644 --- a/Miracast/MiracastService/MiracastService.config +++ b/Miracast/MiracastService/MiracastService.config @@ -1,7 +1,16 @@ -set (autostart false) +set (autostart ${PLUGIN_MIRACASTSERVICE_AUTOSTART}) set (preconditions Platform) set (callsign "org.rdk.MiracastService") if(PLUGIN_MIRACASTSERVICE_STARTUPORDER) set (startuporder ${PLUGIN_MIRACASTSERVICE_STARTUPORDER}) endif() + +map() + key(root) + map() + kv(mode ${PLUGIN_MIRACASTSERVICE_MODE}) + kv(locator lib${PLUGIN_IMPLEMENTATION}.so) + end() +end() +ans(configuration) \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastService.cpp b/Miracast/MiracastService/MiracastService.cpp index 02de1f3d..c3d401b9 100644 --- a/Miracast/MiracastService/MiracastService.cpp +++ b/Miracast/MiracastService/MiracastService.cpp @@ -1,1605 +1,197 @@ /** - * If not stated otherwise in this file or this component's LICENSE - * file the following copyright and licenses apply: - * - * Copyright 2023 RDK Management - * - * 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. - **/ +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ -#include -#include -#if defined(SECURITY_TOKEN_ENABLED) && ((SECURITY_TOKEN_ENABLED == 0) || (SECURITY_TOKEN_ENABLED == false)) -#define GetSecurityToken(a, b) 0 -#define GetToken(a, b, c) 0 -#else -#include -#include -#endif #include "MiracastService.h" -#include "UtilsJsonRpc.h" -#include "UtilsIarm.h" -#include - -#define MIRACAST_DEVICE_PROPERTIES_FILE "/etc/device.properties" - -const short WPEFramework::Plugin::MiracastService::API_VERSION_NUMBER_MAJOR = 1; -const short WPEFramework::Plugin::MiracastService::API_VERSION_NUMBER_MINOR = 0; const string WPEFramework::Plugin::MiracastService::SERVICE_NAME = "org.rdk.MiracastService"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_ENABLE = "setEnable"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_GET_ENABLE = "getEnable"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_P2P_BACKEND_DISCOVERY = "setP2PBackendDiscovery"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_CLIENT_CONNECT = "acceptClientConnection"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_STOP_CLIENT_CONNECT = "stopClientConnection"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_UPDATE_PLAYER_STATE = "updatePlayerState"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_LOG_LEVEL = "setLogging"; - -#ifdef UNIT_TESTING -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_GET_STATUS = "getStatus"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_POWERSTATE = "setPowerState"; -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_SET_WIFISTATE = "setWiFiState"; -#endif /*UNIT_TESTING*/ - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER -const string WPEFramework::Plugin::MiracastService::METHOD_MIRACAST_TEST_NOTIFIER = "testNotifier"; -#endif - -using namespace std; - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 0 -#define API_VERSION_NUMBER_PATCH 8 - -#define SERVER_DETAILS "127.0.0.1:9998" -#define SYSTEM_CALLSIGN "org.rdk.System" -#define SYSTEM_CALLSIGN_VER SYSTEM_CALLSIGN ".1" -#define WIFI_CALLSIGN "org.rdk.Wifi" -#define WIFI_CALLSIGN_VER WIFI_CALLSIGN ".1" -#define SECURITY_TOKEN_LEN_MAX 1024 -#define THUNDER_RPC_TIMEOUT 2000 - -#define EVT_ON_CLIENT_CONNECTION_REQUEST "onClientConnectionRequest" -#define EVT_ON_CLIENT_CONNECTION_ERROR "onClientConnectionError" -#define EVT_ON_LAUNCH_REQUEST "onLaunchRequest" - -static PowerState m_powerState = WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY; -static bool m_IsTransitionFromDeepSleep = false; -static bool m_IsWiFiConnectingState = false; - namespace WPEFramework { - namespace - { - static Plugin::Metadata metadata( - // Version (Major, Minor, Patch) - API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, - // Preconditions - {}, - // Terminations - {}, - // Controls - {}); - } - - namespace Plugin - { - SERVICE_REGISTRATION(MiracastService, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - MiracastService *MiracastService::_instance = nullptr; - MiracastController *MiracastService::m_miracast_ctrler_obj = nullptr; + namespace + { + static Plugin::Metadata metadata( + /* Version (Major, Minor, Patch) */ + MIRACAST_SERVICE_API_VERSION_NUMBER_MAJOR, MIRACAST_SERVICE_API_VERSION_NUMBER_MINOR, MIRACAST_SERVICE_API_VERSION_NUMBER_PATCH, + /* Preconditions */ + {}, + /* Terminations */ + {}, + /* Controls */ + {} + ); + } + + namespace Plugin + { + SERVICE_REGISTRATION(MiracastService, MIRACAST_SERVICE_API_VERSION_NUMBER_MAJOR, MIRACAST_SERVICE_API_VERSION_NUMBER_MINOR, MIRACAST_SERVICE_API_VERSION_NUMBER_PATCH); + + MiracastService* MiracastService::_instance = nullptr; MiracastService::MiracastService() - : PluginHost::JSONRPC(), - m_isServiceInitialized(false), - m_isServiceEnabled(false), - m_eService_state(MIRACAST_SERVICE_STATE_IDLE), - _pwrMgrNotification(*this), - _registeredEventHandlers(false) + : PluginHost::JSONRPC() + , mCurrentService(nullptr) + , mConnectionId(0) + , mMiracastServiceImpl(nullptr) + , mMiracastServiceNotification(this) { - LOGINFO("Entering..!!!"); + SYSLOG(Logging::Startup, (_T("MiracastService Constructor"))); MiracastService::_instance = this; - MIRACAST::logger_init("MiracastService"); - - Register(METHOD_MIRACAST_SET_ENABLE, &MiracastService::setEnableWrapper, this); - Register(METHOD_MIRACAST_GET_ENABLE, &MiracastService::getEnable, this); - Register(METHOD_MIRACAST_SET_P2P_BACKEND_DISCOVERY, &MiracastService::setP2PBackendDiscovery, this); - Register(METHOD_MIRACAST_CLIENT_CONNECT, &MiracastService::acceptClientConnection, this); - Register(METHOD_MIRACAST_STOP_CLIENT_CONNECT, &MiracastService::stopClientConnection, this); - Register(METHOD_MIRACAST_SET_UPDATE_PLAYER_STATE, &MiracastService::updatePlayerState, this); - Register(METHOD_MIRACAST_SET_LOG_LEVEL, &MiracastService::setLogging, this); - #ifdef UNIT_TESTING - Register(METHOD_MIRACAST_GET_STATUS, &MiracastService::getStatus, this); - Register(METHOD_MIRACAST_SET_POWERSTATE, &MiracastService::setPowerStateWrapper, this); - Register(METHOD_MIRACAST_SET_WIFISTATE, &MiracastService::setWiFiStateWrapper, this); - #endif /*UNIT_TESTING*/ - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - m_isTestNotifierEnabled = false; - Register(METHOD_MIRACAST_TEST_NOTIFIER, &MiracastService::testNotifier, this); -#endif /* ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER */ - _engine = Core::ProxyType>::Create(); - _communicatorClient = Core::ProxyType::Create(Core::NodeId("/tmp/communicator"), Core::ProxyType(_engine)); - - LOGINFO("Exiting..!!!"); } - MiracastService::~MiracastService() - { - LOGINFO("Entering..!!!"); - if (nullptr != m_SystemPluginObj) - { - delete m_SystemPluginObj; - m_SystemPluginObj = nullptr; - } - if (nullptr != m_WiFiPluginObj) - { - delete m_WiFiPluginObj; - m_WiFiPluginObj = nullptr; - } - if (m_FriendlyNameMonitorTimerID) - { - g_source_remove(m_FriendlyNameMonitorTimerID); - m_FriendlyNameMonitorTimerID = 0; - } - remove_wifi_connection_state_timer(); - remove_miracast_connection_timer(); - Unregister(METHOD_MIRACAST_SET_ENABLE); - Unregister(METHOD_MIRACAST_GET_ENABLE); - Unregister(METHOD_MIRACAST_STOP_CLIENT_CONNECT); - Unregister(METHOD_MIRACAST_CLIENT_CONNECT); - Unregister(METHOD_MIRACAST_SET_UPDATE_PLAYER_STATE); - Unregister(METHOD_MIRACAST_SET_LOG_LEVEL); - MIRACAST::logger_deinit(); - LOGINFO("Exiting..!!!"); - } - - const void MiracastService::InitializePowerState() + MiracastService::~MiracastService() { - Core::hresult res = Core::ERROR_GENERAL; - PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - - ASSERT (_powerManagerPlugin); - if (_powerManagerPlugin){ - res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); - if (Core::ERROR_NONE == res) - { - setPowerState(pwrStateCur); - LOGINFO("MiracastService::Current state is (%d) \n",pwrStateCur); - } - } - } - - void MiracastService::DeinitializeIARM() - { - } - - void MiracastService::InitializePowerManager(PluginHost::IShell *service) - { - _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) - .withIShell(service) - .withRetryIntervalMS(200) - .withRetryCount(25) - .createInterface(); - registerEventHandlers(); + SYSLOG(Logging::Startup, (_T("MiracastService Destructor"))); + MiracastService::_instance = nullptr; } - void MiracastService::registerEventHandlers() + const string MiracastService::Initialize(PluginHost::IShell* service ) { - ASSERT (_powerManagerPlugin); - - if(!_registeredEventHandlers && _powerManagerPlugin) { - _registeredEventHandlers = true; - _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); - } - } - + string retStatus = ""; - void MiracastService:: onPowerModeChanged(const PowerState currentState, const PowerState newState) - { - if (nullptr == _instance) - { - LOGERR("#### MCAST-TRIAGE-NOK-PWR Miracast Service not enabled yet ####"); - return; - } - lock_guard lck(_instance->m_DiscoveryStateMutex); - _instance->setPowerState(newState); - } + ASSERT(nullptr != service); + ASSERT(nullptr == mCurrentService); + ASSERT(nullptr == mMiracastServiceImpl); + ASSERT(0 == mConnectionId); - // Thunder plugins communication - void MiracastService::getThunderPlugins() - { - MIRACASTLOG_INFO("Entering..!!!"); + SYSLOG(Logging::Startup, (_T("MiracastService::Initialize: PID=%u"), getpid())); - if (nullptr == m_SystemPluginObj) - { - string token; - // TODO: use interfaces and remove token - auto security = m_CurrentService->QueryInterfaceByCallsign("SecurityAgent"); - if (nullptr != security) - { - string payload = "http://localhost"; - if (security->CreateToken(static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) == Core::ERROR_NONE) - { - MIRACASTLOG_INFO("got security token\n"); - } - else - { - LOGERR("failed to get security token\n"); - } - security->Release(); - } - else - { - LOGERR("No security agent\n"); - } + mCurrentService = service; - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); - m_SystemPluginObj = new WPEFramework::JSONRPC::LinkType(_T(SYSTEM_CALLSIGN_VER), (_T("MiracastService")), false, query); - if (nullptr == m_SystemPluginObj) - { - LOGERR("JSONRPC: %s: initialization failed", SYSTEM_CALLSIGN_VER); - } - else - { - MIRACASTLOG_INFO("JSONRPC: %s: initialization ok", SYSTEM_CALLSIGN_VER); - } - - m_WiFiPluginObj = new WPEFramework::JSONRPC::LinkType(_T(WIFI_CALLSIGN_VER), (_T("MiracastService")), false, query); - if (nullptr == m_WiFiPluginObj) - { - LOGERR("JSONRPC: %s: initialization failed", WIFI_CALLSIGN_VER); - } - else - { - MIRACASTLOG_INFO("JSONRPC: %s: initialization ok", WIFI_CALLSIGN_VER); - } - } - MIRACASTLOG_INFO("Exiting..!!!"); - } - - const string MiracastService::Initialize(PluginHost::IShell *service) - { - string msg, - p2p_ctrl_iface = ""; - MIRACASTLOG_INFO("Entering..!!!"); - - if (!(envGetValue("WIFI_P2P_CTRL_INTERFACE", p2p_ctrl_iface))) - { - return "WIFI_P2P_CTRL_INTERFACE not configured in device properties file"; - } - - if (!m_isServiceInitialized) - { - MiracastError ret_code = MIRACAST_OK; - - InitializePowerManager(service); - InitializePowerState(); - - m_miracast_ctrler_obj = MiracastController::getInstance(ret_code, this,p2p_ctrl_iface); - if (nullptr != m_miracast_ctrler_obj) - { - m_CurrentService = service; - getThunderPlugins(); - // subscribe for event - if (nullptr != m_SystemPluginObj) - { - m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged", &MiracastService::onFriendlyNameUpdateHandler, this); - } - if (nullptr != m_WiFiPluginObj) - { - m_WiFiPluginObj->Subscribe(1000, "onWIFIStateChanged", &MiracastService::onWIFIStateChangedHandler, this); - } - - if ( false == updateSystemFriendlyName()) - { - m_FriendlyNameMonitorTimerID = g_timeout_add(2000, MiracastService::monitor_friendly_name_timercallback, this); - MIRACASTLOG_WARNING("Unable to get friendlyName, requires polling [%u]...",m_FriendlyNameMonitorTimerID); - } - else - { - MIRACASTLOG_INFO("friendlyName updated properly..."); - } - m_isServiceInitialized = true; - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_IDLE; - } - else - { - switch (ret_code) - { - case MIRACAST_INVALID_P2P_CTRL_IFACE: - { - msg = "Invalid P2P Ctrl iface configured"; - } - break; - case MIRACAST_CONTROLLER_INIT_FAILED: - { - msg = "Controller Init Failed"; - } - break; - case MIRACAST_P2P_INIT_FAILED: - { - msg = "P2P Init Failed"; - } - break; - case MIRACAST_RTSP_INIT_FAILED: - { - msg = "RTSP msg handler Init Failed"; - } - break; - default: - { - msg = "Unknown Error:Failed to obtain MiracastController Object"; - } - break; - } - } - } - // On success return empty, to indicate there is no error text. - return msg; - } - - void MiracastService::Deinitialize(PluginHost::IShell* /* service */) - { - MiracastService::_instance = nullptr; + if (nullptr != mCurrentService) + { + mCurrentService->AddRef(); + mCurrentService->Register(&mMiracastServiceNotification); - MIRACASTLOG_INFO("Entering..!!!"); + mMiracastServiceImpl = mCurrentService->Root(mConnectionId, 5000, _T(PLUGIN_MIRACAST_SERVICE_IMPLEMENTATION_NAME)); - if (_powerManagerPlugin) { - _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); - _powerManagerPlugin.Reset(); + if (nullptr != mMiracastServiceImpl) + { + mConfigure = mMiracastServiceImpl->QueryInterface(); + if (mConfigure) + { + uint32_t result = mConfigure->Configure(mCurrentService); + if(result != Core::ERROR_NONE) + { + SYSLOG(Logging::Startup, (_T("MiracastService::Initialize: Failed to Configure %s"), PLUGIN_MIRACAST_SERVICE_IMPLEMENTATION_NAME)); + retStatus = _T("MiracastService plugin could not be initialised"); + } + else + { + /* Register for notifications */ + mMiracastServiceImpl->Register(&mMiracastServiceNotification); + /* Invoking Plugin API register to wpeframework */ + Exchange::JMiracastService::Register(*this, mMiracastServiceImpl); + mRegisterEvents = true; + } + mConfigure->Release(); + } + else + { + retStatus = _T("MiracastService implementation did not provide a configuration interface"); + SYSLOG(Logging::Startup, (_T("MiracastService::Initialize: MiracastServiceImpl[%s] does not provide a configuration interface"), PLUGIN_MIRACAST_SERVICE_IMPLEMENTATION_NAME)); + } + } + else + { + SYSLOG(Logging::Startup, (_T("MiracastService::Initialize: MiracastServiceImpl[%s] object creation failed"), PLUGIN_MIRACAST_SERVICE_IMPLEMENTATION_NAME)); + retStatus = _T("MiracastService plugin could not be initialised"); + } } - if (m_WiFiPluginObj) + else { - m_WiFiPluginObj->Unsubscribe(1000, _T("onWIFIStateChanged")); - delete m_WiFiPluginObj; - m_WiFiPluginObj = nullptr; + SYSLOG(Logging::Startup, (_T("MiracastService::Initialize: service is not valid"))); + retStatus = _T("MiracastService plugin could not be initialised"); } - if (m_SystemPluginObj) + if (0 != retStatus.length()) { - m_SystemPluginObj->Unsubscribe(1000, _T("onFriendlyNameChanged")); - delete m_SystemPluginObj; - m_SystemPluginObj = nullptr; - } - - LOGINFO("Disconnect from the COM-RPC socket\n"); - // Disconnect from the COM-RPC socket - if (_communicatorClient.IsValid()) { - _communicatorClient->Close(RPC::CommunicationTimeOut); - _communicatorClient.Release(); - } - - if (_engine.IsValid()) { - _engine.Release(); - } - - _registeredEventHandlers = false; - - if (m_isServiceInitialized) { - MiracastController::destroyInstance(); - DeinitializeIARM(); - m_CurrentService = nullptr; - m_miracast_ctrler_obj = nullptr; - m_isServiceInitialized = false; - m_isServiceEnabled = false; - MIRACASTLOG_INFO("Done..!!!"); + Deinitialize(service); } - MIRACASTLOG_INFO("Exiting..!!!"); + return retStatus; } - string MiracastService::Information() const - { - return (string("{\"service\": \"") + SERVICE_NAME + string("\"}")); - } - - /** - * @brief This method used to Enable/Disable the Miracast/WFD Discovery. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::setEnableWrapper(const JsonObject ¶meters, JsonObject &response) - { - bool success = false; - bool is_enabled = true; - - MIRACASTLOG_INFO("Entering..!!!"); - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", is_enabled); - - lock_guard lck(m_DiscoveryStateMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - if (true == is_enabled) - { - if (!m_isServiceEnabled) - { - lock_guard lock(m_EventMutex); - m_isServiceEnabled = true; - if (m_IsTransitionFromDeepSleep) - { - LOGINFO("#### MCAST-TRIAGE-OK Enable Miracast discovery Async"); - m_miracast_ctrler_obj->restart_discoveryAsync(); - m_IsTransitionFromDeepSleep = false; - } - else - { - setEnable(true); - } - response["message"] = "Successfully enabled the WFD Discovery"; - success = true; - } - else - { - response["message"] = "WFD Discovery already enabled."; - } - } - else - { - if ( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED == current_state ) - { - response["message"] = "Failed as MiracastPlayer already Launched"; - } - else if (m_isServiceEnabled) - { - lock_guard lock(m_EventMutex); - m_isServiceEnabled = false; - if (!m_IsTransitionFromDeepSleep) - { - if ( MIRACAST_SERVICE_STATE_RESTARTING_SESSION == current_state ) - { - m_miracast_ctrler_obj->stop_discoveryAsync(); - } - else - { - setEnable(false); - } - } - else - { - LOGINFO("#### MCAST-TRIAGE-OK Skipping Disable discovery as done by PwrMgr"); - } - remove_wifi_connection_state_timer(); - remove_miracast_connection_timer(); - response["message"] = "Successfully disabled the WFD Discovery"; - success = true; - } - else - { - response["message"] = "WFD Discovery already disabled."; - } - } - } - else - { - response["message"] = "Invalid parameter passed"; - } - - returnResponse(success); - } - - /** - * @brief This method used to get the current state of Miracast/WFD Discovery. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::getEnable(const JsonObject ¶meters, JsonObject &response) - { - MIRACASTLOG_INFO("Entering..!!!"); - response["enabled"] = m_isServiceEnabled; - returnResponse(true); - } - - /** - * @brief This method used to Enable/Disable the Miracast/WFD Discovery. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - void MiracastService::setEnable(bool isEnabled) - { - MIRACASTLOG_INFO("Entering..!!!"); - if ( nullptr != m_miracast_ctrler_obj ) - { - m_miracast_ctrler_obj->set_enable(isEnabled); - } - MIRACASTLOG_INFO("Exiting..!!!"); - } - - /** - * @brief This method used to Enable/Disable the Miracast P2P Backend Discovery. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::setP2PBackendDiscovery(const JsonObject ¶meters, JsonObject &response) - { - bool success = false; - bool is_enabled = true; - - MIRACASTLOG_INFO("Entering..!!!"); - if (parameters.HasLabel("enabled")) - { - getBoolParameter("enabled", is_enabled); - m_miracast_ctrler_obj->setP2PBackendDiscovery(is_enabled); - success = true; - } - else - { - response["message"] = "Invalid parameter passed"; - } - returnResponse(success); - } - - /** - * @brief This method used to Get the value of the given key from the environment (device properties file). - * - * @param: key and value reference pointer. - * @return Returns the true or false. - */ - bool MiracastService::envGetValue(const char *key, std::string &value) - { - std::ifstream fs(MIRACAST_DEVICE_PROPERTIES_FILE, std::ifstream::in); - std::string::size_type delimpos; - std::string line; - if (!fs.fail()) - { - while (std::getline(fs, line)) - { - if (!line.empty() && ((delimpos = line.find('=')) > 0)) - { - std::string itemKey = line.substr(0, delimpos); - if (itemKey == key) - { - value = line.substr(delimpos + 1, std::string::npos); - return true; - } - } - } - } - return false; - } - - /** - * @brief This method used to accept or reject the WFD connection request. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::acceptClientConnection(const JsonObject ¶meters, JsonObject &response) - { - bool success = false; - std::string requestedStatus = ""; - - MIRACASTLOG_INFO("Entering..!!!"); - if (parameters.HasLabel("requestStatus")) - { - requestedStatus = parameters["requestStatus"].String(); - if (("Accept" == requestedStatus) || ("Reject" == requestedStatus)) - { - lock_guard lock(m_EventMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - success = true; - - remove_miracast_connection_timer(); - - if ( MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING == current_state) - { - if ("Accept" == requestedStatus) - { - MIRACASTLOG_INFO("#### Notifying Launch Request ####"); - m_miracast_ctrler_obj->switch_launch_request_context(m_src_dev_ip, m_src_dev_mac, m_src_dev_name, m_sink_dev_ip ); - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED); - } - else - { - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_REJECTED); - m_miracast_ctrler_obj->restart_session_discovery(m_src_dev_mac); - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_IDLE; - changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); - MIRACASTLOG_INFO("#### Refreshing the Session ####"); - } - m_src_dev_ip.clear(); - m_src_dev_mac.clear(); - m_src_dev_name.clear(); - m_sink_dev_ip.clear(); - } - else - { - if ( MIRACAST_SERVICE_STATE_CONNECTING == current_state ) - { - m_miracast_ctrler_obj->accept_client_connection(requestedStatus); - if ("Accept" == requestedStatus) - { - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED); - } - else - { - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_REJECTED); - } - } - else - { - MIRACASTLOG_INFO("Ignoring '%s' as Session already Refreshed and Current State[%#08X]",requestedStatus.c_str(),current_state); - } - } - } - else - { - response["message"] = "Supported 'requestStatus' parameter values are Accept or Reject"; - LOGERR("Unsupported param passed [%s]", requestedStatus.c_str()); - } - } - else - { - LOGERR("Invalid parameter passed"); - response["message"] = "Invalid parameter passed"; - } - - returnResponse(success); - } - - uint32_t MiracastService::stopClientConnection(const JsonObject ¶meters, JsonObject &response) - { - bool success = false; - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfStringParamNotFound(parameters, "name"); - returnIfStringParamNotFound(parameters, "mac"); - - lock_guard lock(m_EventMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - - if ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state ) - { - MIRACASTLOG_WARNING("stopClientConnection Already Received..!!!"); - response["message"] = "stopClientConnection Already Received"; - } - else - { - std::string name,mac; - - getStringParameter("name", name); - getStringParameter("mac", mac); - - if ((( 0 == name.compare(m_miracast_ctrler_obj->get_WFDSourceName())) && - ( 0 == mac.compare(m_miracast_ctrler_obj->get_WFDSourceMACAddress())))|| - (( 0 == name.compare(m_miracast_ctrler_obj->get_NewSourceName())) && - ( 0 == mac.compare(m_miracast_ctrler_obj->get_NewSourceMACAddress())))) - { - std::string cached_mac_address = ""; - if ( 0 == mac.compare(m_miracast_ctrler_obj->get_NewSourceMACAddress())) - { - cached_mac_address = mac; - } - - if ( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED != current_state ) - { - changeServiceState(MIRACAST_SERVICE_STATE_APP_REQ_TO_ABORT_CONNECTION); - m_miracast_ctrler_obj->restart_session_discovery(cached_mac_address); - changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); - success = true; - } - else - { - response["message"] = "stopClientConnection received after Launch"; - LOGERR("stopClientConnection received after Launch..!!!"); - } - } - else - { - response["message"] = "Invalid MAC and Name"; - LOGERR("Invalid MAC and Name[%s][%s]..!!!",mac.c_str(),name.c_str()); - } - } - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - /** - * @brief This method used to update the Player State for MiracastService Plugin. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::updatePlayerState(const JsonObject ¶meters, JsonObject &response) - { - string mac; - string player_state; - bool success = true, - restart_discovery_needed = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - returnIfStringParamNotFound(parameters, "mac"); - returnIfStringParamNotFound(parameters, "state"); - lock_guard lock(m_EventMutex); - if (parameters.HasLabel("mac")) - { - getStringParameter("mac", mac); - } - - if (parameters.HasLabel("state")) - { - getStringParameter("state", player_state); - if (player_state == "PLAYING" || player_state == "playing") - { - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_PLAYING; - } - else if (player_state == "STOPPED" || player_state == "stopped") - { - int64_t json_parsed_value; - eM_PLAYER_REASON_CODE stop_reason_code; - - getNumberParameter("reason_code", json_parsed_value); - stop_reason_code = static_cast(json_parsed_value); - - if ( MIRACAST_PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ == stop_reason_code ) - { - MIRACASTLOG_INFO("!!! STOPPED RECEIVED FOR NEW CONECTION !!!"); - m_miracast_ctrler_obj->flush_current_session(); - } - else - { - restart_discovery_needed = true; - if ( MIRACAST_PLAYER_REASON_CODE_APP_REQ_TO_STOP == stop_reason_code ) - { - MIRACASTLOG_INFO("!!! STOPPED RECEIVED FOR ON EXIT !!!"); - } - else if ( MIRACAST_PLAYER_REASON_CODE_SRC_DEV_REQ_TO_STOP == stop_reason_code ) - { - MIRACASTLOG_INFO("!!! SRC DEV TEARDOWN THE CONNECTION !!!"); - } - else - { - MIRACASTLOG_ERROR("!!! STOPPED RECEIVED FOR REASON[%#04X] !!!",stop_reason_code); - } - } - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_STOPPED; - } - else if (player_state == "INITIATED" || player_state == "initiated") - { - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_INITIATED; - } - else if (player_state == "INPROGRESS" || player_state == "inprogress") - { - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_INPROGRESS; - } - else - { - m_miracast_ctrler_obj->m_ePlayer_state = MIRACAST_PLAYER_STATE_IDLE; - } - } - - if ( m_isServiceEnabled && restart_discovery_needed ) - { - // It will restart the discovering - m_miracast_ctrler_obj->restart_session_discovery(mac); - changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); - } - - MIRACASTLOG_INFO("Player State set to [%s (%d)] for Source device [%s].", player_state.c_str(), (int)m_miracast_ctrler_obj->m_ePlayer_state, mac.c_str()); - // @TODO: Need to check what to do next? - - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - - uint32_t MiracastService::setLogging(const JsonObject ¶meters, JsonObject &response) - { - std::string log_level = ""; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - if (parameters.HasLabel("separate_logger")) - { - JsonObject separate_logger; - separate_logger = parameters["separate_logger"].Object(); - - if (separate_logger.HasLabel("status")) - { - std::string status = ""; - status = separate_logger["status"].String(); - - success = true; - - if (status == "ENABLE" || status == "enable") - { - std::string logfilename = ""; - logfilename = separate_logger["logfilename"].String(); - MIRACAST::enable_separate_logger(logfilename); - } - else if (status == "DISABLE" || status == "disable") - { - MIRACAST::disable_separate_logger(); - } - else - { - success = false; - } - } - } - - if (parameters.HasLabel("level")) - { - LogLevel level = FATAL_LEVEL; - getStringParameter("level", log_level); - success = true; - if (log_level == "FATAL" || log_level == "fatal") - { - level = FATAL_LEVEL; - } - else if (log_level == "ERROR" || log_level == "error") - { - level = ERROR_LEVEL; - } - else if (log_level == "WARNING" || log_level == "warning") - { - level = WARNING_LEVEL; - } - else if (log_level == "INFO" || log_level == "info") - { - level = INFO_LEVEL; - } - else if (log_level == "VERBOSE" || log_level == "verbose") - { - level = VERBOSE_LEVEL; - } - else if (log_level == "TRACE" || log_level == "trace") - { - level = TRACE_LEVEL; - } - else - { - success = false; - } - - if (success) - { - set_loglevel(level); - } - } - MIRACASTLOG_INFO("Exiting..!!!"); - returnResponse(success); - } - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - /** - * @brief This method used to stop the client connection. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::testNotifier(const JsonObject ¶meters, JsonObject &response) - { - MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST stMsgQ = {0}; - string client_mac,client_name,state; - string status; - bool success = false; - - MIRACASTLOG_INFO("Entering..!!!"); - - if ( false == m_isTestNotifierEnabled ) - { - if (parameters.HasLabel("setStatus")) - { - getStringParameter("setStatus", status); - if (status == "ENABLED" || status == "enabled") - { - if ( MIRACAST_OK == m_miracast_ctrler_obj->create_TestNotifier()) - { - m_isTestNotifierEnabled = true; - success = true; - } - else - { - LOGERR("Failed to enable TestNotifier"); - response["message"] = "Failed to enable TestNotifier"; - } - } - else if (status == "DISABLED" || status == "disabled") - { - LOGERR("TestNotifier not yet enabled. Unable to Disable it"); - response["message"] = "TestNotifier not yet enabled. Unable to Disable"; - } - } - else - { - LOGERR("TestNotifier not yet enabled"); - response["message"] = "TestNotifier not yet enabled"; - } - } - else - { - if (parameters.HasLabel("setStatus")) - { - getStringParameter("setStatus", status); - if (status == "DISABLED" || status == "disabled") - { - m_miracast_ctrler_obj->destroy_TestNotifier(); - success = true; - m_isTestNotifierEnabled = false; - } - else if (status == "ENABLED" || status == "enabled") - { - LOGERR("TestNotifier already enabled"); - response["message"] = "TestNotifier already enabled"; - success = false; - } - else - { - LOGERR("Invalid status"); - response["message"] = "Invalid status"; - } - return success; - } - - returnIfStringParamNotFound(parameters, "state"); - returnIfStringParamNotFound(parameters, "mac"); - returnIfStringParamNotFound(parameters, "name"); - - if (parameters.HasLabel("state")) - { - getStringParameter("state", state); - } - - if (parameters.HasLabel("mac")) - { - getStringParameter("mac", client_mac); - } - - if (parameters.HasLabel("name")) - { - getStringParameter("name", client_name); - } - - if (client_mac.empty()||client_name.empty()) - { - LOGERR("Invalid MAC/Name has passed"); - response["message"] = "Invalid MAC/Name has passed"; - } - else - { - strncpy( stMsgQ.src_dev_name, client_name.c_str(), sizeof(stMsgQ.src_dev_name)); - stMsgQ.src_dev_name[sizeof(stMsgQ.src_dev_name) - 1] = '\0'; - strncpy( stMsgQ.src_dev_mac_addr, client_mac.c_str(), sizeof(stMsgQ.src_dev_mac_addr)); - stMsgQ.src_dev_mac_addr[sizeof(stMsgQ.src_dev_mac_addr) - 1] = '\0'; - - MIRACASTLOG_INFO("Given [NAME-MAC-state] are[%s-%s-%s]", - client_name.c_str(), - client_mac.c_str(), - state.c_str()); - - success = true; - - if (state == "CONNECT_REQUEST" || state == "connect_request") - { - stMsgQ.state = MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_REQUESTED; - } - else if (state == "CONNECT_ERROR" || state == "connect_error") - { - int64_t json_parsed_value; - eMIRACAST_SERVICE_ERR_CODE error_code; - - returnIfNumberParamNotFound(parameters, "error_code"); - - getNumberParameter("error_code", json_parsed_value); - error_code = static_cast(json_parsed_value); - - if (( MIRACAST_SERVICE_ERR_CODE_MAX_ERROR > error_code ) && - ( MIRACAST_SERVICE_ERR_CODE_SUCCESS <= error_code )) - { - stMsgQ.state = MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_ERROR; - stMsgQ.error_code = error_code; - } - else - { - success = false; - LOGERR("Invalid error_code passed"); - response["message"] = "Invalid error_code passed"; - } - } - else if (state == "LAUNCH" || state == "launch") - { - string source_dev_ip,sink_dev_ip; - stMsgQ.state = MIRACAST_SERVICE_TEST_NOTIFIER_LAUNCH_REQUESTED; - - returnIfStringParamNotFound(parameters, "source_dev_ip"); - returnIfStringParamNotFound(parameters, "sink_dev_ip"); - - if (parameters.HasLabel("source_dev_ip")) - { - getStringParameter("source_dev_ip", source_dev_ip); - } - - if (parameters.HasLabel("sink_dev_ip")) - { - getStringParameter("sink_dev_ip", sink_dev_ip); - } - - if (source_dev_ip.empty()||sink_dev_ip.empty()) - { - LOGERR("Invalid source_dev_ip/sink_dev_ip has passed"); - response["message"] = "Invalid source_dev_ip/sink_dev_ip has passed"; - success = false; - } - else - { - strncpy( stMsgQ.src_dev_ip_addr, source_dev_ip.c_str(), sizeof(stMsgQ.src_dev_ip_addr)); - stMsgQ.src_dev_ip_addr[sizeof(stMsgQ.src_dev_ip_addr) - 1] = '\0'; - strncpy( stMsgQ.sink_ip_addr, sink_dev_ip.c_str(), sizeof(stMsgQ.sink_ip_addr)); - stMsgQ.sink_ip_addr[sizeof(stMsgQ.sink_ip_addr) - 1] = '\0'; - - MIRACASTLOG_INFO("Given [Src-Sink-IP] are [%s-%s]", - source_dev_ip.c_str(), - sink_dev_ip.c_str()); - } - } - else - { - success = false; - LOGERR("Invalid state passed"); - response["message"] = "Invalid state passed"; - } - if (success) - { - m_miracast_ctrler_obj->send_msgto_test_notifier_thread(stMsgQ); - } - } - } - - MIRACASTLOG_INFO("Exiting..!!!"); - - returnResponse(success); - } -#endif/*ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER*/ - - void MiracastService::onMiracastServiceClientConnectionRequest(string client_mac, string client_name) - { - std::string requestStatus = "Accept"; - bool is_another_connect_request = false; - MIRACASTLOG_INFO("Entering..!!!"); - - lock_guard lock(m_EventMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - - if ( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED == current_state ) - { - is_another_connect_request = true; - MIRACASTLOG_WARNING("Another Connect Request received while casting"); - } - - if (0 == access("/opt/miracast_autoconnect", F_OK)) - { - char commandBuffer[768] = {0}; - - if ( is_another_connect_request ) - { - MIRACASTLOG_INFO("!!! NEED TO STOP ONGOING SESSION !!!"); - strncpy(commandBuffer,"curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastPlayer.1.stopRequest\", \"params\":{\"reason\": \"NEW_CONNECTION\"}}' http://127.0.0.1:9998/jsonrpc &",sizeof(commandBuffer)); - commandBuffer[sizeof(commandBuffer) - 1] = '\0'; - MIRACASTLOG_INFO("Stopping old Session by [%s]",commandBuffer); - MiracastCommon::execute_SystemCommand(commandBuffer); - sleep(1); - } - if (MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED == current_state) - { - changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING); - } - else - { - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTING); - } - memset(commandBuffer,0x00,sizeof(commandBuffer)); - snprintf( commandBuffer, - sizeof(commandBuffer), - "curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastService.1.acceptClientConnection\", \"params\":{\"requestStatus\": \"%s\"}}' http://127.0.0.1:9998/jsonrpc &", - requestStatus.c_str()); - MIRACASTLOG_INFO("AutoConnecting [%s - %s] by [%s]",client_name.c_str(),client_mac.c_str(),commandBuffer); - MiracastCommon::execute_SystemCommand(commandBuffer); - } - else - { - JsonObject params; - params["mac"] = client_mac; - params["name"] = client_name; - sendNotify(EVT_ON_CLIENT_CONNECTION_REQUEST, params); - m_src_dev_mac = client_mac; - - if (MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED == current_state) - { - changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING); - } - else - { - changeServiceState(MIRACAST_SERVICE_STATE_CONNECTING); - } - m_MiracastConnectionMonitorTimerID = g_timeout_add(40000, MiracastService::monitor_miracast_connection_timercallback, this); - MIRACASTLOG_INFO("Timer created to Monitor Miracast Connection Status [%u]",m_MiracastConnectionMonitorTimerID); - } - } - - void MiracastService::onMiracastServiceClientConnectionError(string client_mac, string client_name , eMIRACAST_SERVICE_ERR_CODE error_code ) - { - MIRACASTLOG_INFO("Entering..!!!"); - - lock_guard lock(m_EventMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - - if ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state ) - { - MIRACASTLOG_INFO("Session already refreshed, So no need to report Error. Current state [%#08X]",current_state); - } - else - { - JsonObject params; - params["mac"] = client_mac; - params["name"] = client_name; - params["error_code"] = std::to_string(error_code); - params["reason"] = reasonDescription(error_code); - sendNotify(EVT_ON_CLIENT_CONNECTION_ERROR, params); - } - MIRACASTLOG_INFO("Exiting..!!!"); - } - - std::string MiracastService::reasonDescription(eMIRACAST_SERVICE_ERR_CODE e) - { - switch (e) - { - case MIRACAST_SERVICE_ERR_CODE_SUCCESS: - return "SUCCESS"; - case MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_NEGO_ERROR: - return "P2P GROUP NEGOTIATION FAILURE."; - case MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_FORMATION_ERROR: - return "P2P GROUP FORMATION FAILURE."; - case MIRACAST_SERVICE_ERR_CODE_GENERIC_FAILURE: - return "P2P GENERIC FAILURE."; - case MIRACAST_SERVICE_ERR_CODE_P2P_CONNECT_ERROR: - return "P2P CONNECT FAILURE."; - default: - return "Unimplemented item"; - } - } - - bool MiracastService::updateSystemFriendlyName() - { - JsonObject params, Result; - bool return_value = false; - MIRACASTLOG_INFO("Entering..!!!"); - - getThunderPlugins(); - - if (nullptr == m_SystemPluginObj) - { - LOGERR("m_SystemPluginObj not yet instantiated"); - return false; - } - - uint32_t ret = m_SystemPluginObj->Invoke(THUNDER_RPC_TIMEOUT, _T("getFriendlyName"), params, Result); - - if (Core::ERROR_NONE == ret) - { - if (Result["success"].Boolean()) - { - std::string friendlyName = ""; - friendlyName = Result["friendlyName"].String(); - m_miracast_ctrler_obj->set_FriendlyName(friendlyName,m_isServiceEnabled); - MIRACASTLOG_INFO("Miracast FriendlyName=%s", friendlyName.c_str()); - return_value = true; - } - else - { - ret = Core::ERROR_GENERAL; - LOGERR("updateSystemFriendlyName call failed"); - } - } - else - { - LOGERR("updateSystemFriendlyName call failed E[%u]", ret); - } - return return_value; - } - - void MiracastService::onFriendlyNameUpdateHandler(const JsonObject ¶meters) - { - string message; - string value; - parameters.ToString(message); - MIRACASTLOG_INFO("[Friendly Name Event], [%s]", message.c_str()); - - if (parameters.HasLabel("friendlyName")) - { - value = parameters["friendlyName"].String(); - m_miracast_ctrler_obj->set_FriendlyName(value, m_isServiceEnabled); - MIRACASTLOG_INFO("Miracast FriendlyName=%s", value.c_str()); - } - } - - gboolean MiracastService::monitor_friendly_name_timercallback(gpointer userdata) - { - gboolean timer_retry_state = G_SOURCE_CONTINUE; - MIRACASTLOG_TRACE("Entering..!!!"); - MiracastService *self = (MiracastService *)userdata; - MIRACASTLOG_INFO("TimerCallback Triggered for updating friendlyName..."); - if ( true == self->updateSystemFriendlyName() ) - { - MIRACASTLOG_INFO("friendlyName updated properly, No polling required..."); - timer_retry_state = G_SOURCE_REMOVE; - } - else - { - MIRACASTLOG_WARNING("Unable to get friendlyName, still requires polling..."); - } - MIRACASTLOG_TRACE("Exiting..!!!"); - return timer_retry_state; - } - - void MiracastService::setWiFiState(DEVICE_WIFI_STATES wifiState) - { - MIRACASTLOG_INFO("Miracast WiFi State=%#08X", wifiState); - lock_guard lck(m_DiscoveryStateMutex); - if (m_isServiceEnabled) - { - switch(wifiState) - { - case DEVICE_WIFI_STATE_CONNECTING: - { - MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI DEVICE_WIFI_STATE [CONNECTING] ####"); - {lock_guard lock(m_EventMutex); - setEnable(false); - } - remove_wifi_connection_state_timer(); - m_IsWiFiConnectingState = true; - m_WiFiConnectedStateMonitorTimerID = g_timeout_add(30000, MiracastService::monitor_wifi_connection_state_timercallback, this); - MIRACASTLOG_INFO("Timer created to Monitor WiFi Connection Status [%u]",m_WiFiConnectedStateMonitorTimerID); - } - break; - case DEVICE_WIFI_STATE_CONNECTED: - case DEVICE_WIFI_STATE_FAILED: - { - MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI DEVICE_WIFI_STATE [%s] ####",( DEVICE_WIFI_STATE_CONNECTED == wifiState ) ? "CONNECTED" : "FAILED"); - if (m_IsWiFiConnectingState) - { - {lock_guard lock(m_EventMutex); - setEnable(true); - } - m_IsWiFiConnectingState = false; - } - remove_wifi_connection_state_timer(); - } - break; - default: - { - /* NOP */ - } - break; - } - } - } - - #ifdef UNIT_TESTING - /** - * @brief This method used to get the current status of Miracast. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::getStatus(const JsonObject ¶meters, JsonObject &response) - { - MIRACASTLOG_INFO("Entering..!!!"); - lock_guard lck(m_DiscoveryStateMutex); - lock_guard lock(m_EventMutex); - response["enabled"] = m_isServiceEnabled; - response["state"] = std::to_string(getCurrentServiceState()); - response["powerState"] = getPowerStateString(getCurrentPowerState()); - response["DeepSleepTransition"] = m_IsTransitionFromDeepSleep; - response["wifiState"] = m_IsWiFiConnectingState; - returnResponse(true); - } - - /** - * @brief This method used to get the set Power status to Miracast. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::setPowerStateWrapper(const JsonObject ¶meters, JsonObject &response) - { - string message; - uint32_t powerState; - MIRACASTLOG_INFO("Entering..!!!"); - parameters.ToString(message); - MIRACASTLOG_INFO("[Power State Changed Event], [%s]", message.c_str()); - - if (parameters.HasLabel("state")) - { - powerState = parameters["state"].Number(); - setPowerState(getPowerManagerPluginPowerState(powerState)); - } - returnResponse(true); - } - - /** - * @brief This method used to get the set WiFi status to Miracast. - * - * @param: None. - * @return Returns the success code of underlying method. - */ - uint32_t MiracastService::setWiFiStateWrapper(const JsonObject ¶meters, JsonObject &response) - { - string message; - uint32_t wifiState; - MIRACASTLOG_INFO("Entering..!!!"); - parameters.ToString(message); - MIRACASTLOG_INFO("[WiFi State Changed Event], [%s]", message.c_str()); - - if (parameters.HasLabel("state")) - { - wifiState = parameters["state"].Number(); - DEVICE_WIFI_STATES temp = static_cast(wifiState); - MIRACASTLOG_INFO("[WiFi State Changed Event], [%#08X][%#08X]", wifiState,temp); - setWiFiState(static_cast(wifiState)); - } - returnResponse(true); - } - #endif /*UNIT_TESTING*/ - - void MiracastService::onWIFIStateChangedHandler(const JsonObject ¶meters) - { - string message; - uint32_t wifiState; - parameters.ToString(message); - MIRACASTLOG_INFO("[WiFi State Changed Event], [%s]", message.c_str()); - - if (parameters.HasLabel("state")) - { - wifiState = parameters["state"].Number(); - setWiFiState(static_cast(wifiState)); - } - } - - gboolean MiracastService::monitor_wifi_connection_state_timercallback(gpointer userdata) - { - MIRACASTLOG_TRACE("Entering..!!!"); - MiracastService *self = (MiracastService *)userdata; - MIRACASTLOG_INFO("TimerCallback Triggered for Monitor WiFi Connection Status..."); - {lock_guard lck(self->m_DiscoveryStateMutex); - MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI Discovery[%u] WiFiConnectingState[%u] ####", - self->m_isServiceEnabled,m_IsWiFiConnectingState); - if (self->m_isServiceEnabled && m_IsWiFiConnectingState) - { - {lock_guard lock(self->m_EventMutex); - self->setEnable(true); - } - } - m_IsWiFiConnectingState = false; - } - MIRACASTLOG_TRACE("Exiting..!!!"); - return G_SOURCE_REMOVE; - } - - gboolean MiracastService::monitor_miracast_connection_timercallback(gpointer userdata) - { - MiracastService *self = (MiracastService *)userdata; - MIRACASTLOG_TRACE("Entering..!!!"); - lock_guard lock(self->m_EventMutex); - MIRACASTLOG_INFO("TimerCallback Triggered for Monitor Miracast Connection Expired and Restarting Session..."); - if (self->m_isServiceEnabled) - { - self->m_miracast_ctrler_obj->restart_session_discovery(self->m_src_dev_mac); - self->m_src_dev_mac.clear(); - self->changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); - } - MIRACASTLOG_TRACE("Exiting..!!!"); - return G_SOURCE_REMOVE; - } - - void MiracastService::remove_wifi_connection_state_timer(void) - { - MIRACASTLOG_TRACE("Entering..!!!"); - if (m_WiFiConnectedStateMonitorTimerID) - { - MIRACASTLOG_INFO("Removing WiFi Connection Status Monitor Timer"); - g_source_remove(m_WiFiConnectedStateMonitorTimerID); - m_WiFiConnectedStateMonitorTimerID = 0; - } - m_IsWiFiConnectingState = false; - MIRACASTLOG_TRACE("Exiting..!!!"); - } - - void MiracastService::remove_miracast_connection_timer(void) - { - MIRACASTLOG_TRACE("Entering..!!!"); - if (m_MiracastConnectionMonitorTimerID) - { - MIRACASTLOG_INFO("Removing Miracast Connection Status Monitor Timer"); - g_source_remove(m_MiracastConnectionMonitorTimerID); - m_MiracastConnectionMonitorTimerID = 0; - } - MIRACASTLOG_TRACE("Exiting..!!!"); - } - - void MiracastService::onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) - { - lock_guard lock(m_EventMutex); - eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); - MIRACASTLOG_INFO("Entering[%u]..!!!",is_connect_req_reported); - - if ( !is_connect_req_reported ) - { - changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED); - m_src_dev_ip = src_dev_ip; - m_src_dev_mac = src_dev_mac; - m_src_dev_name = src_dev_name; - m_sink_dev_ip = sink_dev_ip; - MIRACASTLOG_INFO("Direct Launch request has received. So need to notify connect Request"); - onMiracastServiceClientConnectionRequest( src_dev_mac, src_dev_name ); - } - else if ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state ) - { - MIRACASTLOG_INFO("Session already refreshed, So no need to notify Launch Request. Current state [%#08X]",current_state); - //m_miracast_ctrler_obj->restart_session_discovery(); - } - else - { - JsonObject params; - JsonObject device_params; - device_params["source_dev_ip"] = src_dev_ip; - device_params["source_dev_mac"] = src_dev_mac; - device_params["source_dev_name"] = src_dev_name; - device_params["sink_dev_ip"] = sink_dev_ip; - params["device_parameters"] = device_params; - - if (0 == access("/opt/miracast_autoconnect", F_OK)) - { - char commandBuffer[768] = {0}; - snprintf( commandBuffer, - sizeof(commandBuffer), - "curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastPlayer.1.playRequest\", \"params\":{\"device_parameters\": {\"source_dev_ip\": \"%s\",\"source_dev_mac\": \"%s\",\"source_dev_name\": \"%s\",\"sink_dev_ip\": \"%s\"},\"video_rectangle\": {\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}}}' http://127.0.0.1:9998/jsonrpc &", - src_dev_ip.c_str(), - src_dev_mac.c_str(), - src_dev_name.c_str(), - sink_dev_ip.c_str()); - MIRACASTLOG_INFO("System Command [%s]",commandBuffer); - MiracastCommon::execute_SystemCommand(commandBuffer); - } - else - { - sendNotify(EVT_ON_LAUNCH_REQUEST, params); - } - changeServiceState(MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED); - } - } - - void MiracastService::onStateChange(eMIRA_SERVICE_STATES state) - { - MIRACASTLOG_INFO("Entering state [%#08X]",state); - lock_guard lock(m_EventMutex); - switch (state) - { - case MIRACAST_SERVICE_STATE_IDLE: - case MIRACAST_SERVICE_STATE_DISCOVERABLE: - { - if ((!m_isServiceEnabled) && (MIRACAST_SERVICE_STATE_DISCOVERABLE == state)) - { - /*User already disabled the discovery, so should not enable again.*/ - m_miracast_ctrler_obj->stop_discoveryAsync(); - } - else - { - changeServiceState(state); - } - } - break; - default: - { - - } - break; - } - MIRACASTLOG_INFO("Exiting..."); - } - - eMIRA_SERVICE_STATES MiracastService::getCurrentServiceState(void) - { - MIRACASTLOG_INFO("current state [%#08X]",m_eService_state); - return m_eService_state; - } + void MiracastService::Deinitialize(PluginHost::IShell* service) + { + SYSLOG(Logging::Startup, (_T("MiracastService::Deinitialize: PID=%u"), getpid())); - void MiracastService::changeServiceState(eMIRA_SERVICE_STATES eService_state) - { - eMIRA_SERVICE_STATES old_state = m_eService_state, - new_state = eService_state; - m_eService_state = eService_state; - MIRACASTLOG_INFO("changing state [%#08X] -> [%#08X]",old_state,new_state); - } + ASSERT(mCurrentService == service); + ASSERT(0 == mConnectionId); - std::string MiracastService::getPowerStateString(PowerState pwrState) - { - std::string pwrStateStr = ""; + if (nullptr != mMiracastServiceImpl) + { + if (mRegisterEvents) + { + mMiracastServiceImpl->Unregister(&mMiracastServiceNotification); + Exchange::JMiracastService::Unregister(*this); + mRegisterEvents = false; + } - switch (pwrState) + /* Stop processing: */ + RPC::IRemoteConnection* connection = nullptr; + if (service) + { + connection = service->RemoteConnection(mConnectionId); + } + VARIABLE_IS_NOT_USED uint32_t result = mMiracastServiceImpl->Release(); + mMiracastServiceImpl = nullptr; + + /* It should have been the last reference we are releasing, + * so it should endup in a DESTRUCTION_SUCCEEDED, if not we + * are leaking... */ + ASSERT(result == Core::ERROR_DESTRUCTION_SUCCEEDED); + + /* If this was running in a (container) process... */ + if (nullptr != connection) + { + /* Lets trigger the cleanup sequence for + * out-of-process code. Which will guard + * that unwilling processes, get shot if + * not stopped friendly :-) + */ + connection->Terminate(); + connection->Release(); + } + } + if (nullptr != mCurrentService) { - case WPEFramework::Exchange::IPowerManager::POWER_STATE_ON: pwrStateStr = "ON"; break; - case WPEFramework::Exchange::IPowerManager::POWER_STATE_OFF: pwrStateStr = "OFF"; break; - case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY: pwrStateStr = "LIGHT_SLEEP"; break; - case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_LIGHT_SLEEP: pwrStateStr = "LIGHT_SLEEP"; break; - case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP: pwrStateStr = "DEEP_SLEEP"; break; - default: pwrStateStr = "UNKNOWN"; break; + /* Make sure the Activated and Deactivated are no longer called before we start cleaning up.. */ + mCurrentService->Unregister(&mMiracastServiceNotification); + mCurrentService->Release(); + mCurrentService = nullptr; } - return pwrStateStr; + mConnectionId = 0; + SYSLOG(Logging::Shutdown, (string(_T("MiracastService de-initialised")))); } - PowerState MiracastService::getPowerManagerPluginPowerState(uint32_t powerState) + string MiracastService::Information() const { - PowerState ret_power_state = (PowerState)powerState++; - return ret_power_state; + return("This MiracastService Plugin Facilitates Peer-to-Peer Control and WFD Source Device Discovery"); } - - PowerState MiracastService::getCurrentPowerState(void) - { - MIRACASTLOG_INFO("current power state [%s]",getPowerStateString(m_powerState).c_str()); - return m_powerState; - } - - void MiracastService::setPowerState(PowerState pwrState) - { - PowerState old_pwr_state = m_powerState, - new_pwr_state = pwrState; - m_powerState = pwrState; - MIRACASTLOG_INFO("changing power state [%s] -> [%s]", - getPowerStateString(old_pwr_state).c_str(), - getPowerStateString(new_pwr_state).c_str()); - if (WPEFramework::Exchange::IPowerManager::POWER_STATE_ON == pwrState) - { - lock_guard lock(_instance->m_EventMutex); - if ((m_IsTransitionFromDeepSleep) && (_instance->m_isServiceEnabled)) - { - LOGINFO("#### MCAST-TRIAGE-OK-PWR Enable Miracast discovery from PwrMgr [%d]",_instance->m_isServiceEnabled); - _instance->m_miracast_ctrler_obj->restart_discoveryAsync(); - m_IsTransitionFromDeepSleep = false; - } - else if (!_instance->m_isServiceEnabled) - { - LOGINFO("#### MCAST-TRIAGE-OK-PWR Miracast discovery already Disabled [%d]. No need to enable it",_instance->m_isServiceEnabled); - } - } - else if (WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP == pwrState) - { - lock_guard lock(_instance->m_EventMutex); - if ( _instance->m_isServiceEnabled ) - { - LOGINFO("#### MCAST-TRIAGE-OK-PWR Miracast Discovery Disabled ####"); - _instance->setEnable(false); - } - else - { - LOGINFO("#### MCAST-TRIAGE-OK-PWR Miracast discovery already Disabled [%d]. No need to disable it",_instance->m_isServiceEnabled); - } - _instance->remove_wifi_connection_state_timer(); - _instance->remove_miracast_connection_timer(); - m_IsTransitionFromDeepSleep = true; - } - } - } // namespace Plugin -} // namespace WPEFramework + void MiracastService::Deactivated(RPC::IRemoteConnection* connection) + { + if (connection->Id() == mConnectionId) { + ASSERT(nullptr != mCurrentService); + LOGINFO("MiracastService::Deactivated"); + Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(mCurrentService, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + } + } + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastService.h b/Miracast/MiracastService/MiracastService.h index 0d2e4c20..9dc5539c 100644 --- a/Miracast/MiracastService/MiracastService.h +++ b/Miracast/MiracastService/MiracastService.h @@ -1,206 +1,133 @@ /** - * If not stated otherwise in this file or this component's LICENSE - * file the following copyright and licenses apply: - * - * Copyright 2023 RDK Management - * - * 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. - **/ +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2019 RDK Management +* +* 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. +**/ #pragma once +#include "Module.h" +#include +#include +#include +#include +#include "UtilsLogging.h" +#include "tracing/Logging.h" #include -#include -#include "Module.h" -#include -#include "libIARM.h" -#include -#include "PowerManagerInterface.h" - - -using namespace WPEFramework; -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; -using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; - -typedef enum DeviceWiFiStates{ - DEVICE_WIFI_STATE_UNINSTALLED = 0, - DEVICE_WIFI_STATE_DISABLED = 1, - DEVICE_WIFI_STATE_DISCONNECTED = 2, - DEVICE_WIFI_STATE_PAIRING = 3, - DEVICE_WIFI_STATE_CONNECTING = 4, - DEVICE_WIFI_STATE_CONNECTED = 5, - DEVICE_WIFI_STATE_FAILED = 6 -}DEVICE_WIFI_STATES; - -using std::vector; namespace WPEFramework { namespace Plugin { - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class MiracastService : public PluginHost::IPlugin, public PluginHost::JSONRPC, public MiracastServiceNotifier + class MiracastService : public PluginHost::IPlugin, public PluginHost::JSONRPC { - public: - // constants - static const short API_VERSION_NUMBER_MAJOR; - static const short API_VERSION_NUMBER_MINOR; - static const string SERVICE_NAME; - - // methods - static const string METHOD_MIRACAST_SET_ENABLE; - static const string METHOD_MIRACAST_GET_ENABLE; - static const string METHOD_MIRACAST_SET_P2P_BACKEND_DISCOVERY; - static const string METHOD_MIRACAST_CLIENT_CONNECT; - static const string METHOD_MIRACAST_STOP_CLIENT_CONNECT; - static const string METHOD_MIRACAST_SET_UPDATE_PLAYER_STATE; - static const string METHOD_MIRACAST_SET_LOG_LEVEL; - #ifdef UNIT_TESTING - static const string METHOD_MIRACAST_GET_STATUS; - static const string METHOD_MIRACAST_SET_POWERSTATE; - static const string METHOD_MIRACAST_SET_WIFISTATE; - #endif /*UNIT_TESTING*/ - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER - static const string METHOD_MIRACAST_TEST_NOTIFIER; - uint32_t testNotifier(const JsonObject ¶meters, JsonObject &response); - bool m_isTestNotifierEnabled; -#endif /* ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER */ - - MiracastService(); - virtual ~MiracastService(); - virtual const string Initialize(PluginHost::IShell *shell) override; - virtual void Deinitialize(PluginHost::IShell *service) override; - virtual string Information() const override; - - virtual void onMiracastServiceClientConnectionRequest(string client_mac, string client_name) override; - virtual void onMiracastServiceClientConnectionError(string client_mac, string client_name , eMIRACAST_SERVICE_ERR_CODE error_code ) override; - virtual void onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) override; - virtual void onStateChange(eMIRA_SERVICE_STATES state ) override; - void onPowerModeChanged(const PowerState currentState, const PowerState newState); - void registerEventHandlers(); - - BEGIN_INTERFACE_MAP(MiracastService) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - PluginHost::IShell *m_CurrentService; - static MiracastService *_instance; - static MiracastController *m_miracast_ctrler_obj; - - private: - class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { private: - PowerManagerNotification(const PowerManagerNotification&) = delete; - PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; - - public: - explicit PowerManagerNotification(MiracastService& parent) - : _parent(parent) + class Notification : public RPC::IRemoteConnection::INotification, + public Exchange::IMiracastService::INotification { - } - ~PowerManagerNotification() override = default; - + private: + Notification() = delete; + Notification(const Notification&) = delete; + Notification& operator=(const Notification&) = delete; + + public: + explicit Notification(MiracastService* parent) + : _parent(*parent) + { + ASSERT(parent != nullptr); + } + + virtual ~Notification() + { + } + + BEGIN_INTERFACE_MAP(Notification) + INTERFACE_ENTRY(Exchange::IMiracastService::INotification) + INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) + END_INTERFACE_MAP + + void Activated(RPC::IRemoteConnection*) override + { + } + + void Deactivated(RPC::IRemoteConnection *connection) override + { + _parent.Deactivated(connection); + } + + void OnClientConnectionRequest(const string &clientMac , const string &clientName ) override + { + LOGINFO("=> clientMac:[%s], clientName:[%s]", clientMac.c_str(), clientName.c_str()); + Exchange::JMiracastService::Event::OnClientConnectionRequest(_parent, clientMac, clientName); + } + + void OnClientConnectionError(const string &clientMac , const string &clientName , const string &reasonCode , const Exchange::IMiracastService::ReasonCode reasonDescription ) override + { + LOGINFO("=> clientMac:[%s], clientName:[%s], errorCode:[%s]", clientMac.c_str(), clientName.c_str(), reasonCode.c_str()); + Exchange::JMiracastService::Event::OnClientConnectionError(_parent, clientMac, clientName, reasonCode, reasonDescription); + } + + void OnLaunchRequest(const Exchange::IMiracastService::DeviceParameters &deviceParameters) override + { + LOGINFO("=> SrcDevIP[%s] SrcDevMac[%s] SrcDevName[%s] SinkDevIP[%s]", + deviceParameters.sourceDeviceIP.c_str(), + deviceParameters.sourceDeviceMac.c_str(), + deviceParameters.sourceDeviceName.c_str(), + deviceParameters.sinkDeviceIP.c_str()); + Exchange::JMiracastService::Event::OnLaunchRequest(_parent, deviceParameters); + } + + private: + MiracastService& _parent; + }; // class Notification + public: - void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override - { - _parent.onPowerModeChanged(currentState, newState); - } + MiracastService(const MiracastService&) = delete; + MiracastService& operator=(const MiracastService&) = delete; - template - T* baseInterface() - { - static_assert(std::is_base_of(), "base type mismatch"); - return static_cast(this); - } + MiracastService(); + virtual ~MiracastService(); - BEGIN_INTERFACE_MAP(PowerManagerNotification) - INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + BEGIN_INTERFACE_MAP(MiracastService) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_AGGREGATE(Exchange::IMiracastService, mMiracastServiceImpl) END_INTERFACE_MAP - + + /* IPlugin methods */ + const string Initialize(PluginHost::IShell* service) override; + void Deinitialize(PluginHost::IShell* service) override; + string Information() const override; + private: - MiracastService& _parent; - }; - bool m_isServiceInitialized; - bool m_isServiceEnabled; - std::mutex m_DiscoveryStateMutex; - std::recursive_mutex m_EventMutex; - guint m_FriendlyNameMonitorTimerID{0}; - guint m_WiFiConnectedStateMonitorTimerID{0}; - guint m_MiracastConnectionMonitorTimerID{0}; - eMIRA_SERVICE_STATES m_eService_state; - std::string m_src_dev_ip; - std::string m_src_dev_mac; - std::string m_src_dev_name; - std::string m_sink_dev_ip; - Core::ProxyType > _engine; - Core::ProxyType _communicatorClient; - PowerManagerInterfaceRef _powerManagerPlugin; - Core::Sink _pwrMgrNotification; - bool _registeredEventHandlers; - WPEFramework::JSONRPC::LinkType *m_SystemPluginObj = NULL; - WPEFramework::JSONRPC::LinkType *m_WiFiPluginObj = NULL; - uint32_t setEnableWrapper(const JsonObject ¶meters, JsonObject &response); - uint32_t getEnable(const JsonObject ¶meters, JsonObject &response); - uint32_t setP2PBackendDiscovery(const JsonObject ¶meters, JsonObject &response); - uint32_t acceptClientConnection(const JsonObject ¶meters, JsonObject &response); - uint32_t stopClientConnection(const JsonObject ¶meters, JsonObject &response); - uint32_t updatePlayerState(const JsonObject ¶meters, JsonObject &response); - uint32_t setLogging(const JsonObject ¶meters, JsonObject &response); - #ifdef UNIT_TESTING - uint32_t getStatus(const JsonObject ¶meters, JsonObject &response); - uint32_t setPowerStateWrapper(const JsonObject ¶meters, JsonObject &response); - uint32_t setWiFiStateWrapper(const JsonObject ¶meters, JsonObject &response); - #endif /*UNIT_TESTING*/ - - std::string reasonDescription(eMIRACAST_SERVICE_ERR_CODE e); - void getThunderPlugins(); - bool updateSystemFriendlyName(); - void onFriendlyNameUpdateHandler(const JsonObject ¶meters); - static gboolean monitor_friendly_name_timercallback(gpointer userdata); - void setWiFiState(DEVICE_WIFI_STATES wifiState); - void onWIFIStateChangedHandler(const JsonObject ¶meters); - static gboolean monitor_wifi_connection_state_timercallback(gpointer userdata); - void remove_wifi_connection_state_timer(void); - static gboolean monitor_miracast_connection_timercallback(gpointer userdata); - void remove_miracast_connection_timer(void); - bool envGetValue(const char *key, std::string &value); - eMIRA_SERVICE_STATES getCurrentServiceState(void); - void changeServiceState(eMIRA_SERVICE_STATES eService_state); - PowerState getCurrentPowerState(void); - void setPowerState(PowerState pwrState); - std::string getPowerStateString(PowerState pwrState); - PowerState getPowerManagerPluginPowerState(uint32_t powerState); - void setEnable(bool isEnabled); - void InitializePowerManager(PluginHost::IShell *service); - const void InitializePowerState(); - void DeinitializeIARM(); - - // We do not allow this plugin to be copied !! - MiracastService(const MiracastService &) = delete; - MiracastService &operator=(const MiracastService &) = delete; - }; + void Deactivated(RPC::IRemoteConnection* connection); + + private: /* members */ + PluginHost::IShell* mCurrentService{}; + uint32_t mConnectionId{}; + Exchange::IMiracastService* mMiracastServiceImpl{}; + Exchange::IConfiguration* mConfigure; + Core::Sink mMiracastServiceNotification; + bool mRegisterEvents{false}; + + public /* constants */: + static const string SERVICE_NAME; + + public /* members */: + static MiracastService* _instance; + }; // class MiracastService } // namespace Plugin -} // namespace WPEFramework +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastServiceImplementation.cpp b/Miracast/MiracastService/MiracastServiceImplementation.cpp new file mode 100644 index 00000000..cab5df0f --- /dev/null +++ b/Miracast/MiracastService/MiracastServiceImplementation.cpp @@ -0,0 +1,1236 @@ +/** + * If not stated otherwise in this file or this component's LICENSE + * file the following copyright and licenses apply: + * + * Copyright 2023 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include + +#include "MiracastServiceImplementation.h" + +#include "UtilsJsonRpc.h" +#include "UtilsIarm.h" + +#include "UtilsSynchroIarm.hpp" + +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; + +#define MIRACAST_DEVICE_PROPERTIES_FILE "/etc/device.properties" +#define SERVER_DETAILS "127.0.0.1:9998" +#define SYSTEM_CALLSIGN "org.rdk.System" +#define SYSTEM_CALLSIGN_VER SYSTEM_CALLSIGN ".1" +#define WIFI_CALLSIGN "org.rdk.Wifi" +#define WIFI_CALLSIGN_VER WIFI_CALLSIGN ".1" +#define SECURITY_TOKEN_LEN_MAX 1024 +#define THUNDER_RPC_TIMEOUT 2000 + +static PowerState m_powerState = WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY; +static bool m_IsTransitionFromDeepSleep = false; +static bool m_IsWiFiConnectingState = false; + +namespace WPEFramework +{ + namespace Plugin + { + SERVICE_REGISTRATION(MiracastServiceImplementation, MIRACAST_SERVICE_API_VERSION_NUMBER_MAJOR, MIRACAST_SERVICE_API_VERSION_NUMBER_MINOR); + + MiracastServiceImplementation *MiracastServiceImplementation::_instance = nullptr; + PowerManagerInterfaceRef MiracastServiceImplementation::_powerManagerPlugin; + MiracastController *MiracastServiceImplementation::m_miracast_ctrler_obj = nullptr; + + MiracastServiceImplementation::MiracastServiceImplementation() + : _adminLock(), _pwrMgrNotification(*this) + { + LOGINFO("Create MiracastServiceImplementation Instance"); + MiracastServiceImplementation::_instance = this; + MIRACAST::logger_init("MiracastService"); + m_isServiceInitialized = false; + _registeredEventHandlers = false; + m_eService_state = MIRACAST_SERVICE_STATE_IDLE; + m_CurrentService = nullptr; + m_isServiceEnabled = false; + } + + MiracastServiceImplementation::~MiracastServiceImplementation() + { + LOGINFO("Call MiracastServiceImplementation destructor"); + if (m_FriendlyNameMonitorTimerID) + { + g_source_remove(m_FriendlyNameMonitorTimerID); + m_FriendlyNameMonitorTimerID = 0; + } + remove_wifi_connection_state_timer(); + remove_miracast_connection_timer(); + + if (_powerManagerPlugin) + { + _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); + _powerManagerPlugin.Reset(); + } + _registeredEventHandlers = false; + + if (m_WiFiPluginObj) + { + m_WiFiPluginObj->Unsubscribe(1000, _T("onWIFIStateChanged")); + delete m_WiFiPluginObj; + m_WiFiPluginObj = nullptr; + } + + if (m_SystemPluginObj) + { + m_SystemPluginObj->Unsubscribe(1000, _T("onFriendlyNameChanged")); + delete m_SystemPluginObj; + m_SystemPluginObj = nullptr; + } + + MIRACASTLOG_INFO("Disconnect from the COM-RPC socket"); + + if (m_isServiceInitialized) + { + MiracastController::destroyInstance(); + m_CurrentService = nullptr; + m_miracast_ctrler_obj = nullptr; + m_isServiceInitialized = false; + m_isServiceEnabled = false; + MIRACASTLOG_INFO("Done..!!!"); + } + if(m_CurrentService) + { + m_CurrentService->Release(); + m_CurrentService = nullptr; + } + MIRACAST::logger_deinit(); + MiracastServiceImplementation::_instance = nullptr; + } + + /** + * Register a notification callback + */ + Core::hresult MiracastServiceImplementation::Register(Exchange::IMiracastService::INotification *notification) + { + MIRACASTLOG_TRACE("Entering ..."); + ASSERT(nullptr != notification); + + MIRACASTLOG_INFO("Register notification: %p", notification); + _adminLock.Lock(); + + // Make sure we can't register the same notification callback multiple times + if (std::find(_miracastServiceNotification.begin(), _miracastServiceNotification.end(), notification) == _miracastServiceNotification.end()) + { + _miracastServiceNotification.push_back(notification); + notification->AddRef(); + } + else + { + MIRACASTLOG_ERROR("same notification is registered already"); + } + + _adminLock.Unlock(); + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + /** + * Unregister a notification callback + */ + Core::hresult MiracastServiceImplementation::Unregister(Exchange::IMiracastService::INotification *notification) + { + MIRACASTLOG_TRACE("Entering ..."); + Core::hresult status = Core::ERROR_GENERAL; + + ASSERT(nullptr != notification); + + _adminLock.Lock(); + + // we just unregister one notification once + auto itr = std::find(_miracastServiceNotification.begin(), _miracastServiceNotification.end(), notification); + if (itr != _miracastServiceNotification.end()) + { + (*itr)->Release(); + MIRACASTLOG_INFO("Unregister notification"); + _miracastServiceNotification.erase(itr); + status = Core::ERROR_NONE; + } + else + { + MIRACASTLOG_ERROR("notification not found"); + } + + _adminLock.Unlock(); + MIRACASTLOG_TRACE("Exiting ..."); + return status; + } + + /* Helper methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + eMIRA_SERVICE_STATES MiracastServiceImplementation::getCurrentServiceState(void) + { + MIRACASTLOG_INFO("current state [%#08X]",m_eService_state); + return m_eService_state; + } + + void MiracastServiceImplementation::changeServiceState(eMIRA_SERVICE_STATES eService_state) + { + eMIRA_SERVICE_STATES old_state = m_eService_state, + new_state = eService_state; + m_eService_state = eService_state; + MIRACASTLOG_INFO("changing state [%#08X] -> [%#08X]",old_state,new_state); + } + + bool MiracastServiceImplementation::envGetValue(const char *key, std::string &value) + { + std::ifstream fs(MIRACAST_DEVICE_PROPERTIES_FILE, std::ifstream::in); + std::string::size_type delimpos; + std::string line; + if (!fs.fail()) + { + while (std::getline(fs, line)) + { + if (!line.empty() && ((delimpos = line.find('=')) > 0)) + { + std::string itemKey = line.substr(0, delimpos); + if (itemKey == key) + { + value = line.substr(delimpos + 1, std::string::npos); + return true; + } + } + } + } + return false; + } + + void MiracastServiceImplementation::getThunderPlugins(void) + { + MIRACASTLOG_TRACE("Entering ..."); + if (nullptr == m_SystemPluginObj) + { + string token; + // TODO: use interfaces and remove token + auto security = m_CurrentService->QueryInterfaceByCallsign("SecurityAgent"); + if (nullptr != security) + { + string payload = "http://localhost"; + if (security->CreateToken(static_cast(payload.length()), + reinterpret_cast(payload.c_str()), + token) == Core::ERROR_NONE) + { + MIRACASTLOG_INFO("got security token"); + } + else + { + MIRACASTLOG_ERROR("failed to get security token"); + } + security->Release(); + } + else + { + MIRACASTLOG_WARNING("No security agent"); + } + + string query = "token=" + token; + Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); + m_SystemPluginObj = new WPEFramework::JSONRPC::LinkType(_T(SYSTEM_CALLSIGN_VER), (_T("MiracastService")), false, query); + if (nullptr == m_SystemPluginObj) + { + MIRACASTLOG_ERROR("JSONRPC: %s: initialization failed", SYSTEM_CALLSIGN_VER); + } + else + { + MIRACASTLOG_INFO("JSONRPC: %s: initialization ok", SYSTEM_CALLSIGN_VER); + } + + m_WiFiPluginObj = new WPEFramework::JSONRPC::LinkType(_T(WIFI_CALLSIGN_VER), (_T("MiracastService")), false, query); + if (nullptr == m_WiFiPluginObj) + { + MIRACASTLOG_ERROR("JSONRPC: %s: initialization failed", WIFI_CALLSIGN_VER); + } + else + { + MIRACASTLOG_INFO("JSONRPC: %s: initialization ok", WIFI_CALLSIGN_VER); + } + } + MIRACASTLOG_TRACE("Exiting ..."); + } + + bool MiracastServiceImplementation::updateSystemFriendlyName() + { + JsonObject params, Result; + bool return_value = false; + MIRACASTLOG_TRACE("Entering ..."); + + getThunderPlugins(); + + if (nullptr == m_SystemPluginObj) + { + MIRACASTLOG_ERROR("m_SystemPluginObj not yet instantiated"); + return false; + } + + uint32_t ret = m_SystemPluginObj->Invoke(THUNDER_RPC_TIMEOUT, _T("getFriendlyName"), params, Result); + + if (Core::ERROR_NONE == ret) + { + if (Result["success"].Boolean()) + { + std::string friendlyName = ""; + friendlyName = Result["friendlyName"].String(); + m_miracast_ctrler_obj->set_FriendlyName(friendlyName,m_isServiceEnabled); + MIRACASTLOG_INFO("Miracast FriendlyName=%s", friendlyName.c_str()); + return_value = true; + } + else + { + ret = Core::ERROR_GENERAL; + MIRACASTLOG_ERROR("updateSystemFriendlyName call failed"); + } + } + else + { + MIRACASTLOG_ERROR("updateSystemFriendlyName call failed E[%u]", ret); + } + return return_value; + } + + void MiracastServiceImplementation::setEnableInternal(bool isEnabled) + { + MIRACASTLOG_TRACE("Entering ..."); + if ( nullptr != m_miracast_ctrler_obj ) + { + m_miracast_ctrler_obj->set_enable(isEnabled); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + /* Helper and Internal methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + void MiracastServiceImplementation::dispatchEvent(Event event, const JsonObject ¶ms) + { + Core::IWorkerPool::Instance().Submit(Job::Create(this, event, params)); + } + + void MiracastServiceImplementation::Dispatch(Event event,const JsonObject& params) + { + _adminLock.Lock(); + + std::list::const_iterator index(_miracastServiceNotification.begin()); + + switch (event) + { + case MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_REQUEST: + { + string clientMac = ""; + string clientName = ""; + + if (!(params.HasLabel("source_dev_mac") && !(clientMac = params["source_dev_mac"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_mac not present or empty"); + } + else if (!(params.HasLabel("source_dev_name") && !(clientName = params["source_dev_name"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_name not present or empty"); + } + else + { + MIRACASTLOG_INFO("Notifying CLIENT_CONNECTION_REQUEST Event ClientMac[%s] ClientName[%s]", clientMac.c_str(), clientName.c_str()); + while (index != _miracastServiceNotification.end()) + { + (*index)->OnClientConnectionRequest(clientMac , clientName ); + ++index; + } + } + } + break; + case MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_ERROR: + { + string clientMac = ""; + string clientName = ""; + string reasonCodeStr = ""; + MiracastServiceReasonCode reason = WPEFramework::Exchange::IMiracastService::REASON_CODE_SUCCESS; + + if (!(params.HasLabel("source_dev_mac") && !(clientMac = params["source_dev_mac"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_mac not present or empty"); + } + else if (!(params.HasLabel("source_dev_name") && !(clientName = params["source_dev_name"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_name not present or empty"); + } + else if (!(params.HasLabel("reason_code"))) + { + MIRACASTLOG_ERROR("reason_code not present or empty"); + } + else + { + reason = static_cast(params["reason_code"].Number()); + reasonCodeStr = std::to_string(reason); + MIRACASTLOG_INFO("Notifying CLIENT_CONNECTION_ERROR Event Mac[%s] Name[%s] Reason[%u]",clientMac.c_str(), clientName.c_str(), reason); + while (index != _miracastServiceNotification.end()) + { + (*index)->OnClientConnectionError(clientMac , clientName , reasonCodeStr , reason); + ++index; + } + } + } + break; + case MIRACASTSERVICE_EVENT_PLAYER_LAUNCH_REQUEST: + { + DeviceParameters deviceParameters; + if (!(params.HasLabel("source_dev_mac") && !(deviceParameters.sourceDeviceMac = params["source_dev_mac"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_mac not present or empty"); + } + else if (!(params.HasLabel("source_dev_name") && !(deviceParameters.sourceDeviceName = params["source_dev_name"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_name not present or empty"); + } + else if (!(params.HasLabel("source_dev_ip") && !(deviceParameters.sourceDeviceIP = params["source_dev_ip"].String()).empty())) + { + MIRACASTLOG_ERROR("source_dev_ip not present or empty"); + } + else if (!(params.HasLabel("sink_dev_ip") && !(deviceParameters.sinkDeviceIP = params["sink_dev_ip"].String()).empty())) + { + MIRACASTLOG_ERROR("sink_dev_ip not present or empty"); + } + else + { + MIRACASTLOG_INFO("Notifying PLAYER_LAUNCH_REQUEST Event SourceDeviceIP[%s] SourceDeviceMac[%s] SourceDeviceName[%s] SinkDeviceIP[%s]", + deviceParameters.sourceDeviceIP.c_str(), deviceParameters.sourceDeviceMac.c_str(), + deviceParameters.sourceDeviceName.c_str(), deviceParameters.sinkDeviceIP.c_str()); + while (index != _miracastServiceNotification.end()) + { + (*index)->OnLaunchRequest(deviceParameters); + ++index; + } + } + } + break; + default: + { + MIRACASTLOG_WARNING("Event[%u] not handled", event); + } + break; + } + _adminLock.Unlock(); + } + + /* COMRPC Methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + uint32_t MiracastServiceImplementation::Configure(PluginHost::IShell *service) + { + MIRACASTLOG_TRACE("Entering ..."); + uint32_t result = Core::ERROR_GENERAL; + + ASSERT(nullptr != service); + + m_CurrentService = service; + + if (nullptr != m_CurrentService) + { + m_CurrentService->AddRef(); + string p2p_ctrl_iface = ""; + + if (!(envGetValue("WIFI_P2P_CTRL_INTERFACE", p2p_ctrl_iface))) + { + MIRACASTLOG_ERROR("WIFI_P2P_CTRL_INTERFACE not configured in device properties file"); + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_GENERAL; + } + + if (!m_isServiceInitialized) + { + MiracastError ret_code = MIRACAST_OK; + + InitializePowerManager(service); + InitializePowerState(); + + m_miracast_ctrler_obj = MiracastController::getInstance(ret_code, this,std::move(p2p_ctrl_iface)); + if (nullptr != m_miracast_ctrler_obj) + { + getThunderPlugins(); + // subscribe for event + if (nullptr != m_SystemPluginObj) + { + m_SystemPluginObj->Subscribe(1000, "onFriendlyNameChanged", &MiracastServiceImplementation::onFriendlyNameUpdateHandler, this); + } + if (nullptr != m_WiFiPluginObj) + { + m_WiFiPluginObj->Subscribe(1000, "onWIFIStateChanged", &MiracastServiceImplementation::onWIFIStateChangedHandler, this); + } + + if ( false == updateSystemFriendlyName()) + { + m_FriendlyNameMonitorTimerID = g_timeout_add(2000, MiracastServiceImplementation::monitor_friendly_name_timercallback, this); + MIRACASTLOG_WARNING("Unable to get friendlyName, requires polling [%u]...",m_FriendlyNameMonitorTimerID); + } + else + { + MIRACASTLOG_INFO("friendlyName updated properly..."); + } + m_isServiceInitialized = true; + result = Core::ERROR_NONE; + } + else + { + switch (ret_code) + { + case MIRACAST_INVALID_P2P_CTRL_IFACE: + { + MIRACASTLOG_ERROR("Invalid P2P Ctrl iface configured"); + } + break; + case MIRACAST_CONTROLLER_INIT_FAILED: + { + MIRACASTLOG_ERROR("Controller Init Failed"); + } + break; + case MIRACAST_P2P_INIT_FAILED: + { + MIRACASTLOG_ERROR("P2P Init Failed"); + } + break; + default: + { + MIRACASTLOG_ERROR("Unknown Error:Failed to obtain MiracastController Object"); + } + break; + } + } + } + } + MIRACASTLOG_TRACE("Exiting ..."); + return result; + } + + Core::hresult MiracastServiceImplementation::SetEnabled(const bool enabled , Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + bool isSuccessOrFailure = false; + MIRACASTLOG_INFO("SetEnabled called with [%s]", enabled ? "true" : "false"); + lock_guard lck(m_DiscoveryStateMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + if (enabled) + { + if (!m_isServiceEnabled) + { + lock_guard lock(m_EventMutex); + m_isServiceEnabled = true; + if (m_IsTransitionFromDeepSleep) + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK Enable Miracast discovery Async"); + m_miracast_ctrler_obj->restart_discoveryAsync(); + m_IsTransitionFromDeepSleep = false; + } + else + { + setEnableInternal(true); + } + result.message = "Successfully enabled the WFD Discovery"; + isSuccessOrFailure = true; + } + else + { + result.message = "WFD Discovery already enabled."; + } + } + else + { + if ( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED == current_state ) + { + result.message = "Failed as MiracastPlayer already Launched"; + } + else if (m_isServiceEnabled) + { + lock_guard lock(m_EventMutex); + m_isServiceEnabled = false; + if (!m_IsTransitionFromDeepSleep) + { + if ( MIRACAST_SERVICE_STATE_RESTARTING_SESSION == current_state ) + { + m_miracast_ctrler_obj->stop_discoveryAsync(); + } + else + { + setEnableInternal(false); + } + } + else + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK Skipping Disable discovery as done by PwrMgr"); + } + remove_wifi_connection_state_timer(); + remove_miracast_connection_timer(); + isSuccessOrFailure = true; + result.message = "Successfully disabled the WFD Discovery"; + } + else + { + result.message = "WFD Discovery already disabled."; + } + } + result.success = isSuccessOrFailure; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastServiceImplementation::GetEnabled(bool &enabled , bool &success ) + { + MIRACASTLOG_TRACE("Entering ..."); + enabled = m_isServiceEnabled; + success = true; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastServiceImplementation::AcceptClientConnection(const string &requestStatus , Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + bool isSuccessOrFailure = false; + if (("Accept" == requestStatus) || ("Reject" == requestStatus)) + { + lock_guard lock(m_EventMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + isSuccessOrFailure = true; + + remove_miracast_connection_timer(); + + if ( MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING == current_state) + { + if ("Accept" == requestStatus) + { + MIRACASTLOG_INFO("#### Notifying Launch Request ####"); + m_miracast_ctrler_obj->switch_launch_request_context(m_src_dev_ip, m_src_dev_mac, m_src_dev_name, m_sink_dev_ip ); + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED); + } + else + { + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_REJECTED); + m_miracast_ctrler_obj->restart_session_discovery(m_src_dev_mac); + changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); + MIRACASTLOG_INFO("#### Refreshing the Session ####"); + } + m_src_dev_ip.clear(); + m_src_dev_mac.clear(); + m_src_dev_name.clear(); + m_sink_dev_ip.clear(); + } + else + { + if ( MIRACAST_SERVICE_STATE_CONNECTING == current_state ) + { + m_miracast_ctrler_obj->accept_client_connection(requestStatus); + if ("Accept" == requestStatus) + { + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED); + } + else + { + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTION_REJECTED); + } + } + else + { + MIRACASTLOG_INFO("Ignoring '%s' as Session already Refreshed and Current State[%#08X]",requestStatus.c_str(),current_state); + } + } + } + else + { + result.message = "Supported 'requestStatus' parameter values are Accept or Reject"; + MIRACASTLOG_ERROR("Unsupported param passed [%s]", requestStatus.c_str()); + } + result.success = isSuccessOrFailure; + MIRACASTLOG_TRACE("Exiting ..."); + return Core::ERROR_NONE; + } + + Core::hresult MiracastServiceImplementation::StopClientConnection(const string &clientMac , const string &clientName, Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + bool isSuccessOrFailure = false; + MIRACASTLOG_INFO("clientMac[%s] clientName[%s]", clientMac.c_str(), clientName.c_str()); + lock_guard lock(m_EventMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + + if (( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED == current_state )|| + ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state )) + { + MIRACASTLOG_WARNING("Invalid state to process stopClientConnection [%#08X]", current_state); + result.message = "Invalid state to process stopClientConnection"; + } + else + { + if ((( 0 == clientName.compare(m_miracast_ctrler_obj->get_WFDSourceName())) && + ( 0 == clientMac.compare(m_miracast_ctrler_obj->get_WFDSourceMACAddress())))|| + (( 0 == clientName.compare(m_miracast_ctrler_obj->get_NewSourceName())) && + ( 0 == clientMac.compare(m_miracast_ctrler_obj->get_NewSourceMACAddress())))) + { + std::string cached_mac_address = ""; + if ( 0 == clientMac.compare(m_miracast_ctrler_obj->get_NewSourceMACAddress())) + { + cached_mac_address = clientMac; + } + + changeServiceState(MIRACAST_SERVICE_STATE_APP_REQ_TO_ABORT_CONNECTION); + m_miracast_ctrler_obj->restart_session_discovery(cached_mac_address); + changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); + isSuccessOrFailure = true; + } + else + { + result.message = "Invalid MAC and Name"; + MIRACASTLOG_ERROR("Invalid MAC and Name[%s][%s]..!!!",clientMac.c_str(),clientName.c_str()); + } + } + MIRACASTLOG_TRACE("Exiting ..."); + result.success = isSuccessOrFailure; + return Core::ERROR_NONE; + } + + Core::hresult MiracastServiceImplementation::UpdatePlayerState(const string &clientMac , const MiracastPlayerState playerState , const int reasonCode , Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + bool restart_discovery_needed = false; + switch (playerState) + { + case WPEFramework::Exchange::IMiracastService::PLAYER_STATE_IDLE: + case WPEFramework::Exchange::IMiracastService::PLAYER_STATE_INITIATED: + case WPEFramework::Exchange::IMiracastService::PLAYER_STATE_INPROGRESS: + case WPEFramework::Exchange::IMiracastService::PLAYER_STATE_PLAYING: + case WPEFramework::Exchange::IMiracastService::PLAYER_STATE_STOPPED: + { + MIRACASTLOG_INFO("#### clientMac[%s] playerState[%d] reasonCode[%d] ####", clientMac.c_str(), (int)playerState, (int)reasonCode); + + if (WPEFramework::Exchange::IMiracastService::PLAYER_STATE_STOPPED == playerState) + { + MiracastPlayerReasonCode playerReasonCode = static_cast(reasonCode); + if (WPEFramework::Exchange::IMiracastService::PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ == playerReasonCode ) + { + MIRACASTLOG_INFO("!!! STOPPED RECEIVED FOR NEW CONECTION !!!"); + m_miracast_ctrler_obj->flush_current_session(); + } + else + { + restart_discovery_needed = true; + if ( WPEFramework::Exchange::IMiracastService::PLAYER_REASON_CODE_APP_REQ_TO_STOP == playerReasonCode ) + { + MIRACASTLOG_INFO("!!! STOPPED RECEIVED FOR ON EXIT !!!"); + } + else if ( WPEFramework::Exchange::IMiracastService::PLAYER_REASON_CODE_SRC_DEV_REQ_TO_STOP == playerReasonCode ) + { + MIRACASTLOG_INFO("!!! SRC DEV TEARDOWN THE CONNECTION !!!"); + } + else + { + MIRACASTLOG_ERROR("!!! STOPPED RECEIVED FOR REASON[%d] !!!",playerReasonCode); + } + } + } + } + break; + default: + { + result.message = "Invalid Player State"; + MIRACASTLOG_ERROR("Invalid Player State[%#04X]", (int)playerState); + return Core::ERROR_BAD_REQUEST; + } + } + + if ( m_isServiceEnabled && restart_discovery_needed ) + { + // It will restart the discovering + m_miracast_ctrler_obj->restart_session_discovery(clientMac); + changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); + } + MIRACASTLOG_INFO("#### MiracastPlayerState[%d] reasonCode[%#04X] ####", (int)playerState, (int)reasonCode); + MIRACASTLOG_TRACE("Exiting ..."); + result.success = true; + return Core::ERROR_NONE; + } + + Core::hresult MiracastServiceImplementation::SetP2PBackendDiscovery(const bool enabled , Result &result ) + { + MIRACASTLOG_TRACE("Entering ..."); + if (m_miracast_ctrler_obj) + { + m_miracast_ctrler_obj->setP2PBackendDiscovery(enabled); + } + MIRACASTLOG_TRACE("Exiting ..."); + result.success = true; + return Core::ERROR_NONE; + } + /* COMRPC Methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* Events Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastServiceImplementation::onMiracastServiceClientConnectionRequest(string client_mac, string client_name) + { + MIRACASTLOG_TRACE("Entering ..."); + bool is_another_connect_request = false; + + lock_guard lock(m_EventMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + + if ( MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED == current_state ) + { + is_another_connect_request = true; + MIRACASTLOG_WARNING("Another Connect Request received while casting"); + } + + if (0 == access("/opt/miracast_autoconnect", F_OK)) + { + char commandBuffer[768] = {0}; + + if ( is_another_connect_request ) + { + MIRACASTLOG_INFO("!!! NEED TO STOP ONGOING SESSION !!!"); + strncpy(commandBuffer,"curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastPlayer.1.stopRequest\", \"params\":{\"reason\": \"NEW_CONNECTION\"}}' http://127.0.0.1:9998/jsonrpc &",sizeof(commandBuffer)); + commandBuffer[sizeof(commandBuffer) - 1] = '\0'; + MIRACASTLOG_INFO("Stopping old Session by [%s]",commandBuffer); + MiracastCommon::execute_SystemCommand(commandBuffer); + } + if (MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED == current_state) + { + changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING); + } + else + { + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTING); + } + memset(commandBuffer,0x00,sizeof(commandBuffer)); + strncpy(commandBuffer,"curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastService.1.acceptClientConnection\", \"params\":{\"requestStatus\": \"Accept\"}}' http://127.0.0.1:9998/jsonrpc &",sizeof(commandBuffer)); + commandBuffer[sizeof(commandBuffer) - 1] = '\0'; + MIRACASTLOG_INFO("AutoConnecting [%s - %s] by [%s]",client_name.c_str(),client_mac.c_str(),commandBuffer); + MiracastCommon::execute_SystemCommand(commandBuffer); + } + else + { + JsonObject eventDetails; + eventDetails["source_dev_mac"] = client_mac; + eventDetails["source_dev_name"] = client_name; + dispatchEvent(MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_REQUEST, eventDetails); + + m_src_dev_mac = std::move(client_mac); + + if (MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED == current_state) + { + changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING); + } + else + { + changeServiceState(MIRACAST_SERVICE_STATE_CONNECTING); + } + m_MiracastConnectionMonitorTimerID = g_timeout_add(40000, MiracastServiceImplementation::monitor_miracast_connection_timercallback, this); + MIRACASTLOG_INFO("Timer created to Monitor Miracast Connection Status [%u]",m_MiracastConnectionMonitorTimerID); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + + void MiracastServiceImplementation::onMiracastServiceClientConnectionError(string client_mac, string client_name , MiracastServiceReasonCode reason_code ) + { + MIRACASTLOG_TRACE("Entering ..."); + lock_guard lock(m_EventMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + + if ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state ) + { + MIRACASTLOG_INFO("Session already refreshed, So no need to report Error. Current state [%#08X]",current_state); + } + else + { + JsonObject eventDetails; + eventDetails["source_dev_mac"] = client_mac; + eventDetails["source_dev_name"] = client_name; + eventDetails["reason_code"] = static_cast(reason_code); + dispatchEvent(MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_ERROR, eventDetails); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + + void MiracastServiceImplementation::onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) + { + lock_guard lock(m_EventMutex); + eMIRA_SERVICE_STATES current_state = getCurrentServiceState(); + MIRACASTLOG_INFO("Entering[%u]..!!!",is_connect_req_reported); + + if ( !is_connect_req_reported ) + { + changeServiceState(MIRACAST_SERVICE_STATE_DIRECT_LAUCH_REQUESTED); + m_src_dev_ip = std::move(src_dev_ip); + m_src_dev_mac = std::move(src_dev_mac); + m_src_dev_name = std::move(src_dev_name); + m_sink_dev_ip = std::move(sink_dev_ip); + MIRACASTLOG_INFO("Direct Launch request has received. So need to notify connect Request"); + onMiracastServiceClientConnectionRequest( m_src_dev_mac, m_src_dev_name ); + } + else if ( MIRACAST_SERVICE_STATE_CONNECTION_ACCEPTED != current_state ) + { + MIRACASTLOG_INFO("Session already refreshed, So no need to notify Launch Request. Current state [%#08X]",current_state); + //m_miracast_ctrler_obj->restart_session_discovery(); + } + else + { + auto tupleParam = std::make_tuple(src_dev_ip,src_dev_mac,src_dev_name,sink_dev_ip); + + if (0 == access("/opt/miracast_autoconnect", F_OK)) + { + char commandBuffer[768] = {0}; + snprintf( commandBuffer, + sizeof(commandBuffer), + "curl -H \"Authorization: Bearer `WPEFrameworkSecurityUtility | cut -d '\"' -f 4`\" --header \"Content-Type: application/json\" --request POST --data '{\"jsonrpc\":\"2.0\", \"id\":3,\"method\":\"org.rdk.MiracastPlayer.1.playRequest\", \"params\":{\"device_parameters\": {\"source_dev_ip\": \"%s\",\"source_dev_mac\": \"%s\",\"source_dev_name\": \"%s\",\"sink_dev_ip\": \"%s\"},\"video_rectangle\": {\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}}}' http://127.0.0.1:9998/jsonrpc &", + src_dev_ip.c_str(), + src_dev_mac.c_str(), + src_dev_name.c_str(), + sink_dev_ip.c_str()); + MIRACASTLOG_INFO("System Command [%s]",commandBuffer); + MiracastCommon::execute_SystemCommand(commandBuffer); + } + else + { + JsonObject eventDetails; + eventDetails["source_dev_mac"] = src_dev_mac; + eventDetails["source_dev_name"] = src_dev_name; + eventDetails["source_dev_ip"] = src_dev_ip; + eventDetails["sink_dev_ip"] = sink_dev_ip; + dispatchEvent(MIRACASTSERVICE_EVENT_PLAYER_LAUNCH_REQUEST, eventDetails); + } + changeServiceState(MIRACAST_SERVICE_STATE_PLAYER_LAUNCHED); + } + MIRACASTLOG_INFO("Exiting ..."); + } + + void MiracastServiceImplementation::onStateChange(eMIRA_SERVICE_STATES state) + { + MIRACASTLOG_INFO("Entering state [%#08X]",state); + lock_guard lock(m_EventMutex); + switch (state) + { + case MIRACAST_SERVICE_STATE_IDLE: + case MIRACAST_SERVICE_STATE_DISCOVERABLE: + { + if ((!m_isServiceEnabled) && (MIRACAST_SERVICE_STATE_DISCOVERABLE == state)) + { + /*User already disabled the discovery, so should not enable again.*/ + m_miracast_ctrler_obj->stop_discoveryAsync(); + } + else + { + changeServiceState(state); + } + } + break; + default: + { + + } + break; + } + MIRACASTLOG_INFO("Exiting ..."); + } + /* Events End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* PowerManager related methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastServiceImplementation::InitializePowerManager(PluginHost::IShell *service) + { + MIRACASTLOG_INFO("Initializing PowerManager plugin ..."); + _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) + .withIShell(service) + .withRetryIntervalMS(200) + .withRetryCount(25) + .createInterface(); + MIRACASTLOG_INFO("Registering PowerManager plugin events"); + registerEventHandlers(); + } + + void MiracastServiceImplementation::registerEventHandlers() + { + ASSERT (_powerManagerPlugin); + if(!_registeredEventHandlers && _powerManagerPlugin) + { + _registeredEventHandlers = true; + _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); + MIRACASTLOG_INFO("onPowerModeChanged event registered ..."); + } + } + + void MiracastServiceImplementation::onPowerModeChanged(const PowerState currentState, const PowerState newState) + { + if (nullptr == _instance) + { + MIRACASTLOG_ERROR("#### MCAST-TRIAGE-NOK-PWR Miracast Service not enabled yet ####"); + return; + } + lock_guard lck(_instance->m_DiscoveryStateMutex); + _instance->setPowerStateInternal(newState); + } + + void MiracastServiceImplementation::InitializePowerState() + { + MIRACASTLOG_TRACE("Entering ..."); + Core::hresult res = Core::ERROR_GENERAL; + PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + + MIRACASTLOG_INFO("Initializing Power State"); + ASSERT (_powerManagerPlugin); + if (_powerManagerPlugin) + { + res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); + if (Core::ERROR_NONE == res) + { + setPowerStateInternal(pwrStateCur); + MIRACASTLOG_INFO("Current Power State is [%#04X]",pwrStateCur); + } + else + { + MIRACASTLOG_ERROR("Failed to get PowerState, ErrorCode [%#04X]",res); + } + } + MIRACASTLOG_TRACE("Exiting ..."); + } + + std::string MiracastServiceImplementation::getPowerStateString(PowerState pwrState) + { + std::string pwrStateStr = ""; + switch (pwrState) + { + case WPEFramework::Exchange::IPowerManager::POWER_STATE_ON: pwrStateStr = "ON"; break; + case WPEFramework::Exchange::IPowerManager::POWER_STATE_OFF: pwrStateStr = "OFF"; break; + case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY: pwrStateStr = "LIGHT_SLEEP"; break; + case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_LIGHT_SLEEP: pwrStateStr = "LIGHT_SLEEP"; break; + case WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP: pwrStateStr = "DEEP_SLEEP"; break; + default: pwrStateStr = "UNKNOWN"; break; + } + MIRACASTLOG_INFO("Power State[%#04X - %s]",pwrState ,pwrStateStr.c_str()); + return pwrStateStr; + } + + void MiracastServiceImplementation::setPowerStateInternal(PowerState pwrState) + { + MIRACASTLOG_TRACE("Entering ..."); + PowerState old_pwr_state = m_powerState, + new_pwr_state = pwrState; + m_powerState = pwrState; + MIRACASTLOG_INFO("changing power state [%s] -> [%s]", + getPowerStateString(old_pwr_state).c_str(), + getPowerStateString(new_pwr_state).c_str()); + if (WPEFramework::Exchange::IPowerManager::POWER_STATE_ON == pwrState) + { + lock_guard lock(_instance->m_EventMutex); + if ((m_IsTransitionFromDeepSleep) && (_instance->m_isServiceEnabled)) + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-PWR Enable Miracast discovery from PwrMgr [%d]",_instance->m_isServiceEnabled); + _instance->m_miracast_ctrler_obj->restart_discoveryAsync(); + m_IsTransitionFromDeepSleep = false; + } + else if (!_instance->m_isServiceEnabled) + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-PWR Miracast discovery already Disabled [%d]. No need to enable it",_instance->m_isServiceEnabled); + } + } + else if (WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP == pwrState) + { + lock_guard lock(_instance->m_EventMutex); + if ( _instance->m_isServiceEnabled ) + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-PWR Miracast Discovery Disabled ####"); + _instance->setEnableInternal(false); + } + else + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-PWR Miracast discovery already Disabled [%d]. No need to disable it",_instance->m_isServiceEnabled); + } + _instance->remove_wifi_connection_state_timer(); + _instance->remove_miracast_connection_timer(); + m_IsTransitionFromDeepSleep = true; + } + MIRACASTLOG_TRACE("Exiting ..."); + } + /* PowerManager related methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* WiFi related methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastServiceImplementation::setWiFiStateInternal(DEVICE_WIFI_STATES wifiState) + { + MIRACASTLOG_INFO("Miracast WiFi State=%#08X", wifiState); + lock_guard lck(m_DiscoveryStateMutex); + if (m_isServiceEnabled) + { + switch(wifiState) + { + case DEVICE_WIFI_STATE_CONNECTING: + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI DEVICE_WIFI_STATE [CONNECTING] ####"); + {lock_guard lock(m_EventMutex); + setEnableInternal(false); + } + remove_wifi_connection_state_timer(); + m_IsWiFiConnectingState = true; + m_WiFiConnectedStateMonitorTimerID = g_timeout_add(30000, MiracastServiceImplementation::monitor_wifi_connection_state_timercallback, this); + MIRACASTLOG_INFO("Timer created to Monitor WiFi Connection Status [%u]",m_WiFiConnectedStateMonitorTimerID); + } + break; + case DEVICE_WIFI_STATE_CONNECTED: + case DEVICE_WIFI_STATE_FAILED: + { + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI DEVICE_WIFI_STATE [%s] ####",( DEVICE_WIFI_STATE_CONNECTED == wifiState ) ? "CONNECTED" : "FAILED"); + if (m_IsWiFiConnectingState) + { + {lock_guard lock(m_EventMutex); + setEnableInternal(true); + } + m_IsWiFiConnectingState = false; + } + remove_wifi_connection_state_timer(); + } + break; + default: + { + /* NOP */ + } + break; + } + } + } + /* WiFi related methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* JsonRPC Event Subscribed handler methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + void MiracastServiceImplementation::onFriendlyNameUpdateHandler(const JsonObject ¶meters) + { + MIRACASTLOG_TRACE("Entering ..."); + string message; + string value; + parameters.ToString(message); + MIRACASTLOG_INFO("[Friendly Name Event], [%s]", message.c_str()); + + if (parameters.HasLabel("friendlyName")) + { + value = parameters["friendlyName"].String(); + m_miracast_ctrler_obj->set_FriendlyName(value, m_isServiceEnabled); + MIRACASTLOG_INFO("Miracast FriendlyName=%s", value.c_str()); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + + void MiracastServiceImplementation::onWIFIStateChangedHandler(const JsonObject ¶meters) + { + MIRACASTLOG_TRACE("Entering ..."); + string message; + uint32_t wifiState; + parameters.ToString(message); + MIRACASTLOG_INFO("[WiFi State Changed Event], [%s]", message.c_str()); + + if (parameters.HasLabel("state")) + { + wifiState = parameters["state"].Number(); + setWiFiStateInternal(static_cast(wifiState)); + } + MIRACASTLOG_TRACE("Exiting ..."); + } + /* JsonRPC Event Subscribed handler methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + + /* Internal Timer Callback and methods Start */ + /* ------------------------------------------------------------------------------------------------------- */ + gboolean MiracastServiceImplementation::monitor_friendly_name_timercallback(gpointer userdata) + { + gboolean timer_retry_state = G_SOURCE_CONTINUE; + MIRACASTLOG_TRACE("Entering ..."); + MiracastServiceImplementation *self = (MiracastServiceImplementation *)userdata; + MIRACASTLOG_INFO("TimerCallback Triggered for updating friendlyName..."); + if ( true == self->updateSystemFriendlyName() ) + { + MIRACASTLOG_INFO("friendlyName updated properly, No polling required..."); + timer_retry_state = G_SOURCE_REMOVE; + } + else + { + MIRACASTLOG_WARNING("Unable to get friendlyName, still requires polling..."); + } + MIRACASTLOG_TRACE("Exiting ..."); + return timer_retry_state; + } + + gboolean MiracastServiceImplementation::monitor_wifi_connection_state_timercallback(gpointer userdata) + { + MIRACASTLOG_TRACE("Entering ..."); + MiracastServiceImplementation *self = (MiracastServiceImplementation *)userdata; + MIRACASTLOG_INFO("TimerCallback Triggered for Monitor WiFi Connection Status..."); + {lock_guard lck(self->m_DiscoveryStateMutex); + MIRACASTLOG_INFO("#### MCAST-TRIAGE-OK-WIFI Discovery[%u] WiFiConnectingState[%u] ####", + self->m_isServiceEnabled,m_IsWiFiConnectingState); + if (self->m_isServiceEnabled && m_IsWiFiConnectingState) + { + {lock_guard lock(self->m_EventMutex); + self->setEnableInternal(true); + } + } + m_IsWiFiConnectingState = false; + } + MIRACASTLOG_TRACE("Exiting ..."); + return G_SOURCE_REMOVE; + } + + gboolean MiracastServiceImplementation::monitor_miracast_connection_timercallback(gpointer userdata) + { + MiracastServiceImplementation *self = (MiracastServiceImplementation *)userdata; + MIRACASTLOG_TRACE("Entering ..."); + lock_guard lock(self->m_EventMutex); + MIRACASTLOG_INFO("TimerCallback Triggered for Monitor Miracast Connection Expired and Restarting Session..."); + if (self->m_isServiceEnabled) + { + self->m_miracast_ctrler_obj->restart_session_discovery(self->m_src_dev_mac); + self->m_src_dev_mac.clear(); + self->changeServiceState(MIRACAST_SERVICE_STATE_RESTARTING_SESSION); + } + MIRACASTLOG_TRACE("Exiting ..."); + return G_SOURCE_REMOVE; + } + + void MiracastServiceImplementation::remove_wifi_connection_state_timer(void) + { + MIRACASTLOG_TRACE("Entering ..."); + if (m_WiFiConnectedStateMonitorTimerID) + { + MIRACASTLOG_INFO("Removing WiFi Connection Status Monitor Timer"); + g_source_remove(m_WiFiConnectedStateMonitorTimerID); + m_WiFiConnectedStateMonitorTimerID = 0; + } + m_IsWiFiConnectingState = false; + MIRACASTLOG_TRACE("Exiting ..."); + } + + void MiracastServiceImplementation::remove_miracast_connection_timer(void) + { + MIRACASTLOG_TRACE("Entering ..."); + if (m_MiracastConnectionMonitorTimerID) + { + MIRACASTLOG_INFO("Removing Miracast Connection Status Monitor Timer"); + g_source_remove(m_MiracastConnectionMonitorTimerID); + m_MiracastConnectionMonitorTimerID = 0; + } + MIRACASTLOG_TRACE("Exiting ..."); + } + /* Internal Timer Callback and methods End */ + /* ------------------------------------------------------------------------------------------------------- */ + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/MiracastService/MiracastServiceImplementation.h b/Miracast/MiracastService/MiracastServiceImplementation.h new file mode 100644 index 00000000..0428d1ff --- /dev/null +++ b/Miracast/MiracastService/MiracastServiceImplementation.h @@ -0,0 +1,243 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2025 RDK Management +* +* 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. +*/ + +#pragma once + +#include "Module.h" + +#include +#include +#include +#include + +#include +#include "libIARM.h" + +#include +#include +#include +#include + +#include "libIBus.h" + +#include "PowerManagerInterface.h" + +using namespace WPEFramework; +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; +using MiracastPlayerState = WPEFramework::Exchange::IMiracastService::PlayerState; +using MiracastPlayerReasonCode = WPEFramework::Exchange::IMiracastService::PlayerReasonCode; +using MiracastServiceReasonCode = WPEFramework::Exchange::IMiracastService::ReasonCode; + +typedef enum DeviceWiFiStates +{ + DEVICE_WIFI_STATE_UNINSTALLED = 0, + DEVICE_WIFI_STATE_DISABLED = 1, + DEVICE_WIFI_STATE_DISCONNECTED = 2, + DEVICE_WIFI_STATE_PAIRING = 3, + DEVICE_WIFI_STATE_CONNECTING = 4, + DEVICE_WIFI_STATE_CONNECTED = 5, + DEVICE_WIFI_STATE_FAILED = 6 +}DEVICE_WIFI_STATES; + +namespace WPEFramework +{ + namespace Plugin + { + class MiracastServiceImplementation : public Exchange::IMiracastService, public Exchange::IConfiguration, public MiracastServiceNotifier + { + public: + // We do not allow this plugin to be copied !! + MiracastServiceImplementation(); + ~MiracastServiceImplementation() override; + + static MiracastServiceImplementation *instance(MiracastServiceImplementation *MiracastServiceImpl = nullptr); + static MiracastController *m_miracast_ctrler_obj; + + // We do not allow this plugin to be copied !! + MiracastServiceImplementation(const MiracastServiceImplementation &) = delete; + MiracastServiceImplementation &operator=(const MiracastServiceImplementation &) = delete; + + virtual void onMiracastServiceClientConnectionRequest(string client_mac, string client_name) override; + virtual void onMiracastServiceClientConnectionError(string client_mac, string client_name , MiracastServiceReasonCode reason_code ) override; + virtual void onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) override; + virtual void onStateChange(eMIRA_SERVICE_STATES state ) override; + + BEGIN_INTERFACE_MAP(MiracastServiceImplementation) + INTERFACE_ENTRY(Exchange::IMiracastService) + INTERFACE_ENTRY(Exchange::IConfiguration) + END_INTERFACE_MAP + + public: + enum Event + { + MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_REQUEST, + MIRACASTSERVICE_EVENT_CLIENT_CONNECTION_ERROR, + MIRACASTSERVICE_EVENT_PLAYER_LAUNCH_REQUEST + }; + + class EXTERNAL Job : public Core::IDispatch + { + protected: + Job(MiracastServiceImplementation *MiracastServiceImplementation, Event event, JsonObject ¶ms) + : _miracastServiceImplementation(MiracastServiceImplementation), _event(event), _params(params) + { + if (_miracastServiceImplementation != nullptr) + { + _miracastServiceImplementation->AddRef(); + } + } + + public: + Job() = delete; + Job(const Job &) = delete; + Job &operator=(const Job &) = delete; + ~Job() + { + if (_miracastServiceImplementation != nullptr) + { + _miracastServiceImplementation->Release(); + } + } + + public: + static Core::ProxyType Create(MiracastServiceImplementation *miracastServiceImplementation, Event event, JsonObject params) + { + #ifndef USE_THUNDER_R4 + return (Core::proxy_cast(Core::ProxyType::Create(miracastServiceImplementation, event, params))); + #else + return (Core::ProxyType(Core::ProxyType::Create(miracastServiceImplementation, event, params))); + #endif + } + + virtual void Dispatch() + { + _miracastServiceImplementation->Dispatch(_event, _params); + } + + private: + MiracastServiceImplementation *_miracastServiceImplementation; + const Event _event; + JsonObject _params; + }; // class Job + + public: + uint32_t Configure(PluginHost::IShell* service) override; + + Core::hresult Register(Exchange::IMiracastService::INotification *notification) override; + Core::hresult Unregister(Exchange::IMiracastService::INotification *notification) override; + + Core::hresult SetEnabled(const bool enabled , Result &returnPayload ) override; + Core::hresult GetEnabled(bool &enabled , bool &success ) override; + Core::hresult AcceptClientConnection(const string &requestStatus , Result &returnPayload ) override; + Core::hresult StopClientConnection(const string &clientMac , const string &clientName, Result &returnPayload ) override; + Core::hresult UpdatePlayerState(const string &clientMac , const MiracastPlayerState playerState , const int reasonCode , Result &returnPayload ) override; + Core::hresult SetP2PBackendDiscovery(const bool enabled , Result &returnPayload ) override; + + private: + class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification + { + private: + PowerManagerNotification(const PowerManagerNotification&) = delete; + PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; + + public: + explicit PowerManagerNotification(MiracastServiceImplementation& parent) + : _parent(parent) + { + } + ~PowerManagerNotification() override = default; + + public: + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override + { + _parent.onPowerModeChanged(currentState, newState); + } + + template + T* baseInterface() + { + static_assert(std::is_base_of(), "base type mismatch"); + return static_cast(this); + } + + BEGIN_INTERFACE_MAP(PowerManagerNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) + END_INTERFACE_MAP + + private: + MiracastServiceImplementation& _parent; + }; // class PowerManagerNotification + + mutable Core::CriticalSection _adminLock; + std::mutex m_DiscoveryStateMutex; + std::recursive_mutex m_EventMutex; + std::string m_src_dev_ip{""}; + std::string m_src_dev_mac{""}; + std::string m_src_dev_name{""}; + std::string m_sink_dev_ip{""}; + WPEFramework::JSONRPC::LinkType *m_SystemPluginObj = nullptr; + WPEFramework::JSONRPC::LinkType *m_WiFiPluginObj = nullptr; + std::list _miracastServiceNotification; // List of registered notifications + PluginHost::IShell *m_CurrentService; + guint m_FriendlyNameMonitorTimerID{0}; + guint m_WiFiConnectedStateMonitorTimerID{0}; + guint m_MiracastConnectionMonitorTimerID{0}; + eMIRA_SERVICE_STATES m_eService_state; + bool m_isServiceInitialized{false}; + bool m_isServiceEnabled{false}; + + void dispatchEvent(Event, const JsonObject ¶ms); + void Dispatch(Event event, const JsonObject ¶ms); + + eMIRA_SERVICE_STATES getCurrentServiceState(void); + void changeServiceState(eMIRA_SERVICE_STATES eService_state); + bool envGetValue(const char *key, std::string &value); + void getThunderPlugins(void); + bool updateSystemFriendlyName(); + void setEnableInternal(bool isEnabled); + + void InitializePowerManager(PluginHost::IShell *service); + void registerEventHandlers(); + void InitializePowerState(); + std::string getPowerStateString(PowerState pwrState); + void setPowerStateInternal(PowerState pwrState); + + void setWiFiStateInternal(DEVICE_WIFI_STATES wifiState); + + void onFriendlyNameUpdateHandler(const JsonObject ¶meters); + void onWIFIStateChangedHandler(const JsonObject ¶meters); + + static gboolean monitor_friendly_name_timercallback(gpointer userdata); + static gboolean monitor_wifi_connection_state_timercallback(gpointer userdata); + static gboolean monitor_miracast_connection_timercallback(gpointer userdata); + void remove_wifi_connection_state_timer(void); + void remove_miracast_connection_timer(void); + + public: + static MiracastServiceImplementation *_instance; + static PowerManagerInterfaceRef _powerManagerPlugin; + Core::Sink _pwrMgrNotification; + bool _registeredEventHandlers; + + void onPowerModeChanged(const PowerState currentState, const PowerState newState); + + friend class Job; + }; // class MiracastServiceImplementation + } // namespace Plugin +} // namespace WPEFramework \ No newline at end of file diff --git a/Miracast/common/MiracastCommon.h b/Miracast/common/MiracastCommon.h index a632cf45..f527202d 100644 --- a/Miracast/common/MiracastCommon.h +++ b/Miracast/common/MiracastCommon.h @@ -156,19 +156,6 @@ typedef enum emira_service_states_e MIRACAST_SERVICE_STATE_DIRECT_LAUCH_WITH_CONNECTING } eMIRA_SERVICE_STATES; -typedef enum miracast_player_states_e -{ - MIRACAST_PLAYER_STATE_IDLE, - MIRACAST_PLAYER_STATE_INITIATED, - MIRACAST_PLAYER_STATE_INPROGRESS, - MIRACAST_PLAYER_STATE_PLAYING, - MIRACAST_PLAYER_STATE_STOPPED, - MIRACAST_PLAYER_STATE_PAUSED, - // Below are Internal Player States. No need to notify these to subscribers - MIRACAST_PLAYER_STATE_M1_M7_XCHANGE_DONE, - MIRACAST_PLAYER_STATE_SELF_ABORT, -} eMIRA_PLAYER_STATES; - typedef enum miracast_gstplayer_states_e { MIRACAST_GSTPLAYER_STATE_IDLE = 0x01, @@ -179,37 +166,6 @@ typedef enum miracast_gstplayer_states_e MIRACAST_GSTPLAYER_STATE_MAX, } eMIRA_GSTPLAYER_STATES; -typedef enum miracast_service_error_code_e -{ - MIRACAST_SERVICE_ERR_CODE_SUCCESS = 100, - MIRACAST_SERVICE_ERR_CODE_P2P_CONNECT_ERROR, - MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_NEGO_ERROR, - MIRACAST_SERVICE_ERR_CODE_P2P_GROUP_FORMATION_ERROR, - MIRACAST_SERVICE_ERR_CODE_GENERIC_FAILURE, - MIRACAST_SERVICE_ERR_CODE_MAX_ERROR -} eMIRACAST_SERVICE_ERR_CODE; - -typedef enum miracast_player_reason_code_e -{ - MIRACAST_PLAYER_REASON_CODE_SUCCESS = 200, - MIRACAST_PLAYER_REASON_CODE_APP_REQ_TO_STOP, - MIRACAST_PLAYER_REASON_CODE_SRC_DEV_REQ_TO_STOP, - MIRACAST_PLAYER_REASON_CODE_RTSP_ERROR, - MIRACAST_PLAYER_REASON_CODE_RTSP_TIMEOUT, - MIRACAST_PLAYER_REASON_CODE_RTSP_METHOD_NOT_SUPPORTED, - MIRACAST_PLAYER_REASON_CODE_GST_ERROR, - MIRACAST_PLAYER_REASON_CODE_INT_FAILURE, - MIRACAST_PLAYER_REASON_CODE_NEW_SRC_DEV_CONNECT_REQ, - MIRACAST_PLAYER_REASON_CODE_MAX_ERROR -} eM_PLAYER_REASON_CODE; - -typedef enum miracast_player_stop_reason_code_e -{ - MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_EXIT = 300, - MIRACAST_PLAYER_APP_REQ_TO_STOP_ON_NEW_CONNECTION -} -eM_PLAYER_STOP_REASON_CODE; - typedef struct d_info { string deviceMAC; @@ -241,103 +197,11 @@ typedef struct controller_msgq_st eMSG_TYPE msg_type; } CONTROLLER_MSGQ_STRUCT; -typedef struct rtsp_hldr_msgq_st -{ - char source_dev_ip[24]; - char source_dev_mac[24]; - char sink_dev_ip[24]; - char source_dev_name[40]; - VIDEO_RECT_STRUCT videorect; - eCONTROLLER_FW_STATES state; - eM_PLAYER_STOP_REASON_CODE stop_reason_code; - eM_PLAYER_REASON_CODE state_reason_code; - eMIRA_GSTPLAYER_STATES gst_player_state; -} RTSP_HLDR_MSGQ_STRUCT; - #define CONTROLLER_THREAD_NAME ("CONTROL_MSG_HANDLER") #define CONTROLLER_THREAD_STACK (256 * 1024) #define CONTROLLER_MSGQ_COUNT (5) #define CONTROLLER_MSGQ_SIZE (sizeof(CONTROLLER_MSGQ_STRUCT)) -#define RTSP_HANDLER_THREAD_NAME ("RTSP_MSG_HLDR") -#define RTSP_HANDLER_THREAD_STACK ( 512 * 1024) -#define RTSP_HANDLER_MSG_COUNT (2) -#define RTSP_HANDLER_MSGQ_SIZE (sizeof(RTSP_HLDR_MSGQ_STRUCT)) - -#ifdef ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER -typedef enum miracaset_service_test_notifier_states_e -{ - MIRACAST_SERVICE_TEST_NOTIFIER_INVALID_STATE = 0x00, - MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_REQUESTED, - MIRACAST_SERVICE_TEST_NOTIFIER_LAUNCH_REQUESTED, - MIRACAST_SERVICE_TEST_NOTIFIER_CLIENT_CONNECTION_ERROR, - MIRACAST_SERVICE_TEST_NOTIFIER_SHUTDOWN -}MIRACAST_SERVICE_TEST_NOTIFIER_STATES; - -typedef struct miracast_service_test_notifier_msgq_st -{ - char src_dev_name[128]; - char src_dev_mac_addr[32]; - char src_dev_ip_addr[32]; - char sink_ip_addr[32]; - MIRACAST_SERVICE_TEST_NOTIFIER_STATES state; - eMIRACAST_SERVICE_ERR_CODE error_code; -} -MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST; - -#define MIRACAST_SERVICE_TEST_NOTIFIER_THREAD_NAME ("MIRACAST_SERVICE_TEST_NOTIFIER") -#define MIRACAST_SERVICE_TEST_NOTIFIER_THREAD_STACK (100 * 1024) -#define MIRACAST_SERVICE_TEST_NOTIFIER_MSG_COUNT (1) -#define MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_SIZE (sizeof(MIRACAST_SERVICE_TEST_NOTIFIER_MSGQ_ST)) - -#endif/*ENABLE_MIRACAST_SERVICE_TEST_NOTIFIER*/ - -#ifdef ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER -typedef enum miracaset_player_test_notifier_states_e -{ - MIRACAST_PLAYER_TEST_NOTIFIER_INVALID_STATE = 0x00, - MIRACAST_PLAYER_TEST_NOTIFIER_STATE_CHANGED, - MIRACAST_PLAYER_TEST_NOTIFIER_SHUTDOWN -}MIRACAST_PLAYER_TEST_NOTIFIER_STATES; - -typedef struct miracast_player_test_notifier_msgq_st -{ - char src_dev_name[128]; - char src_dev_mac_addr[32]; - MIRACAST_PLAYER_TEST_NOTIFIER_STATES state; - eMIRA_PLAYER_STATES player_state; - eM_PLAYER_REASON_CODE reason_code; -} -MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST; - -#define MIRACAST_PLAYER_TEST_NOTIFIER_THREAD_NAME ("MIRACAST_PLAYER_TEST_NOTIFIER") -#define MIRACAST_PLAYER_TEST_NOTIFIER_THREAD_STACK (100 * 1024) -#define MIRACAST_PLAYER_TEST_NOTIFIER_MSG_COUNT (1) -#define MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_SIZE (sizeof(MIRACAST_PLAYER_TEST_NOTIFIER_MSGQ_ST)) - -#endif /* ENABLE_MIRACAST_PLAYER_TEST_NOTIFIER */ - -/** - * Abstract class for MiracastService Notification. - */ -class MiracastServiceNotifier -{ -public: - virtual void onMiracastServiceClientConnectionRequest(string client_mac, string client_name) = 0; - virtual void onMiracastServiceClientConnectionError(string client_mac, string client_name , eMIRACAST_SERVICE_ERR_CODE error_code ) = 0; - virtual void onMiracastServiceLaunchRequest(string src_dev_ip, string src_dev_mac, string src_dev_name, string sink_dev_ip, bool is_connect_req_reported ) = 0; - virtual void onStateChange(eMIRA_SERVICE_STATES state ) = 0; -}; - -/** - * Abstract class for MiracastPlayer Notification. - */ -class MiracastPlayerNotifier -{ -public: - virtual void onStateChange(const std::string& client_mac, const std::string& client_name, eMIRA_PLAYER_STATES player_state, eM_PLAYER_REASON_CODE reason_code) = 0; -}; - class MiracastThread { public: diff --git a/Miracast/common/MiracastLogger.cpp b/Miracast/common/MiracastLogger.cpp index 70e51626..c9d2c15f 100644 --- a/Miracast/common/MiracastLogger.cpp +++ b/Miracast/common/MiracastLogger.cpp @@ -1,21 +1,21 @@ /* - * If not stated otherwise in this file or this component's Licenses.txt file the - * following copyright and licenses apply: - * - * Copyright 2023 RDK Management - * - * 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. - */ +* If not stated otherwise in this file or this component's Licenses.txt file the +* following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #include "MiracastLogger.h" #include #include @@ -23,7 +23,6 @@ #include #include #include -#include #include namespace MIRACAST @@ -34,39 +33,17 @@ namespace MIRACAST setvbuf(stdout, NULL, _IOLBF, 0); } - std::string methodName(const std::string &prettyFunction) - { - size_t colons = prettyFunction.find("::"); - size_t begin = prettyFunction.substr(0, colons).rfind(" ") + 1; - size_t end = prettyFunction.rfind("(") - begin; - - return prettyFunction.substr(begin, end); - } - - static int gDefaultLogLevel = INFO_LEVEL; - static FILE *logger_file_ptr = nullptr; + static int gDefaultLogLevel = TRACE_LEVEL; static std::string service_name = "NOT-DEFINED"; - static sem_t separate_logger_sync; void logger_init(const char* module_name) { - const char *separate_logger = getenv("MIRACAST_SEPARATE_LOGGER_ENABLED"); const char *level = getenv("MIRACAST_DEFAULT_LOG_LEVEL"); sync_stdout(); - sem_init(&separate_logger_sync, 0, 1); - if (level) { - gDefaultLogLevel = static_cast(atoi(level)); - } - - if ((nullptr != separate_logger)&&(std::string(separate_logger) == "Yes")) - { - std::string logger_filename = "/opt/logs/"; - logger_filename.append(module_name); - logger_filename.append(".log"); - logger_file_ptr = fopen( logger_filename.c_str() , "a"); + set_loglevel(static_cast(atoi(level))); } if ( nullptr != module_name ) @@ -77,46 +54,7 @@ namespace MIRACAST void logger_deinit() { - if (nullptr != logger_file_ptr) - { - sem_wait(&separate_logger_sync); - fclose(logger_file_ptr); - logger_file_ptr = nullptr; - sem_post(&separate_logger_sync); - } - sem_destroy(&separate_logger_sync); - } - - void enable_separate_logger( std::string filename ) - { - sem_wait(&separate_logger_sync); - if (nullptr != logger_file_ptr) - { - fclose(logger_file_ptr); - logger_file_ptr = nullptr; - } - - if ( filename.empty()) - { - filename = service_name; - } - - std::string logger_filename = "/opt/logs/"; - logger_filename.append(filename); - logger_filename.append(".log"); - logger_file_ptr = fopen( logger_filename.c_str() , "a"); - sem_post(&separate_logger_sync); - } - - void disable_separate_logger( void ) - { - sem_wait(&separate_logger_sync); - if (nullptr != logger_file_ptr) - { - fclose(logger_file_ptr); - logger_file_ptr = nullptr; - } - sem_post(&separate_logger_sync); + /* NOP */ } void set_loglevel(LogLevel level) @@ -124,26 +62,12 @@ namespace MIRACAST gDefaultLogLevel = level; } - void current_time(char *time_str) - { - struct timeval tv; - gettimeofday(&tv, NULL); - - long microseconds = tv.tv_usec; - - // Convert time to human-readable format - struct tm *tm_info; - tm_info = localtime(&tv.tv_sec); - - sprintf(time_str, "%02d:%02d:%02d:%06ld", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, microseconds); - } - void log(LogLevel level, - const char *func, - const char *file, - int line, - int threadID, - const char *format, ...) + const char *func, + const char *file, + int line, + int threadID, + const char *format, ...) { const char *levelMap[] = {"FATAL", "ERROR", "WARN", "INFO", "VERBOSE", "TRACE"}; const short kFormatMessageSize = 4096; @@ -159,61 +83,7 @@ namespace MIRACAST vsnprintf(formatted, kFormatMessageSize, format, argptr); va_end(argptr); - sem_wait(&separate_logger_sync); - if (nullptr!=logger_file_ptr) - { - char timestamp[0xFF] = {0}; - struct timespec spec; - struct tm tm; - - clock_gettime(CLOCK_REALTIME, &spec); - gmtime_r(&spec.tv_sec, &tm); - long ms = spec.tv_nsec / 1.0e6; - - sprintf(timestamp, "%02d%02d%02d-%02d:%02d:%02d.%03ld", - tm.tm_year % 100, - tm.tm_mon + 1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec, - ms); - - if (threadID) - { - fprintf(logger_file_ptr, "%s [%s] [tid=%d] %s:%s:%d %s\n", - timestamp, - levelMap[static_cast(level)], - threadID, - func, basename(file), line, - formatted); - } - else - { - fprintf(logger_file_ptr, "%s [%s] %s:%s:%d %s\n", - timestamp, - levelMap[static_cast(level)], - func, basename(file), line, - formatted); - } - - fflush(logger_file_ptr); - } - else{ - #ifdef UNIT_TESTING - char time[24] = {0}; - current_time(time); - fprintf(stderr, "[%s][%d] %s [%s:%d:%s] %s: %s \n", - service_name.c_str(), - (int)syscall(SYS_gettid), - levelMap[static_cast(level)], - basename(file), - line, - time, - func, - formatted); - #else - fprintf(stderr, "[%s][%d] %s [%s:%d] %s: %s \n", + fprintf(stderr, "[%s][%d] %s [%s:%d] %s: %s \n", service_name.c_str(), (int)syscall(SYS_gettid), levelMap[static_cast(level)], @@ -221,10 +91,6 @@ namespace MIRACAST line, func, formatted); - #endif - - fflush(stderr); - } - sem_post(&separate_logger_sync); + fflush(stderr); } -} // namespace MIRACAST +} // namespace MIRACAST \ No newline at end of file diff --git a/Miracast/common/MiracastLogger.h b/Miracast/common/MiracastLogger.h index 5e34dcea..47d82050 100644 --- a/Miracast/common/MiracastLogger.h +++ b/Miracast/common/MiracastLogger.h @@ -31,9 +31,6 @@ namespace MIRACAST { -std::string methodName(const std::string& prettyFunction); -#define __METHOD_NAME__ MIRACAST::methodName(__PRETTY_FUNCTION__) - /** * Logging level with an increasing order of refinement * (TRACE_LEVEL = Finest logging) @@ -55,8 +52,6 @@ void logger_init(const char* module_name); void logger_deinit(); void set_loglevel(LogLevel level); -void enable_separate_logger( std::string filename = "" ); -void disable_separate_logger( void ); #define MIRACAST_assert(expr) do { \ if ( __builtin_expect(expr, true) ) \ @@ -101,4 +96,4 @@ void log(LogLevel level, } // namespace MIRACAST -#endif // MIRACAST_LOGGER_H +#endif // MIRACAST_LOGGER_H \ No newline at end of file diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index 1a787ff6..cf0cc499 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -108,7 +108,7 @@ endmacro() # PLUGIN_MIRACAST set (MIRACAST_INC ${CMAKE_SOURCE_DIR}/../entservices-casting/Miracast/MiracastPlayer ${CMAKE_SOURCE_DIR}/../entservices-casting/Miracast/MiracastPlayer/RTSP ${CMAKE_SOURCE_DIR}/../entservices-casting/Miracast/MiracastService ${CMAKE_SOURCE_DIR}/../entservices-casting/Miracast/MiracastService/P2P ${CMAKE_SOURCE_DIR}/../entservices-casting/Miracast/common ${CMAKE_SOURCE_DIR}/../entservices-casting/helpers) -set (MIRACAST_LIBS ${NAMESPACE}MiracastPlayer ${NAMESPACE}MiracastService) +set (MIRACAST_LIBS ${NAMESPACE}MiracastPlayer ${NAMESPACE}MiracastService ${NAMESPACE}MiracastServiceImplementation ${NAMESPACE}MiracastPlayerImplementation) set (MIRACAST_SRC tests/test_MiracastService.cpp tests/test_MiracastPlayer.cpp) add_plugin_test_ex(PLUGIN_MIRACAST "${MIRACAST_SRC}" "${MIRACAST_INC}" "${MIRACAST_LIBS}") diff --git a/Tests/L1Tests/tests/test_MiracastPlayer.cpp b/Tests/L1Tests/tests/test_MiracastPlayer.cpp old mode 100644 new mode 100755 index 8b934158..ceefb61d --- a/Tests/L1Tests/tests/test_MiracastPlayer.cpp +++ b/Tests/L1Tests/tests/test_MiracastPlayer.cpp @@ -18,19 +18,28 @@ **/ #include -#include -#include -#include "ServiceMock.h" + #include "MiracastPlayer.h" -#include "WrapsMock.h" -#include #include "FactoriesImplementation.h" - +#include "ServiceMock.h" #include "ThunderPortability.h" -using ::testing::NiceMock; + +#include +#include +#include +#include +#include "COMLinkMock.h" +#include "WrapsMock.h" +#include "WorkerPoolImplementation.h" +#include "MiracastPlayerImplementation.h" +#include +#include +#include + using namespace WPEFramework; +using ::testing::NiceMock; namespace { #define RTSP_SEND (1) @@ -40,1185 +49,1263 @@ namespace { #define PORT (7236) #define TEST_LOG(FMT, ...) log(__func__, __FILE__, __LINE__, syscall(__NR_gettid),FMT,##__VA_ARGS__) - typedef enum rtsp_srcmsg_reqresp - { - RTSP_SEND_M1_REQUEST = 0x00, - RTSP_RECV_M1_RESPONSE, - RTSP_RECV_M2_REQUEST, - RTSP_SEND_M2_RESPONSE, - RTSP_SEND_M3_REQUEST, - RTSP_RECV_M3_RESPONSE, - RTSP_SEND_M4_REQUEST, - RTSP_RECV_M4_RESPONSE, - RTSP_SEND_M5_REQUEST, - RTSP_RECV_M5_RESPONSE, - RTSP_RECV_M6_REQUEST, - RTSP_SEND_M6_RESPONSE, - RTSP_RECV_M7_REQUEST, - RTSP_SEND_M7_RESPONSE, - RTSP_SEND_M16_REQUEST, - RTSP_RECV_M16_RESPONSE, - RTSP_SEND_TEARDOWN_REQUEST, - RTSP_RECV_TEADOWN_RESPONSE, - RTSP_RECV_TEARDOWN_REQUEST, - RTSP_SEND_TEARDOWN_RESPONSE - } - RTSP_SRCMSG_REQ_RESP; - - typedef struct rtsp_src_msg_handler_format - { - int rtsp_sendorreceive; - RTSP_SRCMSG_REQ_RESP rtsp_msg_type; - const char* template_name; - } - RTSP_MSG_HANDLER_FORMAT; - - RTSP_MSG_HANDLER_FORMAT default_rtsp_srcMsgbuffer[] = - { - { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, - { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, - { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, - { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, - { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, - { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" }, - { RTSP_SEND , RTSP_SEND_M4_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 3\r\nContent-Type: text/parameters\r\nContent-Length: 246\r\n\r\nwfd_video_formats: 00 00 02 04 00000080 00000000 00000000 00 0000 0000 00 none none\r\nwfd_audio_codecs: AAC 00000001 00\r\nwfd_presentation_URL: rtsp://192.168.49.1/wfd1.0/streamid=0 none\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1990 0 mode=play\r\n" }, - { RTSP_RECV , RTSP_RECV_M4_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 3\r\n" }, - { RTSP_SEND , RTSP_SEND_M5_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 4\r\nContent-Type: text/parameters\r\nContent-Length: 27\r\n\r\nwfd_trigger_method: SETUP\r\n" }, - { RTSP_RECV , RTSP_RECV_M5_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 4\r\n\r\n" }, - { RTSP_RECV , RTSP_RECV_M6_REQUEST , "SETUP rtsp://192.168.49.1/wfd1.0/streamid=0 RTSP/1.0\r\nTransport: RTP/AVP/UDP;unicast;client_port=1990\r\nCSeq: %s\r\n"}, - { RTSP_SEND , RTSP_SEND_M6_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nTransport: RTP/AVP/UDP;unicast;client_port=1991-1992;server_port=19000-19001\r\n" }, - { RTSP_RECV , RTSP_RECV_M7_REQUEST , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, - { RTSP_SEND , RTSP_SEND_M7_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, - { RTSP_SEND , RTSP_SEND_M16_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 5\r\nSession: 1804289383\r\n"}, - { RTSP_RECV , RTSP_RECV_M16_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 5\r\n" } - //{ RTSP_SEND , RTSP_SEND_TEARDOWN_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n" }, - //{ RTSP_RECV , RTSP_RECV_TEADOWN_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 6\r\n" } - }; - - int default_rtsp_srcMsgSize = static_cast(sizeof(default_rtsp_srcMsgbuffer) / sizeof(default_rtsp_srcMsgbuffer[0])); - int server_fd = -1, client_fd = -1; - struct sockaddr_in server_addr, client_addr; - int opt = 1; - - void current_time(char *time_str) - { - struct timeval tv; - gettimeofday(&tv, NULL); - - long microseconds = tv.tv_usec; - - // Convert time to human-readable format - struct tm *tm_info; - tm_info = localtime(&tv.tv_sec); - - sprintf(time_str, ": %02d:%02d:%02d:%06ld", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, microseconds); - } - - void log( const char *func, const char *file, int line, int threadID,const char *format, ...) - { - const short kFormatMessageSize = 4096; - char formatted[kFormatMessageSize]; - char time[24] = {0}; - va_list argptr; - - current_time(time); - - va_start(argptr, format); - vsnprintf(formatted, kFormatMessageSize, format, argptr); - va_end(argptr); - - fprintf(stderr, "[GUNIT][%d] INFO [%s:%d %s] %s: %s \n", + typedef enum rtsp_srcmsg_reqresp + { + RTSP_SEND_M1_REQUEST = 0x00, + RTSP_RECV_M1_RESPONSE, + RTSP_RECV_M2_REQUEST, + RTSP_SEND_M2_RESPONSE, + RTSP_SEND_M3_REQUEST, + RTSP_RECV_M3_RESPONSE, + RTSP_SEND_M4_REQUEST, + RTSP_RECV_M4_RESPONSE, + RTSP_SEND_M5_REQUEST, + RTSP_RECV_M5_RESPONSE, + RTSP_RECV_M6_REQUEST, + RTSP_SEND_M6_RESPONSE, + RTSP_RECV_M7_REQUEST, + RTSP_SEND_M7_RESPONSE, + RTSP_SEND_M16_REQUEST, + RTSP_RECV_M16_RESPONSE, + RTSP_SEND_TEARDOWN_REQUEST, + RTSP_RECV_TEADOWN_RESPONSE, + RTSP_RECV_TEARDOWN_REQUEST, + RTSP_SEND_TEARDOWN_RESPONSE + } + RTSP_SRCMSG_REQ_RESP; + + typedef struct rtsp_src_msg_handler_format + { + int rtsp_sendorreceive; + RTSP_SRCMSG_REQ_RESP rtsp_msg_type; + const char* template_name; + } + RTSP_MSG_HANDLER_FORMAT; + + RTSP_MSG_HANDLER_FORMAT default_rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, + { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" }, + { RTSP_SEND , RTSP_SEND_M4_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 3\r\nContent-Type: text/parameters\r\nContent-Length: 246\r\n\r\nwfd_video_formats: 00 00 02 04 00000080 00000000 00000000 00 0000 0000 00 none none\r\nwfd_audio_codecs: AAC 00000001 00\r\nwfd_presentation_URL: rtsp://192.168.49.1/wfd1.0/streamid=0 none\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1990 0 mode=play\r\n" }, + { RTSP_RECV , RTSP_RECV_M4_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 3\r\n" }, + { RTSP_SEND , RTSP_SEND_M5_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 4\r\nContent-Type: text/parameters\r\nContent-Length: 27\r\n\r\nwfd_trigger_method: SETUP\r\n" }, + { RTSP_RECV , RTSP_RECV_M5_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 4\r\n\r\n" }, + { RTSP_RECV , RTSP_RECV_M6_REQUEST , "SETUP rtsp://192.168.49.1/wfd1.0/streamid=0 RTSP/1.0\r\nTransport: RTP/AVP/UDP;unicast;client_port=1990\r\nCSeq: %s\r\n"}, + { RTSP_SEND , RTSP_SEND_M6_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nTransport: RTP/AVP/UDP;unicast;client_port=1991-1992;server_port=19000-19001\r\n" }, + { RTSP_RECV , RTSP_RECV_M7_REQUEST , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, + { RTSP_SEND , RTSP_SEND_M7_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: 1804289383;timeout=30\r\nRange: npt=now-\r\n" }, + { RTSP_SEND , RTSP_SEND_M16_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 5\r\nSession: 1804289383\r\n"}, + { RTSP_RECV , RTSP_RECV_M16_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 5\r\n" } + //{ RTSP_SEND , RTSP_SEND_TEARDOWN_REQUEST , "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n" }, + //{ RTSP_RECV , RTSP_RECV_TEADOWN_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: 6\r\n" } + }; + + int default_rtsp_srcMsgSize = static_cast(sizeof(default_rtsp_srcMsgbuffer) / sizeof(default_rtsp_srcMsgbuffer[0])); + int server_fd = -1, client_fd = -1; + struct sockaddr_in server_addr, client_addr; + int opt = 1; + + void current_time(char *time_str) + { + struct timeval tv; + gettimeofday(&tv, NULL); + + long microseconds = tv.tv_usec; + + // Convert time to human-readable format + struct tm *tm_info; + tm_info = localtime(&tv.tv_sec); + + sprintf(time_str, ": %02d:%02d:%02d:%06ld", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, microseconds); + } + + void log( const char *func, const char *file, int line, int threadID,const char *format, ...) + { + const short kFormatMessageSize = 4096; + char formatted[kFormatMessageSize]; + char time[24] = {0}; + va_list argptr; + + current_time(time); + + va_start(argptr, format); + vsnprintf(formatted, kFormatMessageSize, format, argptr); + va_end(argptr); + + fprintf(stderr, "[GUNIT][%d] INFO [%s:%d %s] %s: %s \n", (int)syscall(SYS_gettid), basename(file), line, - time, + time, func, formatted); - fflush(stderr); - } - - static void removeFile(const char* fileName) - { - if (std::remove(fileName) != 0) - { - TEST_LOG("ERROR: deleting File [%s] ...",strerror(errno)); - } - else - { - TEST_LOG("File %s successfully deleted", fileName); - } - } - - static void createFile(const char* fileName, const char* fileContent) - { - removeFile(fileName); - - std::ofstream fileContentStream(fileName); - fileContentStream << fileContent; - fileContentStream << "\n"; - fileContentStream.close(); - TEST_LOG("File %s successfully created", fileName); - } - - const char* get_RequestResponseFormat(RTSP_MSG_HANDLER_FORMAT *pstRTSPSrcHldrFmt , int index , size_t rtsp_msg_fmt_count ) - { - if (index >= 0 && index < static_cast(rtsp_msg_fmt_count)) - { - return pstRTSPSrcHldrFmt[index].template_name; - } - return ""; - } - - std::string parse_received_parser_field_value(std::string rtsp_msg_buffer , const char* given_tag ) - { - std::string seq_str = ""; - std::stringstream ss(rtsp_msg_buffer); - std::string prefix = ""; - std::string line; - - while (std::getline(ss, line)) - { - if (line.find(given_tag) != std::string::npos) - { - prefix = given_tag; - seq_str = line.substr(prefix.length()); - REMOVE_R(seq_str); - REMOVE_N(seq_str); - break; - } - } - return seq_str; - } - - void send_rtsp_msg( int sockfd , std::string msg_buffer ) - { - usleep(500000); - TEST_LOG("Send Msg[%lu][%s]...",msg_buffer.size(),msg_buffer.c_str()); - send(sockfd, msg_buffer.c_str(), msg_buffer.size(), 0); - } - - /* - * Wait for data returned by the socket for specified time - */ - bool wait_data_timeout(int m_Sockfd, unsigned int ms) - { - struct timeval timeout = {0}; - fd_set readFDSet; - bool returnValue = false; - - FD_ZERO(&readFDSet); - FD_SET(m_Sockfd, &readFDSet); - - timeout.tv_sec = (ms / 1000); - timeout.tv_usec = ((ms % 1000) * 1000); - - if (select(m_Sockfd + 1, &readFDSet, nullptr, nullptr, &timeout) > 0) - { - returnValue = FD_ISSET(m_Sockfd, &readFDSet); - } - return returnValue; - } - - bool recv_rtsp_msg(int socket_fd, void *buffer, size_t buffer_len ) - { - int recv_return = -1; - bool status = true; - - TEST_LOG("Entering "); - if (!wait_data_timeout(socket_fd, 15000 )) - { - TEST_LOG("ERROR: Exiting Timeout "); - return false; - } - else - { - recv_return = recv(socket_fd, buffer, buffer_len, 0); - } - - if (recv_return <= 0) - { - if (errno == EAGAIN || errno == EWOULDBLOCK) - { - TEST_LOG("ERROR:recv timed out ..."); - status = false; - } - else - { - TEST_LOG("ERROR: recv failed [%s] ...",strerror(errno)); - status = false; - } - } - TEST_LOG("recv string [%s][%d] ...",buffer,recv_return); - return status; - } - - bool initialize_ServerSocket(void) - { - // Create socket file descriptor - if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { - perror("socket failed"); - return false; - } - - fcntl(server_fd, F_SETFL, O_NONBLOCK); - TEST_LOG("#### NON_BLOCKING Socket Enabled ####"); - - // Forcefully attaching socket to the port 7236 - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { - perror("setsockopt"); - close(server_fd); - server_fd = -1; - return false; - } - - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(PORT); - - // Bind the socket to localhost port 7236 - if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - perror("bind failed"); - close(server_fd); - server_fd = -1; - return false; - } - return true; - } - - void release_SocketDescriptor(void) - { - if ( -1 != server_fd ) - { - close(server_fd); - server_fd = -1; - } - if ( -1 != client_fd ) - { - close(client_fd); - client_fd = -1; - } - } - - void runRTSPSourceHandler(RTSP_MSG_HANDLER_FORMAT* custom_src_msg_buffer, size_t rtsp_msg_count , std::string & response_buffer ) - { - int addrlen = sizeof(server_addr); - char buffer[BUFFER_SIZE] = {0}; - - response_buffer = "FAIL"; - - if( -1 == server_fd ) - { - return; - } - // Listen for incoming connections - if (listen(server_fd, 3) < 0) { - perror("listen"); - return; - } - - if (!wait_data_timeout(server_fd, 30000 )) - { - // connection timed out or failed - TEST_LOG("Socket Connection Timedout %s received(%d)...", strerror(errno), errno); - response_buffer = "FAIL"; - return; - } - else - { - // Accept an incoming connection - if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addrlen)) < 0) { - perror("accept"); - return; - } - TEST_LOG("socket accept done"); - } - - response_buffer = "SUCCESS"; - - std::string receivedCSeqNum = ""; - size_t current_msg = 0; - - while ( current_msg < rtsp_msg_count ) - { - RTSP_SRCMSG_REQ_RESP rtsp_msg_type = custom_src_msg_buffer[current_msg].rtsp_msg_type; - int rtsp_sendorreceive = custom_src_msg_buffer[current_msg].rtsp_sendorreceive; - const char* rtsp_req_resp_format = get_RequestResponseFormat(custom_src_msg_buffer,current_msg,rtsp_msg_count); - std::string msg_buffer = ""; - - memset( buffer , 0x00 , sizeof(buffer)); - TEST_LOG("Index[%d] RTSP Msg[%x]",current_msg,rtsp_msg_type); - - if ( RTSP_SEND == rtsp_sendorreceive ) - { - TEST_LOG("RTSP_SEND"); - switch (rtsp_msg_type) - { - case RTSP_SEND_M1_REQUEST: - case RTSP_SEND_M3_REQUEST: - case RTSP_SEND_M4_REQUEST: - case RTSP_SEND_M5_REQUEST: - case RTSP_SEND_M16_REQUEST: - case RTSP_SEND_TEARDOWN_REQUEST: - { - TEST_LOG("RTSP_SEND REQUEST Messages"); - msg_buffer = rtsp_req_resp_format; - } - break; - case RTSP_SEND_M2_RESPONSE: - case RTSP_SEND_M6_RESPONSE: - case RTSP_SEND_M7_RESPONSE: - case RTSP_SEND_TEARDOWN_RESPONSE: - { - std::string temp_buffer = rtsp_req_resp_format; - - TEST_LOG("RTSP_SEND RESPONSE Messages"); - if (temp_buffer.find("%s") != std::string::npos) - { - sprintf( buffer , rtsp_req_resp_format , receivedCSeqNum.c_str()); - msg_buffer = buffer; - TEST_LOG("Response sequence number replaced as [%s]",receivedCSeqNum.c_str()); - receivedCSeqNum.clear(); - } - else - { - msg_buffer = rtsp_req_resp_format; - } - } - break; - default: - { - - } - break; - } - if ( !msg_buffer.empty()) - { - send_rtsp_msg( client_fd , msg_buffer ); - } - } - else - { - TEST_LOG("RTSP_RECV"); - bool status = recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); - msg_buffer = buffer; - if ((msg_buffer.find("TEARDOWN") == 0) || (false == status )) - { - TEST_LOG("TEARDOWN initiated from Sink Device[%x]",status); - response_buffer = "SUCCESS"; - break; - } - switch (rtsp_msg_type) - { - case RTSP_RECV_M1_RESPONSE: - case RTSP_RECV_M4_RESPONSE: - case RTSP_RECV_M5_RESPONSE: - case RTSP_RECV_M16_RESPONSE: - case RTSP_RECV_TEADOWN_RESPONSE: - { - msg_buffer = rtsp_req_resp_format; - - if ( 0 != strncmp( buffer , rtsp_req_resp_format , strlen(rtsp_req_resp_format))) - { - response_buffer = "FAIL"; - TEST_LOG("ERROR: expected[%s] actual[%s]",rtsp_req_resp_format,buffer); - } - else if ( strlen(buffer) > strlen(rtsp_req_resp_format) ) - { - if (( RTSP_RECV_M1_RESPONSE == rtsp_msg_type ) || - ( RTSP_RECV_M5_RESPONSE == rtsp_msg_type )) - { - int processedBytes = strlen(rtsp_req_resp_format), - totalLen = strlen(buffer); - std::string temp_buffer = buffer; - std::string response = temp_buffer.substr(0,processedBytes); - EXPECT_EQ(response,string(rtsp_req_resp_format)); - std::string request = temp_buffer.substr(processedBytes, totalLen - processedBytes); - receivedCSeqNum = parse_received_parser_field_value( request , "CSeq: " ); - TEST_LOG("Parsed Response + Request[%s][%s]",response.c_str(),request.c_str()); - TEST_LOG("processedBytes[%d]totalLen[%d]",processedBytes,totalLen); - EXPECT_TRUE(!receivedCSeqNum.empty()); - TEST_LOG("Skipping to RTSP_RECV REQUEST Messages"); - ++current_msg; - } - } - } - break; - case RTSP_RECV_M3_RESPONSE: - { - TEST_LOG("RTSP_RECV M3 RESPONSE Messages"); - std::string expected_sequence_number = parse_received_parser_field_value( msg_buffer , "CSeq: " ), - actual_sequence_number = parse_received_parser_field_value( rtsp_req_resp_format , "CSeq: " ); - - if ( 0 != expected_sequence_number.compare(actual_sequence_number)) - { - response_buffer = "FAIL"; - TEST_LOG("Error: expected[%s]actual[%s]",msg_buffer.c_str(),rtsp_req_resp_format); - } - } - break; - case RTSP_RECV_M2_REQUEST: - case RTSP_RECV_M6_REQUEST: - case RTSP_RECV_M7_REQUEST: - { - TEST_LOG("RTSP_RECV REQUEST Messages"); - receivedCSeqNum = parse_received_parser_field_value( msg_buffer , "CSeq: " ); - } - break; - default: - { - break; - } - } - } - ++current_msg; - - if ( 0 == response_buffer.compare("FAIL")) - { - TEST_LOG("ERROR: RESPONSE FAILED"); - break; - } - } - - if ( 0 == response_buffer.compare("FAIL")) - { - TEST_LOG("ERROR: RTSP Msg Exchange Failed"); - } - else - { - TEST_LOG("RTSP Msg Exchange Success"); - } - } + fflush(stderr); + } + + static void removeFile(const char* fileName) + { + if (std::remove(fileName) != 0) + { + TEST_LOG("ERROR: deleting File [%s] ...",strerror(errno)); + } + else + { + TEST_LOG("File %s successfully deleted", fileName); + } + } + + static void createFile(const char* fileName, const char* fileContent) + { + removeFile(fileName); + + std::ofstream fileContentStream(fileName); + fileContentStream << fileContent; + fileContentStream << "\n"; + fileContentStream.close(); + TEST_LOG("File %s successfully created", fileName); + } + + const char* get_RequestResponseFormat(RTSP_MSG_HANDLER_FORMAT *pstRTSPSrcHldrFmt , int index , size_t rtsp_msg_fmt_count ) + { + if (index >= 0 && index < static_cast(rtsp_msg_fmt_count)) + { + return pstRTSPSrcHldrFmt[index].template_name; + } + return ""; + } + + std::string parse_received_parser_field_value(std::string rtsp_msg_buffer , const char* given_tag ) + { + std::string seq_str = ""; + std::stringstream ss(rtsp_msg_buffer); + std::string prefix = ""; + std::string line; + + while (std::getline(ss, line)) + { + if (line.find(given_tag) != std::string::npos) + { + prefix = given_tag; + seq_str = line.substr(prefix.length()); + REMOVE_R(seq_str); + REMOVE_N(seq_str); + break; + } + } + return seq_str; + } + + void send_rtsp_msg( int sockfd , const std::string &msg_buffer ) + { + usleep(500000); + TEST_LOG("Send Msg[%lu][%s]...",msg_buffer.size(),msg_buffer.c_str()); + ssize_t bytes_sent = send(sockfd, msg_buffer.c_str(), msg_buffer.size(), 0); + + if (bytes_sent < 0) + { + TEST_LOG("ERROR: send failed [%s]...", strerror(errno)); + } + else if (static_cast(bytes_sent) < msg_buffer.size()) + { + // Partial send occurred + TEST_LOG("Partial message sent: %ld bytes out of %lu", bytes_sent, msg_buffer.size()); + } + else + { + TEST_LOG("Sent %ld bytes successfully", bytes_sent); + } + } + + /* + * Wait for data returned by the socket for specified time + */ + bool wait_data_timeout(int m_Sockfd, unsigned int ms) + { + struct timeval timeout = {0}; + fd_set readFDSet; + bool returnValue = false; + + FD_ZERO(&readFDSet); + FD_SET(m_Sockfd, &readFDSet); + + timeout.tv_sec = (ms / 1000); + timeout.tv_usec = ((ms % 1000) * 1000); + + if (select(m_Sockfd + 1, &readFDSet, nullptr, nullptr, &timeout) > 0) + { + returnValue = FD_ISSET(m_Sockfd, &readFDSet); + } + return returnValue; + } + + bool recv_rtsp_msg(int socket_fd, void *buffer, size_t buffer_len, int* bytes_processed_ptr ) + { + int recv_return = -1; + bool status = true; + + if (nullptr == bytes_processed_ptr) + { + TEST_LOG("ERROR: Invalid Argument"); + return false; + } + + TEST_LOG("Entering "); + if (!wait_data_timeout(socket_fd, 15000 )) + { + TEST_LOG("ERROR: Exiting Timeout "); + return false; + } + else + { + recv_return = recv(socket_fd, buffer, buffer_len, 0); + } + + if (recv_return <= 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { + TEST_LOG("ERROR:recv timed out ..."); + } + else + { + TEST_LOG("ERROR: recv failed [%s] ...",strerror(errno)); + } + status = false; + *bytes_processed_ptr = 0; + } + else + { + *bytes_processed_ptr = recv_return; + TEST_LOG("recv string [%s][%d] ...", (char*)buffer,recv_return); + } + return status; + } + + bool initialize_ServerSocket(void) + { + // Create socket file descriptor + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + return false; + } + + fcntl(server_fd, F_SETFL, O_NONBLOCK); + TEST_LOG("#### NON_BLOCKING Socket Enabled ####"); + + // Forcefully attaching socket to the port 7236 + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt"); + close(server_fd); + server_fd = -1; + return false; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(PORT); + + // Bind the socket to localhost port 7236 + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("bind failed"); + close(server_fd); + server_fd = -1; + return false; + } + return true; + } + + void release_SocketDescriptor(void) + { + if ( -1 != server_fd ) + { + close(server_fd); + server_fd = -1; + } + if ( -1 != client_fd ) + { + close(client_fd); + client_fd = -1; + } + } + + void runRTSPSourceHandler(RTSP_MSG_HANDLER_FORMAT* custom_src_msg_buffer, size_t rtsp_msg_count , std::string & response_buffer ) + { + int addrlen = sizeof(server_addr); + char buffer[BUFFER_SIZE] = {0}; + + response_buffer = "FAIL"; + + if( -1 == server_fd ) + { + return; + } + // Listen for incoming connections + if (listen(server_fd, 3) < 0) { + perror("listen"); + return; + } + + if (!wait_data_timeout(server_fd, 30000 )) + { + // connection timed out or failed + TEST_LOG("Socket Connection Timedout %s received(%d)...", strerror(errno), errno); + response_buffer = "FAIL"; + return; + } + else + { + // Accept an incoming connection + if ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addrlen)) < 0) { + perror("accept"); + return; + } + TEST_LOG("socket accept done"); + } + + response_buffer = "SUCCESS"; + + std::string receivedCSeqNum = ""; + size_t current_msg = 0; + + while ( current_msg < rtsp_msg_count ) + { + RTSP_SRCMSG_REQ_RESP rtsp_msg_type = custom_src_msg_buffer[current_msg].rtsp_msg_type; + int rtsp_sendorreceive = custom_src_msg_buffer[current_msg].rtsp_sendorreceive; + const char* rtsp_req_resp_format = get_RequestResponseFormat(custom_src_msg_buffer,current_msg,rtsp_msg_count); + std::string msg_buffer = ""; + + memset( buffer , 0x00 , sizeof(buffer)); + TEST_LOG("Index[%d] RTSP Msg[%x]",current_msg,rtsp_msg_type); + + if ( RTSP_SEND == rtsp_sendorreceive ) + { + TEST_LOG("RTSP_SEND"); + switch (rtsp_msg_type) + { + case RTSP_SEND_M1_REQUEST: + case RTSP_SEND_M3_REQUEST: + case RTSP_SEND_M4_REQUEST: + case RTSP_SEND_M5_REQUEST: + case RTSP_SEND_M16_REQUEST: + case RTSP_SEND_TEARDOWN_REQUEST: + { + TEST_LOG("RTSP_SEND REQUEST Messages"); + msg_buffer = rtsp_req_resp_format; + } + break; + case RTSP_SEND_M2_RESPONSE: + case RTSP_SEND_M6_RESPONSE: + case RTSP_SEND_M7_RESPONSE: + case RTSP_SEND_TEARDOWN_RESPONSE: + { + std::string temp_buffer = rtsp_req_resp_format; + + TEST_LOG("RTSP_SEND RESPONSE Messages"); + if (temp_buffer.find("%s") != std::string::npos) + { + sprintf( buffer , rtsp_req_resp_format , receivedCSeqNum.c_str()); + msg_buffer = buffer; + TEST_LOG("Response sequence number replaced as [%s]",receivedCSeqNum.c_str()); + receivedCSeqNum.clear(); + } + else + { + msg_buffer = rtsp_req_resp_format; + } + } + break; + default: + { + + } + break; + } + if ( !msg_buffer.empty()) + { + send_rtsp_msg( client_fd , msg_buffer ); + } + } + else + { + int bytes_processed = 0; + TEST_LOG("RTSP_RECV"); + bool status = recv_rtsp_msg( client_fd , buffer , sizeof(buffer), &bytes_processed); + buffer[bytes_processed] = '\0'; // Null-terminate the received string + msg_buffer = buffer; + if ((false == status ) || (msg_buffer.find("TEARDOWN") == 0)) + { + TEST_LOG("TEARDOWN initiated from Sink Device[%x]",status); + response_buffer = "SUCCESS"; + break; + } + switch (rtsp_msg_type) + { + case RTSP_RECV_M1_RESPONSE: + case RTSP_RECV_M4_RESPONSE: + case RTSP_RECV_M5_RESPONSE: + case RTSP_RECV_M16_RESPONSE: + case RTSP_RECV_TEADOWN_RESPONSE: + { + msg_buffer = rtsp_req_resp_format; + + if ( 0 != strncmp( buffer , rtsp_req_resp_format , strlen(rtsp_req_resp_format))) + { + response_buffer = "FAIL"; + TEST_LOG("ERROR: expected[%s] actual[%s]",rtsp_req_resp_format,buffer); + } + else if ( strlen(buffer) > strlen(rtsp_req_resp_format) ) + { + if (( RTSP_RECV_M1_RESPONSE == rtsp_msg_type ) || + ( RTSP_RECV_M5_RESPONSE == rtsp_msg_type )) + { + int processedBytes = strlen(rtsp_req_resp_format), + totalLen = strlen(buffer); + std::string temp_buffer = buffer; + std::string response = temp_buffer.substr(0,processedBytes); + EXPECT_EQ(response,string(rtsp_req_resp_format)); + std::string request = temp_buffer.substr(processedBytes, totalLen - processedBytes); + receivedCSeqNum = parse_received_parser_field_value( request , "CSeq: " ); + TEST_LOG("Parsed Response + Request[%s][%s]",response.c_str(),request.c_str()); + TEST_LOG("processedBytes[%d]totalLen[%d]",processedBytes,totalLen); + EXPECT_TRUE(!receivedCSeqNum.empty()); + TEST_LOG("Skipping to RTSP_RECV REQUEST Messages"); + ++current_msg; + } + } + } + break; + case RTSP_RECV_M3_RESPONSE: + { + TEST_LOG("RTSP_RECV M3 RESPONSE Messages"); + std::string expected_sequence_number = parse_received_parser_field_value( msg_buffer , "CSeq: " ), + actual_sequence_number = parse_received_parser_field_value( rtsp_req_resp_format , "CSeq: " ); + + if ( 0 != expected_sequence_number.compare(actual_sequence_number)) + { + response_buffer = "FAIL"; + TEST_LOG("Error: expected[%s]actual[%s]",msg_buffer.c_str(),rtsp_req_resp_format); + } + } + break; + case RTSP_RECV_M2_REQUEST: + case RTSP_RECV_M6_REQUEST: + case RTSP_RECV_M7_REQUEST: + { + TEST_LOG("RTSP_RECV REQUEST Messages"); + receivedCSeqNum = parse_received_parser_field_value( msg_buffer , "CSeq: " ); + } + break; + default: + { + break; + } + } + } + ++current_msg; + + if ( 0 == response_buffer.compare("FAIL")) + { + TEST_LOG("ERROR: RESPONSE FAILED"); + break; + } + } + + if ( 0 == response_buffer.compare("FAIL")) + { + TEST_LOG("ERROR: RTSP Msg Exchange Failed"); + } + else + { + TEST_LOG("RTSP Msg Exchange Success"); + } + } } class MiracastPlayerTest : public ::testing::Test { - protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - DECL_CORE_JSONRPC_CONX connection; - string response; - ServiceMock service; - WrapsImplMock *p_wrapsImplMock = nullptr; - - MiracastPlayerTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , INIT_CONX(1, 0) - { - p_wrapsImplMock = new NiceMock ; - Wraps::setImpl(p_wrapsImplMock); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillRepeatedly(::testing::Invoke( - [&](const uint32_t, const string& name) -> void* { - return nullptr; - })); - ON_CALL(*p_wrapsImplMock, system(::testing::_)) - .WillByDefault(::testing::Invoke([&](const char* command) {return 0;})); - EXPECT_EQ(string(""), plugin->Initialize(&service)); - } - virtual ~MiracastPlayerTest() override - { - plugin->Deinitialize(nullptr); - Wraps::setImpl(nullptr); - if (p_wrapsImplMock != nullptr) - { - delete p_wrapsImplMock; - p_wrapsImplMock = nullptr; - } - } +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + WrapsImplMock *p_wrapsImplMock = nullptr; + Core::ProxyType miracastPlayerImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + + NiceMock factoriesImplementation; + + MiracastPlayerTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + p_wrapsImplMock = new NiceMock; + printf("Pass created wrapsImplMock: %p ", p_wrapsImplMock); + Wraps::setImpl(p_wrapsImplMock); + + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + TEST_LOG("Pass created comLinkMock: %p ", &comLinkMock); + return &comLinkMock; + })); + + + #ifdef USE_THUNDER_R4 + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + miracastPlayerImpl = Core::ProxyType::Create(); + TEST_LOG("Pass created miracastPlayerImpl: %p ", &miracastPlayerImpl); + return &miracastPlayerImpl; + })); + #else + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(miracastPlayerImpl)); + #endif /*USE_THUNDER_R4 */ + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + + EXPECT_EQ(string(""), plugin->Initialize(&service)); + } + virtual ~MiracastPlayerTest() override + { + TEST_LOG("MiracastPlayerTest Destructor"); + + plugin->Deinitialize(&service); + + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + PluginHost::IFactories::Assign(nullptr); + IarmBus::setImpl(nullptr); + } }; class MiracastPlayerEventTest : public MiracastPlayerTest { - protected: - NiceMock service; - NiceMock factoriesImplementation; - PLUGINHOST_DISPATCHER* dispatcher; - Core::JSONRPC::Message message; - - MiracastPlayerEventTest() - : MiracastPlayerTest() - { - PluginHost::IFactories::Assign(&factoriesImplementation); - - dispatcher = static_cast( - plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); - dispatcher->Activate(&service); - } - - virtual ~MiracastPlayerEventTest() override - { - dispatcher->Deactivate(); - dispatcher->Release(); - - PluginHost::IFactories::Assign(nullptr); - } +protected: + NiceMock service; + NiceMock factoriesImplementation; + PLUGINHOST_DISPATCHER* dispatcher; + Core::JSONRPC::Message message; + + MiracastPlayerEventTest() + : MiracastPlayerTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + } + + virtual ~MiracastPlayerEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } }; TEST_F(MiracastPlayerTest, RegisteredMethods) { - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("playRequest"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopRequest"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setPlayerState"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLogging"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("playRequest"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopRequest"))); + EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); } -TEST_F(MiracastPlayerTest, Logging) +TEST_F(MiracastPlayerTest, GetInformation) { - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"ENABLE\",\"logfilename\": \"GTest\"}}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"VERBOSE\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"WARNING\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"ERROR\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"FATAL\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"TRACE\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"INFO\"}"), response)); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"UNKNOWN\"}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"DISABLE\",\"logfilename\": \"GTest\"}}"), response)); + EXPECT_EQ("This MiracastPlayer Plugin Facilitates Miracast session like RTSP communication and GStreamer Playback", plugin->Information()); } -TEST_F(MiracastPlayerTest, setRTSPWaitTimeOutAndAVFormats) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setRTSPWaitTimeOut"), _T("{\"Request\": 10000,\"Response\": 10000}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoFormats"), _T("{\"native\": 0x02,\"display_mode_supported\": false,\"h264_codecs\": [{\"profile\": 0x01,\"level\": 0x08,\"cea_mask\": 0x00010000,\"vesa_mask\": 0x00000000,\"hh_mask\": 0x00000000,\"latency\": 0,\"min_slice\": 0,\"slice_encode\": 0,\"video_frame_skip_support\": true,\"max_skip_intervals\": 0,\"video_frame_rate_change_support\": false}]}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setAudioFormats"), _T("{\"audio_codecs\": [{\"audio_format\": 0x01,\"modes\": 0x00000002,\"latency\": 0}]}"), response)); -} - -#if 0 TEST_F(MiracastPlayerEventTest, APP_REQUESTED_TO_STOP) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Playing(false, true); - Core::Event Stopped(false, true); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"PLAYING\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Playing.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"201\"," - "\"reason\":\"APP REQUESTED TO STOP.\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - - EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); - - sleep(2); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 300}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); - release_SocketDescriptor(); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json){ + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"201\"," + "\"reason\":\"APP_REQ_TO_STOP\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Invalid Video Rectangle Coords\",\"success\":false}")); + + sleep(2); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); + EXPECT_EQ(response, string("{\"message\":\"UNKNOWN STOP REASON CODE RECEIVED\",\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 300}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } TEST_F(MiracastPlayerEventTest, APP_REQ_TO_STOP_FOR_NEW_CONNECTION) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Playing(false, true); - Core::Event Stopped(false, true); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"PLAYING\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Playing.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"208\"," - "\"reason\":\"APP REQ TO STOP FOR NEW CONNECTION.\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - - EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); - - sleep(2); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 301}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); - release_SocketDescriptor(); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"208\"," + "\"reason\":\"NEW_SRC_DEV_CONNECT_REQ\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + sleep(2); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 303}"), response)); + EXPECT_EQ(response, string("{\"message\":\"UNKNOWN STOP REASON CODE RECEIVED\",\"success\":false}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopRequest"), _T("{\"reason_code\": 301}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } TEST_F(MiracastPlayerEventTest, SRC_DEV_REQUESTED_TO_STOP) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Playing(false, true); - Core::Event Stopped(false, true); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"PLAYING\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Playing.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"202\"," - "\"reason\":\"SRC DEVICE REQUESTED TO STOP.\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - - EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"X\": 0,\"Y\": 0,\"W\": 1280,\"H\": 720}"), response)); - - char buffer[BUFFER_SIZE] = {0}; - std::string teardown_request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n"; - std::string teardown_response = "RTSP/1.0 200 OK\r\nCSeq: 6\r\n\r\n", - temp_buffer = ""; - - send_rtsp_msg(client_fd,teardown_request); - recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); - temp_buffer = buffer; - - EXPECT_EQ(teardown_response, temp_buffer); - - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); - release_SocketDescriptor(); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"202\"," + "\"reason\":\"SRC_DEV_REQ_TO_STOP\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + + char buffer[BUFFER_SIZE] = {0}; + std::string teardown_request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n"; + std::string teardown_response = "RTSP/1.0 200 OK\r\nCSeq: 6\r\n\r\n", + temp_buffer = ""; + int processed_bytes = 0; + + send_rtsp_msg(client_fd,teardown_request); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer), &processed_bytes); + buffer[processed_bytes] = '\0'; // Null-terminate the received string + temp_buffer = buffer; + + EXPECT_EQ(teardown_response, temp_buffer); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } -#endif + TEST_F(MiracastPlayerEventTest, RTSP_TimeOut) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Stopped(false, true); - RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = - { - { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, - { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, - { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, - { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\nGET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, - { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" } - }; - - int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"204\"," - "\"reason\":\"RTSP Timeout.\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(25000)); - - release_SocketDescriptor(); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Stopped(false, true); + RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\nGET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\nwfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" }, + { RTSP_RECV , RTSP_RECV_M3_RESPONSE , "RTSP/1.0 200 OK\r\nContent-Length: 210\r\nContent-Type: text/parameters\r\nCSeq: 2\r\n\r\nwfd_content_protection: none\r\nwfd_video_formats: 00 00 03 10 0001ffff 1fffffff 00001fff 00 0000 0000 10 none none\r\nwfd_audio_codecs: AAC 00000007 00\r\nwfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play\r\n" } + }; + + int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"204\"," + "\"reason\":\"RTSP_TIMEOUT\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(25000)); + + release_SocketDescriptor(); + + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } TEST_F(MiracastPlayerEventTest, RTSP_Failure) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Stopped(false, true); - RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = - { - { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, - { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, - { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, - { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, - { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\n" }, - { RTSP_SEND , RTSP_SEND_M3_REQUEST , "wfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" } - }; - - int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"203\"," - "\"reason\":\"RTSP Failure.\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - sleep(2); - release_SocketDescriptor(); - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Stopped(false, true); + RTSP_MSG_HANDLER_FORMAT rtsp_srcMsgbuffer[] = + { + { RTSP_SEND , RTSP_SEND_M1_REQUEST , "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nServer: AllShareCast/Galaxy/Android13\r\nRequire: org.wfa.wfd1.0\r\n"}, + { RTSP_RECV , RTSP_RECV_M1_RESPONSE , "RTSP/1.0 200 OK\r\nPublic: \"org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\"\r\nCSeq: 1\r\n\r\n"}, + { RTSP_RECV , RTSP_RECV_M2_REQUEST , "OPTIONS * RTSP/1.0\r\nRequire: org.wfa.wfd1.0\r\nCSeq: %s"}, + { RTSP_SEND , RTSP_SEND_M2_RESPONSE , "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 2\r\nContent-Type: text/parameters\r\nContent-Length: 211\r\n\r\nwfd_video_formats\r\nwfd_audio_codecs\r\nwfd_uibc_capability\r\nwfd_client_rtp_ports\r\nwfd_content_protection\r\nwfd_sec_screensharing\r\n" }, + { RTSP_SEND , RTSP_SEND_M3_REQUEST , "wfd_sec_portrait_display\r\nwfd_sec_rotation\r\nwfd_sec_hw_rotation\r\nwfd_sec_framerate\r\n" } + }; + + int rtsp_srcMsgSize = static_cast(sizeof(rtsp_srcMsgbuffer) / sizeof(rtsp_srcMsgbuffer[0])); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( rtsp_srcMsgbuffer , rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"203\"," + "\"reason\":\"RTSP_FAILURE\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + sleep(2); + release_SocketDescriptor(); + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } -#if 0 + TEST_F(MiracastPlayerEventTest, setPlayerState) { - std::string rtsp_response = ""; - Core::Event Initiated(false, true); - Core::Event Inprogress(false, true); - Core::Event Playing(false, true); - Core::Event Stopped(false, true); - - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INITIATED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Initiated.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"INPROGRESS\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Inprogress.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"PLAYING\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Playing.SetEvent(); - return Core::ERROR_NONE; - })) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text,string(_T("{" - "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," - "\"params\":{\"mac\":\"A1:B2:C3:D4:E5:F6\"," - "\"name\":\"Sample-Android-Test-1\"," - "\"state\":\"STOPPED\"," - "\"reason_code\":\"200\"," - "\"reason\":\"SUCCESS\"" - "}}" - ))); - Stopped.SetEvent(); - return Core::ERROR_NONE; - })); - - EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); - EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); - - serverThread.join(); - EXPECT_EQ(rtsp_response, string("SUCCESS")); - - EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); + std::string rtsp_response = ""; + Core::Event Initiated(false, true); + Core::Event Inprogress(false, true); + Core::Event Playing(false, true); + Core::Event Stopped(false, true); + + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + + EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) + .Times(::testing::AnyNumber()) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INITIATED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Initiated.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"INPROGRESS\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Inprogress.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"PLAYING\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Playing.SetEvent(); + return Core::ERROR_NONE; + })) + .WillOnce(::testing::Invoke( + [&](const uint32_t, const Core::ProxyType& json) { + string text; + EXPECT_TRUE(json->ToString(text)); + EXPECT_EQ(text,string(_T("{" + "\"jsonrpc\":\"2.0\",\"method\":\"client.events.onStateChange\"," + "\"params\":{\"name\":\"Sample-Android-Test-1\"," + "\"mac\":\"A1:B2:C3:D4:E5:F6\"," + "\"state\":\"STOPPED\"," + "\"reason_code\":\"200\"," + "\"reason\":\"SUCCESS\"" + "}}" + ))); + Stopped.SetEvent(); + return Core::ERROR_NONE; + })); + + EVENT_SUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, Initiated.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, Inprogress.Lock(10000)); + + serverThread.join(); + EXPECT_EQ(rtsp_response, string("SUCCESS")); + + EXPECT_EQ(Core::ERROR_NONE, Playing.Lock(10000)); - char buffer[BUFFER_SIZE] = {0}; - //std::string trigger_request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\nCSeq: 6\r\nContent-Type: text/parameters\r\nContent-Length: 30\r\n\r\nwfd_trigger_method: TEARDOWN\r\n"; - std::string trigger_response = "", - temp_buffer = ""; - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"PAUSE\"}"), response)); - recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); - temp_buffer = buffer; - std::string receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); - EXPECT_TRUE(temp_buffer.find("PAUSE") == 0); - trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; - send_rtsp_msg(client_fd,trigger_response); - receivedCSeqNum.clear(); - memset(buffer,0x00,sizeof(buffer)); - - sleep(2); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"PLAY\"}"), response)); - recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); - temp_buffer = buffer; - receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); - EXPECT_TRUE(temp_buffer.find("PLAY") == 0); - trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; - send_rtsp_msg(client_fd,trigger_response); - receivedCSeqNum.clear(); - memset(buffer,0x00,sizeof(buffer)); - - sleep(2); - - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"UNKNOWN\"}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setPlayerState"), _T("{\"state\": \"STOP\"}"), response)); - recv_rtsp_msg( client_fd , buffer , sizeof(buffer)); - temp_buffer = buffer; - receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); - EXPECT_TRUE(temp_buffer.find("TEARDOWN") == 0); - trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; - send_rtsp_msg(client_fd,trigger_response); - receivedCSeqNum.clear(); - memset(buffer,0x00,sizeof(buffer)); - - EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); - release_SocketDescriptor(); - - EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); + char buffer[BUFFER_SIZE] = {0}; + RTSP_HLDR_MSGQ_STRUCT rtsp_hldr_msgq_data = {0}; + std::string trigger_response = "", + temp_buffer = ""; + + if (Plugin::MiracastPlayerImplementation::_instance->m_miracast_rtsp_obj) + { + int processed_bytes = 0; + rtsp_hldr_msgq_data.state = RTSP_PAUSE_FROM_SINK2SRC; + Plugin::MiracastPlayerImplementation::_instance->m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer), &processed_bytes); + buffer[processed_bytes] = '\0'; // Null-terminate the received string + temp_buffer = buffer; + std::string receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("PAUSE") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + + sleep(2); + + rtsp_hldr_msgq_data.state = RTSP_PLAY_FROM_SINK2SRC; + Plugin::MiracastPlayerImplementation::_instance->m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer), &processed_bytes); + buffer[processed_bytes] = '\0'; // Null-terminate the received string + temp_buffer = buffer; + receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("PLAY") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + + sleep(2); + + rtsp_hldr_msgq_data.state = RTSP_TEARDOWN_FROM_SINK2SRC; + Plugin::MiracastPlayerImplementation::_instance->m_miracast_rtsp_obj->send_msgto_rtsp_msg_hdler_thread(rtsp_hldr_msgq_data); + recv_rtsp_msg( client_fd , buffer , sizeof(buffer), &processed_bytes); + buffer[processed_bytes] = '\0'; // Null-terminate the received string + temp_buffer = buffer; + receivedCSeqNum = parse_received_parser_field_value( temp_buffer , "CSeq: " ); + EXPECT_TRUE(temp_buffer.find("TEARDOWN") == 0); + trigger_response = "RTSP/1.0 200 OK\r\nCSeq: " + receivedCSeqNum + "\r\n\r\n"; + send_rtsp_msg(client_fd,trigger_response); + receivedCSeqNum.clear(); + memset(buffer,0x00,sizeof(buffer)); + EXPECT_EQ(Core::ERROR_NONE, Stopped.Lock(10000)); + release_SocketDescriptor(); + } + EVENT_UNSUBSCRIBE(0, _T("onStateChange"), _T("client.events"), message); } -#endif + TEST_F(MiracastPlayerTest, AutoConnectOptFlag) { - std::string rtsp_response = ""; - createFile("/opt/miracast_autoconnect","GTest"); + std::string rtsp_response = ""; + createFile("/opt/miracast_autoconnect","GTest"); - sleep(2); - EXPECT_TRUE(initialize_ServerSocket()); - std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); + sleep(2); + EXPECT_TRUE(initialize_ServerSocket()); + std::thread serverThread = std::thread([&]() { runRTSPSourceHandler( default_rtsp_srcMsgbuffer , default_rtsp_srcMsgSize , rtsp_response ); }); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("playRequest"), _T("{\"device_parameters\": {\"source_dev_ip\":\"127.0.0.1\",\"source_dev_mac\": \"A1:B2:C3:D4:E5:F6\",\"source_dev_name\":\"Sample-Android-Test-1\",\"sink_dev_ip\":\"192.168.59.1\"},\"video_rectangle\": {\"X\": 0,\"Y\" : 0,\"W\": 1920,\"H\": 1080}}"), response)); - serverThread.join(); - sleep(2); - release_SocketDescriptor(); - removeFile("/opt/miracast_autoconnect"); - sleep(2); + serverThread.join(); + sleep(2); + release_SocketDescriptor(); + removeFile("/opt/miracast_autoconnect"); + sleep(2); } + +TEST_F(MiracastPlayerTest, SetOrUnsetEnvArguments) +{ + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWesterosEnvironment"), _T("{\"westerosArgs\":[{\"argName\":\"WAYLAND_DISPLAY\",\"argValue\":\"westeros-testplayer-0\"},{\"argName\":\"XDG_RUNTIME_DIR\",\"argValue\":\"/tmp\"}],\"appName\":\"MiracastApp\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("unsetWesterosEnvironment"), _T("{}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWesterosEnvironment"), _T("{\"westerosArgs\":[{\"argName\":\"DISPLAY\",\"argValue\":\"display-testplayer-0\"},{\"argName\":\"XDG_RUNTIME_DIR\",\"argValue\":\"/tmp\"}],\"appName\":\"MiracastApp\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Failed, Missing Wayland Display Name\",\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnvArguments"), _T("{\"envArgs\":[{\"argName\":\"WAYLAND_DISPLAY\",\"argValue\":\"westeros-testplayer-0\"},{\"argName\":\"XDG_RUNTIME_DIR\",\"argValue\":\"/tmp\"}],\"appName\":\"MiracastApp\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("unsetEnvArguments"), _T("{}"), response)); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnvArguments"), _T("{\"envArgs\":[{\"argName\":\"DISPLAY\",\"argValue\":\"display-testplayer-0\"},{\"argName\":\"XDG_RUNTIME_DIR\",\"argValue\":\"/tmp\"}],\"appName\":\"MiracastApp\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Failed, Missing Wayland Display Name\",\"success\":false}")); +} \ No newline at end of file diff --git a/Tests/L1Tests/tests/test_MiracastService.cpp b/Tests/L1Tests/tests/test_MiracastService.cpp index 8713a0d5..74cee193 100755 --- a/Tests/L1Tests/tests/test_MiracastService.cpp +++ b/Tests/L1Tests/tests/test_MiracastService.cpp @@ -17,20 +17,32 @@ * limitations under the License. **/ - #include + +#include "MiracastService.h" + #include "FactoriesImplementation.h" #include "ServiceMock.h" -#include "MiracastService.h" -#include "wpa_ctrl_mock.h" -#include "WrapsMock.h" -#include "IarmBusMock.h" #include "ThunderPortability.h" +#include "PowerManagerMock.h" + +#include +#include +#include +#include +#include "COMLinkMock.h" +#include "WrapsMock.h" +#include "WorkerPoolImplementation.h" +#include "MiracastServiceImplementation.h" +#include +#include -using ::testing::NiceMock; using namespace WPEFramework; +using ::testing::NiceMock; namespace { + #define TEST_LOG(FMT, ...) log(__func__, __FILE__, __LINE__, syscall(__NR_gettid),FMT,##__VA_ARGS__) + static void removeFile(const char* fileName) { if (std::remove(fileName) != 0) @@ -84,37 +96,95 @@ namespace fileContentStream << "\n"; fileContentStream.close(); } + void current_time(char *time_str) + { + struct timeval tv; + gettimeofday(&tv, NULL); + + long microseconds = tv.tv_usec; + + // Convert time to human-readable format + struct tm *tm_info; + tm_info = localtime(&tv.tv_sec); + + sprintf(time_str, ": %02d:%02d:%02d:%06ld", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, microseconds); + } + void log( const char *func, const char *file, int line, int threadID,const char *format, ...) + { + const short kFormatMessageSize = 4096; + char formatted[kFormatMessageSize]; + char time[24] = {0}; + va_list argptr; + + current_time(time); + + va_start(argptr, format); + vsnprintf(formatted, kFormatMessageSize, format, argptr); + va_end(argptr); + + fprintf(stderr, "[GUNIT][%d] INFO [%s:%d %s] %s: %s \n", + (int)syscall(SYS_gettid), + basename(file), + line, + time, + func, + formatted); + fflush(stderr); + } } static struct wpa_ctrl global_wpa_ctrl_handle; class MiracastServiceTest : public ::testing::Test { - protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - DECL_CORE_JSONRPC_CONX connection; - string response; - ServiceMock service; - WrapsImplMock *p_wrapsImplMock = nullptr; - IarmBusImplMock *p_iarmBusImplMock = nullptr; - IARM_EventHandler_t pwrMgrEventHandler; - - MiracastServiceTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , INIT_CONX(1, 0) - - { - p_wrapsImplMock = new NiceMock ; - Wraps::setImpl(p_wrapsImplMock); - - p_iarmBusImplMock = new testing::NiceMock ; - IarmBus::setImpl(p_iarmBusImplMock); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillRepeatedly(::testing::Invoke([&](const uint32_t, const string& name) -> void* { return nullptr; })); - ON_CALL(*p_wrapsImplMock, wpa_ctrl_open(::testing::_)) +protected: + Core::ProxyType plugin; + Core::JSONRPC::Handler& handler; + DECL_CORE_JSONRPC_CONX connection; + Core::JSONRPC::Message message; + string response; + + WrapsImplMock *p_wrapsImplMock = nullptr; + Core::ProxyType miracastServiceImpl; + + NiceMock comLinkMock; + NiceMock service; + PLUGINHOST_DISPATCHER* dispatcher; + Core::ProxyType workerPool; + + NiceMock factoriesImplementation; + + MiracastServiceTest() + : plugin(Core::ProxyType::Create()) + , handler(*(plugin)) + , INIT_CONX(1, 0) + , workerPool(Core::ProxyType::Create(2, Core::Thread::DefaultStackSize(), 16)) + { + p_wrapsImplMock = new NiceMock; + printf("Pass created wrapsImplMock: %p ", p_wrapsImplMock); + Wraps::setImpl(p_wrapsImplMock); + + ON_CALL(service, COMLink()) + .WillByDefault(::testing::Invoke( + [this]() { + TEST_LOG("Pass created comLinkMock: %p ", &comLinkMock); + return &comLinkMock; + })); + + + #ifdef USE_THUNDER_R4 + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Invoke( + [&](const RPC::Object& object, const uint32_t waitTime, uint32_t& connectionId) { + miracastServiceImpl = Core::ProxyType::Create(); + TEST_LOG("Pass created miracastServiceImpl: %p ", &miracastServiceImpl); + return &miracastServiceImpl; + })); + #else + ON_CALL(comLinkMock, Instantiate(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(miracastServiceImpl)); + #endif /*USE_THUNDER_R4 */ + + ON_CALL(*p_wrapsImplMock, wpa_ctrl_open(::testing::_)) .WillByDefault(::testing::Invoke([&](const char *ctrl_path) { return &global_wpa_ctrl_handle; })); ON_CALL(*p_wrapsImplMock, wpa_ctrl_close(::testing::_)) .WillByDefault(::testing::Invoke([&](struct wpa_ctrl *) { return; })); @@ -124,74 +194,73 @@ class MiracastServiceTest : public ::testing::Test { .WillByDefault(::testing::Invoke([&](struct wpa_ctrl *ctrl) { return false; })); ON_CALL(*p_wrapsImplMock, system(::testing::_)) .WillByDefault(::testing::Invoke([&](const char* command) {return 0;})); -#if 0 // will fix in RDK-55557 - ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) - .WillByDefault(::testing::Invoke([&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler){ - if ((string(IARM_BUS_PWRMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_PWRMGR_EVENT_MODECHANGED)) { - pwrMgrEventHandler = handler; - } - return IARM_RESULT_SUCCESS; - })); - ON_CALL(*p_iarmBusImplMock, IARM_Bus_Call) - .WillByDefault([](const char* ownerName, const char* methodName, void* arg, size_t argLen){ - if (strcmp(methodName, IARM_BUS_PWRMGR_API_GetPowerState) == 0){ - auto* param = static_cast(arg); - param->curState = IARM_BUS_PWRMGR_POWERSTATE_ON; - } - return IARM_RESULT_SUCCESS; - }); -#endif - } - virtual ~MiracastServiceTest() override - { - Wraps::setImpl(nullptr); - if (p_wrapsImplMock != nullptr) - { - delete p_wrapsImplMock; - p_wrapsImplMock = nullptr; - } - - IarmBus::setImpl(nullptr); - if (p_iarmBusImplMock != nullptr) - { - delete p_iarmBusImplMock; - p_iarmBusImplMock = nullptr; - } - } + + PluginHost::IFactories::Assign(&factoriesImplementation); + + Core::IWorkerPool::Assign(&(*workerPool)); + workerPool->Run(); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + } + virtual ~MiracastServiceTest() override + { + TEST_LOG("MiracastServiceTest Destructor"); + + dispatcher->Deactivate(); + dispatcher->Release(); + + Core::IWorkerPool::Assign(nullptr); + workerPool.Release(); + + Wraps::setImpl(nullptr); + if (p_wrapsImplMock != nullptr) + { + delete p_wrapsImplMock; + p_wrapsImplMock = nullptr; + } + PluginHost::IFactories::Assign(nullptr); + } }; class MiracastServiceEventTest : public MiracastServiceTest { - protected: - NiceMock service; - NiceMock factoriesImplementation; - PLUGINHOST_DISPATCHER* dispatcher; - Core::JSONRPC::Message message; - - MiracastServiceEventTest() - : MiracastServiceTest() - { - PluginHost::IFactories::Assign(&factoriesImplementation); - - dispatcher = static_cast( - plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); - dispatcher->Activate(&service); - } - - virtual ~MiracastServiceEventTest() override - { - dispatcher->Deactivate(); - dispatcher->Release(); - - PluginHost::IFactories::Assign(nullptr); - } +protected: + NiceMock service; + NiceMock factoriesImplementation; + PLUGINHOST_DISPATCHER* dispatcher; + Core::JSONRPC::Message message; + + MiracastServiceEventTest() + : MiracastServiceTest() + { + PluginHost::IFactories::Assign(&factoriesImplementation); + + dispatcher = static_cast( + plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); + dispatcher->Activate(&service); + } + + virtual ~MiracastServiceEventTest() override + { + dispatcher->Deactivate(); + dispatcher->Release(); + + PluginHost::IFactories::Assign(nullptr); + } }; +TEST_F(MiracastServiceTest, GetInformation) +{ + EXPECT_EQ("This MiracastService Plugin Facilitates Peer-to-Peer Control and WFD Source Device Discovery", plugin->Information()); +} + TEST_F(MiracastServiceTest, P2PCtrlInterfaceNameNotFound) { removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - //EXPECT_EQ(string("WIFI_P2P_CTRL_INTERFACE not configured in device properties file"), plugin->Initialize(&service)); - EXPECT_EQ("WIFI_P2P_CTRL_INTERFACE not configured in device properties file", plugin->Initialize(&service)); + // WIFI_P2P_CTRL_INTERFACE not configured in device properties file + EXPECT_NE(string(""), plugin->Initialize(&service)); plugin->Deinitialize(nullptr); } @@ -200,13 +269,13 @@ TEST_F(MiracastServiceTest, P2PCtrlInterfacePathNotFound) removeFile("/var/run/wpa_supplicant/p2p0"); createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - //EXPECT_EQ(string("Invalid P2P Ctrl iface configured"), plugin->Initialize(&service)); - EXPECT_EQ("Invalid P2P Ctrl iface configured", plugin->Initialize(&service)); + // Invalid P2P Ctrl iface configured + EXPECT_NE(string(""), plugin->Initialize(&service)); plugin->Deinitialize(nullptr); removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); } -#if 0 + TEST_F(MiracastServiceTest, RegisteredMethods) { createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); @@ -219,17 +288,13 @@ TEST_F(MiracastServiceTest, RegisteredMethods) EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("acceptClientConnection"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopClientConnection"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("updatePlayerState"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setLogging"))); EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setP2PBackendDiscovery"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getStatus"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setWiFiState"))); plugin->Deinitialize(nullptr); removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); removeFile("/var/run/wpa_supplicant/p2p0"); } -#endif TEST_F(MiracastServiceTest, P2P_DiscoveryStatus) { @@ -241,8 +306,8 @@ TEST_F(MiracastServiceTest, P2P_DiscoveryStatus) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); EXPECT_EQ(response, string("{\"message\":\"Successfully enabled the WFD Discovery\",\"success\":true}")); - /* @return : {"message":"WFD Discovery already enabled.","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); + EXPECT_EQ(response, string("{\"message\":\"WFD Discovery already enabled.\",\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnable"), _T("{}"), response)); EXPECT_EQ(response, string("{\"enabled\":true,\"success\":true}")); @@ -250,8 +315,8 @@ TEST_F(MiracastServiceTest, P2P_DiscoveryStatus) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); EXPECT_EQ(response, string("{\"message\":\"Successfully disabled the WFD Discovery\",\"success\":true}")); - /* @return : {"message":"WFD Discovery already disabled.","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"message\":\"WFD Discovery already disabled.\",\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getEnable"), _T("{}"), response)); EXPECT_EQ(response, string("{\"enabled\":false,\"success\":true}")); @@ -271,37 +336,10 @@ TEST_F(MiracastServiceTest, BackendDiscoveryStatus) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setP2PBackendDiscovery"), _T("{\"enabled\": true}"), response)); - /* @return : {"message":"Invalid parameter passed","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setP2PBackendDiscovery"), _T("{\"enable\": true}"), response)); - - plugin->Deinitialize(nullptr); - - removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - removeFile("/var/run/wpa_supplicant/p2p0"); -} - -TEST_F(MiracastServiceTest, Logging) -{ - createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - createFile("/var/run/wpa_supplicant/p2p0","p2p0"); - - EXPECT_EQ(string(""), plugin->Initialize(&service)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"ENABLE\",\"logfilename\": \"GTest\"}}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"VERBOSE\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"WARNING\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"ERROR\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"FATAL\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"TRACE\"}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"INFO\"}"), response)); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setLogging"), _T("{\"level\": \"UNKNOWN\"}"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setLogging"), _T("{\"separate_logger\": {\"status\":\"DISABLE\",\"logfilename\": \"GTest\"}}"), response)); plugin->Deinitialize(nullptr); removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); removeFile("/var/run/wpa_supplicant/p2p0"); - removeFile("/opt/logs/GTest.log"); } TEST_F(MiracastServiceEventTest, stopClientConnection) @@ -377,18 +415,20 @@ TEST_F(MiracastServiceEventTest, stopClientConnection) EXPECT_EQ(Core::ERROR_NONE, connectRequest.Lock(10000)); - /* @return : {"message":"Supported 'requestStatus' parameter values are Accept or Reject","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Timeout}"), response)); - /* @return : {"message":"Invalid parameter passed","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"request\": Accept}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Timeout}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Supported 'requestStatus' parameter values are Accept or Reject\",\"success\":false}")); + + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"request\": Accept}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Supported 'requestStatus' parameter values are Accept or Reject\",\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("acceptClientConnection"), _T("{\"requestStatus\": Accept}"), response)); sleep(2); - /* @return : {"message":"Invalid MAC and Name","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Invalid MAC and Name\",\"success\":false}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Invalid MAC and Name\",\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); @@ -554,6 +594,9 @@ TEST_F(MiracastServiceEventTest, P2P_GOMode_onClientConnectionAndLaunchRequest) EXPECT_EQ(Core::ERROR_NONE, P2PGrpStart.Lock(10000)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Invalid state to process stopClientConnection\",\"success\":false}")); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"INITIATED\"}"), response)); sleep(1); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"INPROGRESS\"}"), response)); @@ -561,11 +604,11 @@ TEST_F(MiracastServiceEventTest, P2P_GOMode_onClientConnectionAndLaunchRequest) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"PLAYING\"}"), response)); sleep(1); - /* @return : {"message":"Failed as MiracastPlayer already Launched.","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Failed as MiracastPlayer already Launched\",\"success\":false}")); - /* @return : {"message":"stopClientConnection received after Launch","success":false}*/ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopClientConnection"), _T("{\"name\": \"Sample-Test-Android-2\",\"mac\": \"96:52:44:b6:7d:14\"}"), response)); + EXPECT_EQ(response, string("{\"message\":\"Invalid state to process stopClientConnection\",\"success\":false}")); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("updatePlayerState"), _T("{\"mac\": \"96:52:44:b6:7d:14\",\"state\":\"STOPPED\"}"), response)); @@ -733,7 +776,7 @@ TEST_F(MiracastServiceEventTest, P2P_CONNECT_FAIL_onClientConnectionError) "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," "\"name\":\"Sample-Test-Android-2\"," "\"error_code\":\"101\"," - "\"reason\":\"P2P CONNECT FAILURE.\"" + "\"reason\":\"P2P_CONNECT_FAILURE\"" "}" "}"))); P2PConnectFail.SetEvent(); @@ -847,7 +890,7 @@ TEST_F(MiracastServiceEventTest, P2P_GO_NEGOTIATION_FAIL_onClientConnectionError "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," "\"name\":\"Sample-Test-Android-2\"," "\"error_code\":\"102\"," - "\"reason\":\"P2P GROUP NEGOTIATION FAILURE.\"" + "\"reason\":\"P2P_GROUP_NEGOTIATION_FAILURE\"" "}" "}"))); P2PGoFail.SetEvent(); @@ -968,7 +1011,7 @@ TEST_F(MiracastServiceEventTest, P2P_GO_FORMATION_FAIL_onClientConnectionError) "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," "\"name\":\"Sample-Test-Android-2\"," "\"error_code\":\"103\"," - "\"reason\":\"P2P GROUP FORMATION FAILURE.\"" + "\"reason\":\"P2P_GROUP_FORMATION_FAILURE\"" "}" "}"))); P2PGoFail.SetEvent(); @@ -1706,7 +1749,7 @@ TEST_F(MiracastServiceEventTest, P2P_ClientMode_GENERIC_FAILURE) "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," "\"name\":\"Sample-Test-Android-2\"," "\"error_code\":\"104\"," - "\"reason\":\"P2P GENERIC FAILURE.\"" + "\"reason\":\"GENERIC_FAILURE\"" "}" "}" ))); @@ -1846,7 +1889,7 @@ TEST_F(MiracastServiceEventTest, P2P_GOMode_GENERIC_FAILURE) "\"params\":{\"mac\":\"96:52:44:b6:7d:14\"," "\"name\":\"Sample-Test-Android-2\"," "\"error_code\":\"104\"," - "\"reason\":\"P2P GENERIC FAILURE.\"" + "\"reason\":\"GENERIC_FAILURE\"" "}" "}" ))); @@ -1970,10 +2013,9 @@ TEST_F(MiracastServiceEventTest, P2P_GOMode_AutoConnect) removeFile("/var/run/wpa_supplicant/p2p0"); removeFile("/opt/miracast_autoconnect"); } -#if 0 // will fix in RDK-55557 + TEST_F(MiracastServiceEventTest, powerStateChange) { - IARM_Bus_PWRMgr_EventData_t param; createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); createFile("/var/run/wpa_supplicant/p2p0","p2p0"); @@ -1981,87 +2023,15 @@ TEST_F(MiracastServiceEventTest, powerStateChange) EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); - param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; - param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; - pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); - - param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; - param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; - pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); - sleep(5); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); - - param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_ON; - param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; - pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); - + Plugin::MiracastServiceImplementation::_instance->onPowerModeChanged(WPEFramework::Exchange::IPowerManager::POWER_STATE_ON, WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP); + Plugin::MiracastServiceImplementation::_instance->onPowerModeChanged(WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP, WPEFramework::Exchange::IPowerManager::POWER_STATE_ON); + sleep(5); + Plugin::MiracastServiceImplementation::_instance->onPowerModeChanged(WPEFramework::Exchange::IPowerManager::POWER_STATE_ON, WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": false}"), response)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":false,\"state\":\"0\",\"powerState\":\"DEEP_SLEEP\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); - - param.data.state.curState = IARM_BUS_PWRMGR_POWERSTATE_STANDBY_DEEP_SLEEP; - param.data.state.newState = IARM_BUS_PWRMGR_POWERSTATE_ON; - pwrMgrEventHandler(IARM_BUS_PWRMGR_NAME, IARM_BUS_PWRMGR_EVENT_MODECHANGED, ¶m, 0); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":false,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":true,\"wifiState\":false,\"success\":true}")); - + Plugin::MiracastServiceImplementation::_instance->onPowerModeChanged(WPEFramework::Exchange::IPowerManager::POWER_STATE_STANDBY_DEEP_SLEEP, WPEFramework::Exchange::IPowerManager::POWER_STATE_ON); EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); - sleep(5); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); - plugin->Deinitialize(nullptr); removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); removeFile("/var/run/wpa_supplicant/p2p0"); -} - -TEST_F(MiracastServiceEventTest, wifiStateChange) -{ - createFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - createFile("/var/run/wpa_supplicant/p2p0","p2p0"); - - EXPECT_EQ(string(""), plugin->Initialize(&service)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setEnable"), _T("{\"enabled\": true}"), response)); - - // Setting WiFi Connecting State - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 4 }"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":true,\"success\":true}")); - - // Setting WiFi Connected State - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 5 }"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); - - // Setting WiFi Connecting State - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 4 }"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"0\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":true,\"success\":true}")); - - // Setting WiFi Connect Failed State - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setWiFiState"), _T("{\"state\": 6 }"), response)); - - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getStatus"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"enabled\":true,\"state\":\"1\",\"powerState\":\"ON\",\"DeepSleepTransition\":false,\"wifiState\":false,\"success\":true}")); - - plugin->Deinitialize(nullptr); - - removeEntryFromFile("/etc/device.properties","WIFI_P2P_CTRL_INTERFACE=p2p0"); - removeFile("/var/run/wpa_supplicant/p2p0"); -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/build_dependencies.sh b/build_dependencies.sh index e8dbd045..2ecb8f54 100644 --- a/build_dependencies.sh +++ b/build_dependencies.sh @@ -31,7 +31,7 @@ git clone --branch R4.4.3 https://github.com/rdkcentral/ThunderTools.git git clone --branch R4.4.1 https://github.com/rdkcentral/Thunder.git -git clone --branch main https://github.com/rdkcentral/entservices-apis.git +git clone --branch develop https://github.com/rdkcentral/entservices-apis.git git clone https://$GITHUB_TOKEN@github.com/rdkcentral/entservices-testframework.git