From: YoungHun Kim Date: Wed, 12 Jun 2024 10:19:09 +0000 (+0900) Subject: Initial Release X-Git-Tag: accepted/tizen/unified/20240801.021620~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=302d3f1275766516728df270f6b716e1f0952ea2;p=platform%2Fcore%2Fmultimedia%2Frscmgr-service.git Initial Release Change-Id: I6539ef377a33ff79fde7ca709507e8f6e6adec62 --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8162b6a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,117 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6...2.29.2) +PROJECT(rscmgr-service CXX) + +SET(PKG_MODULES + vconf + dlog + glib-2.0 + gio-unix-2.0 + capi-system-info + resource-information + capi-system-info + libtzplatform-config + ttrace + aul + wayland-client +) +SET(EXTERN_DEBUG_MODULES + syspopup + syspopup-caller +) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED ${PKG_MODULES}) +pkg_check_modules(extern_debug_pkgs REQUIRED ${EXTERN_DEBUG_MODULES}) + + +IF(NOT DEFINED PACKAGE_NAME) + SET(PACKAGE_NAME ${PROJECT_NAME}) +ENDIF(NOT DEFINED PACKAGE_NAME) + +ADD_DEFINITIONS(-DLIBDIR="${LIBDIR}") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wformat -Wl,--as-needed -Wl,--rpath=${LIBDIR} -pie") + +SET(RSCMGR_SRCS + src/rms_service.cpp + src/manager/CConsumer.cpp + src/manager/CDebugUtils.cpp + src/manager/CResource.cpp + src/manager/CResourceCategory.cpp + src/manager/CResourceDB.cpp + src/manager/CResourceState.cpp + src/manager/CResourceManager.cpp + src/manager/CVirtualResource.cpp + src/manager/CConsumerContainer.cpp + src/manager/CPriority.cpp + src/manager/CCache.cpp + src/manager/CVideoController.cpp + src/manager/CLockController.cpp + src/manager/dependence/CDependencyController.cpp + src/manager/dependence/CMemCluster.cpp + src/manager/dependence/CAudioCodec.cpp + src/manager/dependence/CAudioCodecCollection.cpp + src/manager/dependence/CBandwidth.cpp + src/manager/dependence/CMixingMode.cpp + src/manager/strategy/CAllocateStrategyProvider.cpp + src/manager/strategy/CAllocateStrategy.cpp + src/manager/strategy/CNormalStrategy.cpp + src/manager/strategy/CVideoDecoderStrategy.cpp + src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp + src/manager/strategy/CAudioDecoderStrategy.cpp + src/manager/strategy/CAllocateModeStrategyProvider.cpp + src/manager/strategy/CNormalModeStrategy.cpp + src/manager/strategy/CPreferenceModeStrategy.cpp + src/manager/strategy/CInvalidModeStrategy.cpp + src/manager/strategy/CMixingStrategy.cpp + src/manager/strategy/CExclusiveStrategy.cpp + src/manager/strategy/CScalerStrategy.cpp + src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp + src/CMessage.cpp + src/CDbusHandler.cpp + src/CHandleManager.cpp + src/CHandle.cpp + src/CCallback.cpp + src/CResourceService.cpp + src/CMessageHandler.cpp + src/CQueryHandler.cpp + src/CAsyncQueue.cpp + src/CMessageQueue.cpp + src/CRequest.cpp + src/CRequester.cpp + src/CSysInfo.cpp +) + +include_directories(${pkgs_INCLUDE_DIRS}) +link_directories(${pkgs_LIBRARY_DIRS}) + +include_directories(/usr/include) +include_directories(/usr/include/dlog) +include_directories(/usr/include/aul) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include_internal) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include_internal/manager) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include_internal/manager/dependence) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include_internal/manager/strategy) + +FOREACH (flag ${RSCMNG_SERVER_DEPENDENCY_PKGS_CXXFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${extern_debug_pkgs_CXXFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -O2 -g2 -fPIE -fstack-protector-strong -Wl,-z,relro -D_FORTIFY_SOURCE=2") + +MESSAGE(${CMAKE_CXX_FLAGS}) + +ADD_EXECUTABLE(${PROJECT_NAME} ${RSCMGR_SRCS}) +ADD_EXECUTABLE(gen_rm_msgq src/gen_rm_msgq.cpp) + +target_link_libraries(${PROJECT_NAME} ${pkgs_LIBRARIES} "-ldl") +target_link_libraries(gen_rm_msgq ${pkgs_LIBRARIES}) + +#install +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR}) +INSTALL(TARGETS gen_rm_msgq DESTINATION ${BINDIR}) + diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..bbe9d02 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,206 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/include_internal/CAsyncQueue.h b/include_internal/CAsyncQueue.h new file mode 100644 index 0000000..619ae3a --- /dev/null +++ b/include_internal/CAsyncQueue.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __C_ASYNC_QUEUE_H__ +#define __C_ASYNC_QUEUE_H__ + +#include + +typedef void (*destoryNotify)(void *data); + +class CAsyncQueue{ +public: + CAsyncQueue(); + CAsyncQueue(destoryNotify destory_cb); + ~CAsyncQueue(); + + void push(void *data); + void push(CAsyncQueue *src_queue); + void push_front(void *data); + void push_front(CAsyncQueue *src_queue); + + void *pop(void); + void *pop(unsigned int timeout_ms); + + int length(void); + +private: + GAsyncQueue *queue; +}; + +#endif // __C_ASYNC_QUEUE_H__ diff --git a/include_internal/CCallback.h b/include_internal/CCallback.h new file mode 100644 index 0000000..aee85c8 --- /dev/null +++ b/include_internal/CCallback.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_CCALLBACK_H__ +#define __RMS_CCALLBACK_H__ + +class CCallback +{ +public: + CCallback() {} + ~CCallback() {} + + static void InitCallback(void); + static int SendCallbackMessage(int cid, int pid, void *callback_data, int size, int *err); + static int RemoveFIFOServerToClient(int pid, int cid); + static int ConvertCallbackType(int rm_return_type); + static unsigned int GetTimeout(void); +}; + +#endif //__RMS_CCALLBACK_H__ diff --git a/include_internal/CDbusHandler.h b/include_internal/CDbusHandler.h new file mode 100644 index 0000000..711c1e6 --- /dev/null +++ b/include_internal/CDbusHandler.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CDBUS_HANDLER_H__ +#define __CDBUS_HANDLER_H__ + +#include +#include + +#include + +class CDbusHandler +{ +public: + CDbusHandler(CAsyncQueue *queue); + ~CDbusHandler() = default; + + static void OnMethodCall(GDBusConnection *conn, const gchar *sender, const gchar *obj_path, const gchar *ifname, const gchar *method_name, GVariant *params, GDBusMethodInvocation *invoc, gpointer data); + static void OnBusAcquired(GDBusConnection *conn, const gchar *bus_name, gpointer data); + static void OnNameLost(GDBusConnection *conn, const gchar *bus_name, gpointer data); + +private: + + static const std::string m_methods; + static const GDBusInterfaceVTable m_vtable; + + GDBusConnection *m_conn; + unsigned int m_reg_id; + unsigned int m_own_id; + + CAsyncQueue *m_async_queue; + + bool MakeDbusConnection(void); + void RegisterObjects(void); + void GenerateReadyEvent(void); +}; + +#endif // __CDBUS_HANDLER_H__ diff --git a/include_internal/CHandle.h b/include_internal/CHandle.h new file mode 100644 index 0000000..2bc26ba --- /dev/null +++ b/include_internal/CHandle.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_CHANDLE_H__ +#define __RMS_CHANDLE_H__ +#include +class CHandle +{ +public: + CHandle() {} + CHandle(int handle, int is_used, int pid); + ~CHandle() {} + + int handle; + int is_used; + int pid; + int main_priority; + int sub_priority; + int app_pid; + char *app_id; + char process_name[RMS_NAME_BUF_SIZE]; +}; + +#endif //__RMS_CHANDLE_H__ diff --git a/include_internal/CHandleManager.h b/include_internal/CHandleManager.h new file mode 100644 index 0000000..2280b45 --- /dev/null +++ b/include_internal/CHandleManager.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_CHANDLE_MANAGER_H__ +#define __RMS_CHANDLE_MANAGER_H__ + +#include +#include +#include + +class CHandleManager +{ +public: + CHandleManager(CResourceManager *rsc_mgr); + ~CHandleManager() {} + + int GetNewHandle(int pid, int main_priority, int sub_priority, int app_pid, char *app_id); + int RemoveHandle(int handle, int pid); + int SetPriority(int handle, int main_priority, int sub_priority); + int GetPriority(int handle, int *main_priority, int *sub_priority); + int SetAppID(int handle, char *app_id); + char *GetAppID(int handle); + void ReclaimAllInvalidCustomer(int request_pid); + +private: + int m_RemoveHandle(int handle, int pid); + int m_IsValidHandle(int handle); + int m_ReclaimHandle(void); + int m_AddNewHandle(int handle, int pid, int main_priority, int sub_priority, int app_pid, char *app_id); + int m_PrintHandleInfo(int handle, int pid); + void m_PrintHandleList(void); + CHandle *findHandle(int id); + + CResourceManager *m_rsc_mgr; + int m_next_handle; + std::map m_handles; +}; + +#endif //__RMS_CHANDLE_MANAGER_H__ diff --git a/include_internal/CMessage.h b/include_internal/CMessage.h new file mode 100644 index 0000000..fb7e3aa --- /dev/null +++ b/include_internal/CMessage.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CMESSAGE_H__ +#define __CMESSAGE_H__ + +#include +#include +#include + +typedef enum { + MSG_SENDER_MSGQ, + MSG_SENDER_DBUS, + MSG_SENDER_INTERNAL +} msg_sender_e; + +class CMessage +{ +public: + CMessage(std::string name); + CMessage(rms_msg_request *msgq_req); + CMessage(GDBusMethodInvocation *invoc); + ~CMessage(); + + int GetReqType(void); + std::string GetName(void) { return m_name; } + msg_sender_e GetSender(void) { return m_sender; } + rms_msg_request *GetRequest(void) { return m_msgq_req; } + GDBusMethodInvocation *GetMethodInvocation(void) { return m_invoc; } + + bool IsUnlockMsg(void); + bool IsMsgFor(ResourceType rsc_type); + void PrintInfo(void); + +private: + rms_msg_request *m_msgq_req; + GDBusMethodInvocation *m_invoc; + msg_sender_e m_sender; + std::string m_name; + + void PrintDbus(void); + void PrintInternal(void); + void PrintMsgQ(void); + + bool IsMsgForScaler(void); + bool IsMsgForScalerDbus(void); + bool IsMsgForScalerMsgQ(void); +}; + +#endif //__CMESSAGE_H__ diff --git a/include_internal/CMessageHandler.h b/include_internal/CMessageHandler.h new file mode 100644 index 0000000..61caafd --- /dev/null +++ b/include_internal/CMessageHandler.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_CMESSAGE_HANDLER_H__ +#define __RMS_CMESSAGE_HANDLER_H__ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class CMessageHandler +{ +public: + typedef GVariant *(CMessageHandler::*MsgHandler)(GVariant *params); + + CMessageHandler(CResourceManager *rsc_mgr); + ~CMessageHandler(void); + + int Run(void); + void NotifyWatchdog(void); + +private: + void InitDbusHandlers(void); + void InitInternalMsgHandlers(void); + + static gpointer msgThread(gpointer data); + static gpointer msgQThread(gpointer data); + + int ProcessMessage(void); + int ProcessCallbackMessage(rms_consumer_tobe_returned_s *consumer_info, int requester_cid); + void ProcessMessage(CAsyncQueue *queue, CMessage *msg, int cid_requester, int cid_releaser); + void ProcessMsgQMessage(CMessage *msg); + void ProcessDbusMessage(CMessage *msg); + void ProcessInternalMessage(CMessage *msg); + + void EmptyPendingQueue(void); + void InsertPendingQueue(CMessage *msg); + + int SendResponse(rms_msg_response *response); + int PushMessage(CAsyncQueue *queue, CMessage *msg); + + bool IsRegisteredHandle(int handle); + bool IsValidProcess(int pid); + bool IsValidRequest(int req_type); + bool IsAllResourcesReclaimed(rms_consumer_tobe_returned_s *consumer_info); + + int ReleaseInvalidProcessResources(int pid, int handle); + int ReclaimResources(int reason, int requester_cid, int requester_zone_id, consumer_reclaim_s *conflict_info, bool *need_response); + + void SetRequesterInfo(rms_msg_request *request); + + void m_ConstructResponse(rms_msg_response *response, int data_type, rms_response_type_e msg_type, int handle, int pid); + void m_ConstructRequestedDevice(rms_msg_request *request, rms_requests_device_s *requested_resource); + void m_FreeAllocatedDevice(rms_return_device_s *allocated_device); + int *m_SerializeCallbackData(const rms_consumer_tobe_returned_s *consumer_info, int reason, int *data_size); + void m_Free(consumer_reclaim_s *consumer_info); + + void m_RegisterConsumer(rms_msg_request *request, rms_msg_response *response); + void m_UnregisterConsumer(rms_msg_request *request, rms_msg_response *response); + void m_AllocateResources(rms_msg_request *request, rms_msg_response *response); + void m_ReleaseResources(rms_msg_request *request, rms_msg_response *response); + void m_Query(rms_msg_request *request, rms_msg_response *response); + void m_SetConsumerPriority(rms_msg_request *request, rms_msg_response *response); + void m_SetAppID(rms_msg_request *request, rms_msg_response *response); + + GVariant *RegisterResource(GVariant *params); + GVariant *GetResourceState(GVariant *params); + GVariant *GetResourceList(GVariant *params); + GVariant *GetResourceCollectionState(GVariant *params); + GVariant *FindDeviceId(GVariant *params); + GVariant *SwapResources(GVariant *params); + GVariant *GetScalerState(GVariant *params); + GVariant *GetAppId(GVariant *params); + GVariant *GetActiveAudioOut(GVariant *params); + GVariant *GetScalerHWID(GVariant *params); + GVariant *RestoreResources(GVariant *params); + GVariant *NotifyResourcePolicy(GVariant *params); + GVariant *NotifyAppZoneInfo(GVariant *params); + GVariant *NotifyWatchdog(GVariant *params); + + void NotifyConflict(consumer_reclaim_s *conflict_info, int zone_id); + + unsigned long m_req_timeout = 5; + + CMessageQueue *msgq_rx; + CMessageQueue *msgq_tx; + CAsyncQueue *async_queue; + CAsyncQueue *async_pending_queue; + CLockController *m_lock_ctr; + CResourceManager *m_rsc_mgr; + CHandleManager *m_handle_mgr; + CQueryHandler *m_query_h; + CDbusHandler *m_dbus_h; + + typedef void (CMessageHandler::*msg_handler)(rms_msg_request *request, rms_msg_response *response); + static msg_handler handlers[RMS_REQUEST_MAX]; + std::map m_dbus_handlers; + std::map m_internal_msg_handlers; +}; + +#endif //__RMS_CMESSAGE_HANDLER_H__ diff --git a/include_internal/CMessageQueue.h b/include_internal/CMessageQueue.h new file mode 100644 index 0000000..7630413 --- /dev/null +++ b/include_internal/CMessageQueue.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CMESSAGE_QUEUE_H__ +#define __CMESSAGE_QUEUE_H__ + +#include +#include + +typedef enum { + MSG_QUEUE_RX = 0, + MSG_QUEUE_TX +} msgq_type_e; + +class CMessageQueue{ +public: + CMessageQueue(msgq_type_e type); + ~CMessageQueue(); + + int receive(rms_msg_request *req, int msg_type); + int send(rms_msg_response *response); + +private: + int init(void); + int recover(void); + static int getKey(msgq_type_e type); + + msgq_type_e msgq_type; + int msgq_id; + + static const long msgq_size = 131072; // 128KB + static const int key_rx = 8211; + static const int key_tx = 8212; +}; + +#endif //__CMESSAGE_QUEUE_H__ diff --git a/include_internal/CQueryHandler.h b/include_internal/CQueryHandler.h new file mode 100644 index 0000000..2a1bcaa --- /dev/null +++ b/include_internal/CQueryHandler.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CQUERY_HANDLER_H__ +#define __CQUERY_HANDLER_H__ + +#include +#include + +class CQueryHandler +{ +public: + CQueryHandler(CResourceManager *rsc_mgr); + ~CQueryHandler(); + + int GetAnswer(rms_msg_request *request, int *answer_out); +private: + CResourceManager *m_rsc_mgr; +}; + +#endif //__CQUERY_HANDLER_H__ \ No newline at end of file diff --git a/include_internal/CRequest.h b/include_internal/CRequest.h new file mode 100644 index 0000000..e98279b --- /dev/null +++ b/include_internal/CRequest.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CREQUEST_H__ +#define __CREQUEST_H__ + +#include "rms_type.h" + +class CRequester; +class CRequest +{ +public: + CRequest(CRequester *requester); + ~CRequest(); + + CRequester *getRequester(void); + + void SetCategory(int category_id, int category_option); + void SetState(int req_state); + + void SetResult(rms_return_code_e req_result); + void SetReason(rms_error_type_e reason) { m_reason = reason; } + void ResetResult(void) { m_result = RMS_ERROR; } + void SetCandidateDevice(int device_id) { m_candidate_device = device_id; } + void SetAllocatedDevice(int device_id) { m_allocated_device = device_id; } + void SetAllocatedVirtualDevice(int virtual_id) { m_virtual_device = virtual_id; } + + bool IsRequestByDevice(void) { return (m_device_id > 0); } + bool IsMainDeviceRequest(void); + bool IsSubDeviceRequest(void); + bool IsAIDeviceRequest(void); + + rms_rsc_category_e GetCategory(void); + int GetDevice(void) { return m_device_id; } + rms_requests_resource_state_e GetState(void) { return m_state; } + rms_error_type_e GetReason(void) { return m_reason; } + + rms_return_code_e GetResult(void); + int GetCandidateDevice(void) { return m_candidate_device; } + int GetAllocatedDevice(void) { return m_allocated_device; } + int GetAllocatedVirtualDevice(void) { return m_virtual_device; } + rms_mixing_mode_e GetMixingMode(void) { return m_mixing_mode; } + + int GetMultiviewZoneId(void) { return m_mv_zone_id; } + void PrintResult(void); + +private: + rms_rsc_category_e ToVideoDecoderCategory(int category, int category_option, bool force_main, bool force_sub); + rms_rsc_category_e ToJpegDecoderCategory(int category, int category_option); + rms_rsc_category_e ToMJpegDecoderCategory(int category, int category_option); + rms_rsc_category_e ToAudioDecoderCategory(int category, int category_option, bool force_main, bool force_sub); + rms_rsc_category_e ToScalerCategory(int category, int category_option, bool force_main, bool force_sub); + rms_rsc_category_e ToAudioOutCategory(int category, int category_option, bool force_main, bool force_sub); + rms_rsc_category_e ToResourceCategory(int category, int category_option); + rms_rsc_category_e ToImageDecoderCategory(int category, int category_option); + rms_mixing_mode_e ToMixingMode(int category, int category_option); + int ToMultiviewZoneId(int category_option); + bool IsSupportedCategory(int category_option); + int UnmaskMainSubOptions(int category_option); + int UnmaskMixingOptions(int category_option); + int UnmaskMVZoneInfo(int category_option); + int UnmaskForceOptions(int category_option); + + CRequester *m_requester; + + int m_category_id; + int m_category_option; + rms_rsc_category_e m_category; + rms_requests_resource_state_e m_state; + rms_mixing_mode_e m_mixing_mode; + int m_device_id; + + rms_return_code_e m_result; + int m_candidate_device; + int m_allocated_device; + int m_virtual_device; + int m_mv_zone_id; + rms_error_type_e m_reason; +}; + +#endif //__CREQUEST_H__ diff --git a/include_internal/CRequester.h b/include_internal/CRequester.h new file mode 100644 index 0000000..03a12a0 --- /dev/null +++ b/include_internal/CRequester.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CREQUESTER_H__ +#define __CREQUESTER_H__ + +#include + +#include "rms_type.h" + +class CRequester +{ +public: + CRequester(); + CRequester(rms_msg_request *req); + ~CRequester(); + + int getHandle(void); + int getPid(void); + int getMainPriority(void); + int getSubPriority(void); + std::string getAppId(void) { return m_app_id; } + void SetCmdName(int pid); + std::string GetCmdName(void) { return m_cmd_name; } + +private: + int m_handle; + int m_pid; + int m_main_priority; + int m_sub_priority; + std::string m_app_id; + std::string m_cmd_name; +}; + +#endif // __CREQUESTER_H__ diff --git a/include_internal/CResourceService.h b/include_internal/CResourceService.h new file mode 100644 index 0000000..c91d54b --- /dev/null +++ b/include_internal/CResourceService.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_CRESOURCE_SERVICE_H__ +#define __RMS_CRESOURCE_SERVICE_H__ + +#include +#include + +class CResourceService +{ +public: + CResourceService(void) {} + ~CResourceService(void) {} + int Init(GMainLoop *main_loop); + +private: + + CMessageHandler *m_msg_h; + + int IsFirstLaunch(void); + void RequestColdPowerOff(void); + void CreateWatchDogTimer(void); + void SetVIPProcess(void); + static gboolean WatchDogCallback(gpointer data); + static gboolean InvalidResourceTableMsgCallback(gpointer data); +}; + +#endif //__RMS_CRESOURCE_SERVICE_H__ diff --git a/include_internal/CSysInfo.h b/include_internal/CSysInfo.h new file mode 100644 index 0000000..6347f53 --- /dev/null +++ b/include_internal/CSysInfo.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CSYS_INFO_H__ +#define __CSYS_INFO_H__ + +class CSysInfo +{ +public: + ~CSysInfo() = default; + + static CSysInfo *GetInstance(void); + bool IsAudioMixingSupported(void); +private: + CSysInfo() = default; + + static CSysInfo *m_instance; + bool m_support_audio_mixing; +}; + +#endif //__CSYS_INFO_H__ diff --git a/include_internal/manager/CCache.h b/include_internal/manager/CCache.h new file mode 100644 index 0000000..60a8d8a --- /dev/null +++ b/include_internal/manager/CCache.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CCACHE_H__ +#define __CCACHE_H__ + +#include + +class CCache +{ +public: + static CCache *getInstance(void); + ~CCache() = default; + + void Drop(void); + int GetAppStatus(std::string app_id); + void SetAppStatus(std::string app_id, int status); + +private: + CCache() = default; + + static CCache *m_instance; + std::map m_visibility; // app id, app status +}; + +#endif //__CCACHE_H__ diff --git a/include_internal/manager/CConsumer.h b/include_internal/manager/CConsumer.h new file mode 100644 index 0000000..d79039f --- /dev/null +++ b/include_internal/manager/CConsumer.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_CONSUMER_H__ +#define __RSC_MGR_SERVER_CONSUMER_H__ + +#include +#include +#include + +class CConsumer +{ +public: + CConsumer(IN const rms_consumer_s *consumer); + virtual ~CConsumer() {} + + long GetPid(void) { return m_pid; } + int GetId(void) { return m_consumerID; } + void SetAppID(IN const char *app_id); + std::string GetAppID(void) { return m_app_id; } + std::string GetCmdName(void) { return m_cmd_name; } + + bool AddResource(IN int device_id); + int ReleaseResource(IN int device_id); + bool IsUsingResource(IN int device_id); + std::set GetResources(void) { return m_resources; } + int GetResourceNum(void) { return m_resources.size(); } + + void SetPriority(rms_priority_s priority) { m_priority = priority; } + rms_error_type_e ComparePriority(CConsumer *requester); + +private: + rms_priority_s GetPriority(void) { return m_priority; } + bool ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2); + bool CheckVisibility(IN std::string app_id_requester); + bool GetAppVisibility(IN std::string app_id, bool requester); + bool CheckWebAppState(IN std::string app_id_requesting); + bool IsVisibleStatus(int status); + bool NeedStatusUpdate(std::string app_id); + int UpdateAppStatus(std::string app_id); + void SetCmdName(long pid); + std::string GetAppId(int pid); + + std::set m_resources; + + int m_consumerID; + rms_priority_s m_priority; + long m_pid; + std::string m_app_id; + std::string m_cmd_name; +}; + + +#endif // __RSC_MGR_SERVER_CONSUMER_H__ diff --git a/include_internal/manager/CConsumerContainer.h b/include_internal/manager/CConsumerContainer.h new file mode 100644 index 0000000..1a6c765 --- /dev/null +++ b/include_internal/manager/CConsumerContainer.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CCONSUMER_CONTAINER_H__ +#define __CCONSUMER_CONTAINER_H__ + +#include + +class CConsumer; +class CConsumerContainer +{ +public: + static CConsumerContainer *getInstance(void); + ~CConsumerContainer() = default; + + bool AddConsumer(int consumer_id, CConsumer *consumer); + void RemoveConsumer(int consumer_id); + CConsumer *findConsumer(int consumer_id); + std::map FindConsumers(std::string app_id); + std::map findConsumers(int pid); + +private: + CConsumerContainer() = default; + + static CConsumerContainer *m_instance; + std::map m_consumers; +}; + +#endif // __CCONSUMER_CONTAINER_H__ diff --git a/include_internal/manager/CDebugUtils.h b/include_internal/manager/CDebugUtils.h new file mode 100644 index 0000000..8ce5a50 --- /dev/null +++ b/include_internal/manager/CDebugUtils.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_DEBUGUTILS_H__ +#define __RSC_MGR_SERVER_DEBUGUTILS_H__ + +#include +#include +#include + +#define RMS_CONSOLE_BUF_SIZE 256 + +typedef enum { + RMS_ALARM_NO_CALLBACK_RESPONSE, + RMS_ALARM_NO_DEALLOCATION, +} rms_alarm_reason_e; + +const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum); +const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum); +const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum); +const char *rm_print_allocation_failure_reason(int ret_value); +const char *rm_convert_device_enum_to_string(rms_device_e device_enum); + +int rms_get_cmd_name(pid_t pid, char *name_out, int size); +void rms_print_log_console(char *buf); + +int rm_get_product_type(void); +int rm_is_valid_pid(int pid); +int rms_report_emergency(IN int cid, IN int pid, IN int requester); + +int is_symlink_file(const char *path); +const char *rm_convert_error_type_to_string(rms_error_type_e error_type); + +void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info); +void rms_display_resource_table_error_popup(void); +void rms_print_model_info(void); + +bool process_htable_contains(const char *name); + +#endif //__RSC_MGR_SERVER_DEBUGUTILS_H__ diff --git a/include_internal/manager/CLockController.h b/include_internal/manager/CLockController.h new file mode 100644 index 0000000..24a85ed --- /dev/null +++ b/include_internal/manager/CLockController.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CLOCK_CONTROLLER_H__ +#define __CLOCK_CONTROLLER_H__ + +#include +#include +#include + +class CLockController +{ +public: + static CLockController *GetInstance(void); + void SetMsgQ(CAsyncQueue *queue) { m_msg_q = queue; } + + void Lock(ResourceType rsc_type); + void Unlock(ResourceType rsc_type); + unsigned int GetLockCount(void); + bool IsLocked(CMessage *msg); + +private: + CLockController() = default; + ~CLockController() = default; + void NotifyUnlock(void); + + static CLockController *m_instance; + std::map m_locks; + CAsyncQueue *m_msg_q; +}; + +#endif //__CLOCK_CONTROLLER_H__S diff --git a/include_internal/manager/CPriority.h b/include_internal/manager/CPriority.h new file mode 100644 index 0000000..21cde0f --- /dev/null +++ b/include_internal/manager/CPriority.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CPRIORITY_H__ +#define __CPRIORITY_H__ + +#include + +enum { + LOW_PRIORITY = -1, + SAME_PRIORITY = 0, + HIGH_PRIORITY = 1 +}; + +class CPriority +{ +public:; + ~CPriority(); + + static bool isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type); + static int compareCurConsumers(int device_id, int consumer_id); + static int compare(int cur_consumer_id, int consumer_id); + static int getReclaimableConsumers(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type); + static int getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type); +private: + CPriority(); +}; + +#endif //__CPRIORITY_H__ diff --git a/include_internal/manager/CResource.h b/include_internal/manager/CResource.h new file mode 100644 index 0000000..f4d1da1 --- /dev/null +++ b/include_internal/manager/CResource.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_RESOURCE_H__ +#define __RSC_MGR_SERVER_RESOURCE_H__ + +#include +#include +#include + +#include +#include + +class CResource : public CResourceSubject +{ +public: + CResource(IN const int device_id, IN const rms_rsc_category_e category_type, IN const char *name, IN const char *path, + IN std::set mem_cluster, IN int is_main_device, IN const char *audio_codec, IN int sharable_count); + ~CResource(); + + std::string GetName(void) { return std::string(m_device_name); } + int GetDeviceID(void) { return m_id; } + int GetVirtualResourceID(void) { return m_vrsc_id; } + const char *GetDevicePath(void) { return m_device_path; } + std::string GetAudioCodec(void) { return m_audio_codec; } + rms_mixing_mode_e GetMixingMode(void) { return m_mixing_mode; } + rms_rsc_category_e GetCategoryType(void) { return m_category_type; } + int GetCurCategory(void) { return m_cur_category; } + int getSharableCount(void) { return (m_sharable_count - m_shared_count - m_reserved_count); } + int GetCategoryClass(void) { return m_category_class; } + + bool IsFreeState(void) { return m_state == RMS_INTERNAL_STATE_FREE; }; + bool IsAllocatableState(IN rms_requests_resource_state_e requested_state); + bool IsSharableState(void) { return (m_state == RMS_INTERNAL_STATE_FREE || m_state == RMS_INTERNAL_STATE_SHARABLE); } + bool IsReserved(void) { return m_is_reserved; } + bool IsSharableDevice(void) { return (m_sharable_count >= 2); } + bool IsMainDevice(void) { return m_is_main_device; } + bool IsAudioDevice(void); + bool IsVideoDecoder(void); + bool IsScaler(void) { return m_is_scaler; } + bool IsJpegDecoder(void); + + void AddConsumer(IN int consumer_id, IN rms_requests_resource_state_e state); + void ResetConsumer(std::set new_consumers); + int RemoveConsumer(IN int consumer_id, IN bool force); + std::set GetConsumers(void) { return m_consumer_ids; } + int GetFirstConsumer(void); + + int Reserve(IN int consumer_id, rms_requests_resource_state_e state); + void CancelReservation(rms_requests_resource_state_e state); + + void SetDefaultBW(unsigned int bw); + unsigned int GetBW(void) { return m_occupied_bw; } + int GetDefaultBW(void) { return m_default_bw; } + void ResetBW(void) { m_occupied_bw = m_default_bw; } + void SetAllocatedTime(void); + unsigned long GetAllocatedTime(void) { return m_allocated_time; } + + void SetVirtualDeviceId(int id) { m_virtual_id = id; } + int GetVirtualDeviceId(void); + void SetDedicatedVirtualDeviceId(int id) { m_dedicated_virtual_id = id; } + int GetDedicatedVirtualDeviceId(void) { return m_dedicated_virtual_id; } + + std::set GetMemClusters(void) { return m_mem_clusters; } + void UpdateProperties(std::set mem_clusters, int bw, int category, int category_class, int vrsc_id); + void UpdateAudioCodec(std::string codec_name); + void updateMixingMode(rms_mixing_mode_e mode) { m_mixing_mode = mode; } + + void RegisterObserver(CResourceObserver *observer); + void UnregisterObserver(CResourceObserver *observer); + + bool Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id); + int GetState(void) { return (int) m_state; } + int GetZoneId(void) { return m_mv_zone_id; } + void SetZoneId(int zone_id); + + void ChangeState(rms_resource_internal_state_e next_state); + +private: + void m_SetSubScalerFlag(int next_state); + bool IsRegisteredConsumer(int consumer_id); + int IncreaseRefCount(int consumer_id); + int DecreaseRefCount(int consumer_id); + void NotifyObservers(resource_update_type_e type, int consumer_id); + bool ChangeStateByAllocation(IN rms_requests_resource_state_e state, const int consumer_id, int mv_zone_id); + bool ChangeStateByRelease(int consumer_id); + bool IsScaler(rms_rsc_category_e category); + + int ReserveExclusive(int consumer_id); + int ReserveShared(int consumer_id); + + std::map m_consumers; // consumer id, cnt + std::set m_shared_consumers; + std::set m_consumer_ids; + + int m_id; + int m_vrsc_id; + int m_virtual_id; + int m_dedicated_virtual_id; + rms_resource_internal_state_e m_state; + rms_rsc_category_e m_category_type; + const char *m_device_name; + const char *m_device_path; + int m_category_class; + int m_cur_category; + + unsigned int m_occupied_bw; + unsigned int m_default_bw; + int m_is_main_device; + int m_sharable_count; + + bool m_is_reserved; + bool m_is_scaler; + int m_reserved_consumer_id; + unsigned long m_allocated_time; + + int m_shared_count; + int m_reserved_count; + int m_mv_zone_id; + + std::string m_audio_codec; + std::vector m_observers; + std::set m_mem_clusters; + rms_mixing_mode_e m_mixing_mode; +}; + +#endif // __RSC_MGR_SERVER_RESOURCE_H__ diff --git a/include_internal/manager/CResourceCategory.h b/include_internal/manager/CResourceCategory.h new file mode 100644 index 0000000..6fdd6ac --- /dev/null +++ b/include_internal/manager/CResourceCategory.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_CATEGORY_H__ +#define __RSC_MGR_SERVER_CATEGORY_H__ + +#include +#include +#include +#include + +#include + +class CConsumer; +class CVirtualResource; +class CRequest; +class CAllocateStrategy; +class CResourceCategory +{ +public: + CResourceCategory(rms_rsc_category_e resource_category_id, int category_class); + virtual ~CResourceCategory() {} + + rms_rsc_category_e GetCategoryID(void) { return m_categoryID; } + void AddVirtualResource(IN int device_id, IN CVirtualResource *vresource); + + CResource *ReserveCandidate(CRequest *req, bool apply_promotion); + void GetRetirableConsumers(CRequest *req, std::multimap* return_ids_in_category, rms_error_type_e *err_type); + bool hasFreeStateResource(void); + bool IsAvailableToUse(rms_requests_resource_state_e request_state); + void GetResources(std::map *resource_map); + CResource *FindMainResource(void); +private: + std::map m_device_id_to_vresource_map; + + rms_rsc_category_e m_categoryID; + CAllocateStrategy *m_alloc_strategy; + + void MakeResourceMapSortedByAllocTime(std::multimap *time_resource_map); +}; + +#endif // __RSC_MGR_SERVER_CATEGORY_H__ diff --git a/include_internal/manager/CResourceDB.h b/include_internal/manager/CResourceDB.h new file mode 100644 index 0000000..99d6609 --- /dev/null +++ b/include_internal/manager/CResourceDB.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_DB_H__ +#define __RSC_MGR_SERVER_DB_H__ + +#include +#include +#include +#include +#include + +class CResourceCategory; +class CVirtualResource; +class CResource; +class CResourceDB : public CResourceObserver +{ +public: + CResourceDB(void) = default; + virtual ~CResourceDB(void) {} + static CResourceDB *getInstance(void); + + void AddVirtualResource(IN CVirtualResource *vrsc, IN rms_rsc_category_e resource_category_id, IN const char *name, + IN const char *path, IN std::set mem_cluster_info, + IN unsigned int device_id_unique, IN int is_main_device, IN const char *audio_codec, + IN int sharable_count, IN int mixing_count, IN CResourceObserver *observer); + + void AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category); + + CResourceCategory *FindResourceCategory(IN rms_rsc_category_e category_id); + CResource *FindResource(IN const int device_id); + CVirtualResource *FindVirtualResource(const int vid); + int FindRealDeviceId(int virtual_id); + void FindMainResources(IN std::map *resource_map); + void FindActiveVideoDecoders(IN std::map *resource_map); + + void SetMaxVideoDecoders(int n_decs) { m_max_vdecs = n_decs; } + std::map GetActiveVideoDecoders(void) { return m_active_vdecs; } + std::map GetActiveNVideoDecoders(void) { return m_active_nvdecs; } + int GetActiveDecoderNum(void); + bool HasAvailableDecoder(void); + bool HasAvailableDecoderNDecoding(void); + bool HasAvailableDecoder(std::multimap retirables); + bool HasAvailableDecoderNDecoding(std::multimap retirables); + void AddReclaimResources(consumer_reclaim_s *consumers); + void ClearReclaimResources(void); + void Update(resource_update_type_e type, const int device_id, const int consumer_id); + + void InitScalerTable(void); + int SwapScaler(int id_a, int id_b); + void GetScalerList(std::map *scalers); + int ToScalerId(int device_id); + void UpdateVirtualScalerIds(void); + void ResetZoneIds(void); + + static gboolean NotifyResourceStateUpdated(gpointer data); +private: + CResource *FindResource(const char *device_name); + CResource *FindMainResource(rms_rsc_category_e category_id); + + void AddDeviceID(IN int device_id, IN CResource *resource); + void AddDeviceName(IN const char *device_name, IN CResource *resource); + void AddVirtualDeviceID(IN CVirtualResource *vresource); + + void UpdateBWbyRelease(CResource *resource); + void UpdateBWbyAllocation(const unsigned int bandwidth, CResource *resource); + void UpdateByRelease(CResource *resource, const int device_id, const int consumer_id); + void UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id); + void SetVirtualScalerId(CResource *resource); + int GetVirtualScalerId(CResource *resource); + int GetDedicatedVirtualScalerId(int device_id); + void PrintVirtualScalerMap(void); + + void AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class); + void RemoveActiveVideoDecoder(const int device_id, const int category_class); + void AddActiveJpegDecoder(const int device_id, const int consumer_id); + void RemoveActiveJpegDecoder(const int device_id); + void PrintVideoDecoderConsumers(void); + + void NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id); + + CResource *FindScaler(int id); + void InsertVirtualScaler(int virtual_id, CResource *resource); + void SwapResource(std::set consumers, int cur_device_id, int new_device_id); + void UpdateConsumerInfoOfResource(CResource *resource, std::set new_consumers, int new_virtual_id); + + int CountNDecoders(std::map retirables); + void InsertResourceHasZoneId(CResource *resource); + void RemoveResourceHasZoneId(int device_id); + std::map m_resourceCategoryMap; //category info + std::map m_v_deviceid_to_rsc; + std::map m_deviceid_to_rsc; + std::map m_devicename_to_rsc; + std::map m_scaler_map; + std::map m_rscs_has_zone_id; + + static CResourceDB *m_instance; + unsigned int m_device_id; //for virtual resource + int m_max_vdecs; + + std::set m_reclaim_rscs; // resources reclaiming + std::map m_active_vdecs; // device id, consumer id + std::map m_active_jdecs; // device id, consumer id + std::map m_active_nvdecs; // device id, consumer id +}; + +#endif // __RSC_MGR_SERVER_DB_H__ diff --git a/include_internal/manager/CResourceManager.h b/include_internal/manager/CResourceManager.h new file mode 100644 index 0000000..f25b963 --- /dev/null +++ b/include_internal/manager/CResourceManager.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RSC_MGR_SERVER_MANAGER_H__ +#define __RSC_MGR_SERVER_MANAGER_H__ +#include +#include +#include +#include +#include +#include + +class CResourceManager +{ +public: + CResourceManager(); + ~CResourceManager() = default; + + int AllocateResources(rms_msg_request *req, rms_return_device_s *allocated_devices); + int ReleaseResourcesOfPid(IN const int pid); + int ReleaseResources(IN int consumer_id, IN const rms_requests_device_s *req); + int RegisterResources(void); + + int SetAppId(IN int consumer_id, IN const char *app_id); + int RegisterConsumer(int consumer_id, int process_id, const char *app_id, int main_priority, int sub_priority); + int UnregisterConsumer(IN int consumer_id); + int FindReclaimableConsumers(rms_msg_request *req, consumer_reclaim_s *return_consumer, int *zone_id); + int GetActiveDecoderNum(void); + int GetActiveAudioOut(int consumer_id); + + int IsCategoryAvailableToUse(rms_msg_request *request, int *is_available); + bool IsReclaimed(IN const int device_id, IN const int consumer_id); + + int GetResourceState(int device_id); + int FindDeviceId(int virtual_id); + int GetResourceList(int category_id, GVariantBuilder *builder); + int GetScalerState(GVariantBuilder *builder); + int GetResourceCollectionState(int collection, GVariantBuilder *builder); + int SwapResources(int device_id_a, int device_id_b); + int RestoreResources(int category_id); + int GetScalerHWId(int zone_id); + int GetZoneId(int device_id); + void ResetZoneIds(void); + void UpdateZoneIds(std::string app_id, int zone_id); + +private: + void MakeRequests(CRequester *requester, rms_msg_request *reqs, std::vector *requests); + void AllocateCandidates(std::vector requests); + void ReleaseResources(const int consumer_id); + int GetScalerState(int category_id, GVariantBuilder *builder); + + void MakeResourceMapPerConsumer(std::multimap *device_id_to_consumer_id_map, std::map > *consumer_id_to_resource_set_map); + void MakeConsumerInfoToBeReturned(consumer_reclaim_s *return_consumer, std::map > *consumer_id_to_resource_set_map); + void PrintConsumerInfoToBeReturned(consumer_reclaim_s *consumer_info); + + CResourceDB *m_db; + + int m_is_db_created; + rms_error_type_e m_error_type; + CConsumerContainer *m_consumers; + +}; + +#endif // __RSC_MGR_SERVER_MANAGER_H__ diff --git a/include_internal/manager/CResourceObserver.h b/include_internal/manager/CResourceObserver.h new file mode 100644 index 0000000..9c1f246 --- /dev/null +++ b/include_internal/manager/CResourceObserver.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CRESOURCE_OBSERVER_H__ +#define __CRESOURCE_OBSERVER_H__ + +typedef enum _resource_update_type_e { + UPDATED_BY_ALLOC = 0, + UPDATED_BY_RELEASE +} resource_update_type_e; + +class CResourceObserver +{ +public: + virtual ~CResourceObserver() {} + virtual void Update(resource_update_type_e type, const int device_id, const int consumer_id) = 0; +}; + +#endif // __CRESOURCE_OBSERVER_H__ diff --git a/include_internal/manager/CResourceState.h b/include_internal/manager/CResourceState.h new file mode 100644 index 0000000..5064e66 --- /dev/null +++ b/include_internal/manager/CResourceState.h @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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. +*/ + +#ifndef __CRESOURCE_STATE_H__ +#include + +class CResourceState +{ +public: + CResourceState(int device_id, int category_type, int consumer_id, int state, std::string app_id); + ~CResourceState() = default; + + int GetDeviceId(void) { return m_device_id; } + int GetConsumerId(void) { return m_consumer_id; } + int GetState(void) { return m_state; } + int GetCategoryType(void) { return m_category_type; } + std::string GetAppId(void) { return m_app_id; } + +private: + int m_device_id; + int m_consumer_id; + int m_state; + int m_category_type; + std::string m_app_id; +}; + +#endif //__CRESOURCE_STATE_H__ \ No newline at end of file diff --git a/include_internal/manager/CResourceSubject.h b/include_internal/manager/CResourceSubject.h new file mode 100644 index 0000000..d8c2aaf --- /dev/null +++ b/include_internal/manager/CResourceSubject.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CRESOURCE_SUBJECT_H__ +#define __CRESOURCE_SUBJECT_H__ + +#include + +class CResourceObserver; +class CResourceSubject +{ +public: + virtual ~CResourceSubject() {} + + virtual void RegisterObserver(CResourceObserver *observer) = 0; + virtual void UnregisterObserver(CResourceObserver *observer) = 0; + virtual void NotifyObservers(resource_update_type_e type, const int consumer_id) = 0; +}; + +#endif // __CRESOURCE_SUBJECT_H__ + diff --git a/include_internal/manager/CVideoController.h b/include_internal/manager/CVideoController.h new file mode 100644 index 0000000..d6ec594 --- /dev/null +++ b/include_internal/manager/CVideoController.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __C_VIDEO_CONTROLLER_H__ +#define __C_VIDEO_CONTROLLER_H__ + +#include +#include +#include +#include + +class CVideoController +{ +public: + ~CVideoController(void); + static CVideoController *GetInstance(void); + void UpdateVirtualScalerIds(std::map scaler_id_map); + +private: + typedef struct _scaler_id_pair { + unsigned int virtual_scaler_id; + unsigned int scaler_id; + } scaler_id_pair_t; + + CVideoController(void); + void WaylandDisplayCreate(void); + void WaylandDisplayDestroy(void); + void RunWaitingThread(void); + static gpointer WaitingThread(gpointer data); + + static CVideoController *m_instance; + struct wl_display *m_wl_display; + struct wl_registry *m_wl_registry; + struct tizen_video_rsc *m_tizen_video_rsc; + struct wl_registry_listener m_registry_listener; + + GThread *m_waiting_thread; + CLockController *m_lock_ctr; +}; + +#endif //__C_VIDEO_CONTROLLER_H__ diff --git a/include_internal/manager/CVirtualResource.h b/include_internal/manager/CVirtualResource.h new file mode 100644 index 0000000..a5771b3 --- /dev/null +++ b/include_internal/manager/CVirtualResource.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef _RM_VIRTUAL_RESOURCE_H_INCLUDED +#define _RM_VIRTUAL_RESOURCE_H_INCLUDED + +#include +#include +#include + +class CResource; +class CVirtualResource +{ +public: + CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set dependent, bool is_main_device, const char *audio_codec, int category_class); + virtual ~CVirtualResource(void) {} + + CResource *GetResource(void) { return m_rsc; } + void SetResource(CResource *resource); + + int GetVResourceID(void) { return m_vir_rsc_id; } + rms_rsc_category_e GetCategoryType(void) { return m_category_type; } + int GetCategoryClass(void) { return m_category_class; } + unsigned int GetBW(void) { return m_vir_rsc_bw; } + std::set GetMemClusters(void) { return m_mem_clusters; } + std::string GetAudioCodec(void) { return m_audio_codec; } + + bool IsMainDevice(void) { return m_is_main_device; } + bool IsAIDevice(void) { return m_is_ai_device; } +private: + int m_vir_rsc_id; + rms_rsc_category_e m_category_type; + unsigned int m_vir_rsc_bw; + bool m_is_main_device; + bool m_is_ai_device; + int m_category_class; + std::set m_mem_clusters; + std::string m_audio_codec; + + CResource *m_rsc; +}; + +#endif // _RM_VIRTUAL_RESOURCE_H_INCLUDED diff --git a/include_internal/manager/dependence/CAudioCodec.h b/include_internal/manager/dependence/CAudioCodec.h new file mode 100644 index 0000000..1dcb59a --- /dev/null +++ b/include_internal/manager/dependence/CAudioCodec.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CAUDIO_CODEC_H__ +#define __CAUDIO_CODEC_H__ + +#include +#include +#include + +class CAudioCodec{ +public: + CAudioCodec(const char *name); + ~CAudioCodec(); + + std::string getName(void) { return m_name; } + std::set getResourcesOfConsumer(int consumer_id); + + void increaseRef(int device_id, int consumer_id); + void decreaseRef(int device_id, int consumer_id); + void increaseMaxRef(void); + + bool isAvailableToUse(void); + bool isMixingSupported(void) { return (m_ref_count_max >= 2 || m_name.length() == 0); } + bool canBeUsedByMultiApp(void) { return (m_name.length() == 0); } + std::map GetConsumers(void) { return m_consumers; } + +private: + bool isUnknownCodec(void) { return (m_name.length() == 0); } + std::string m_name; + unsigned int m_ref_count; + unsigned int m_ref_count_max; + std::map m_consumers; // consumer id, ref_count + std::map m_resources; // device_id, consumer id +}; + +#endif //__CAUDIO_CODEC_H__ \ No newline at end of file diff --git a/include_internal/manager/dependence/CAudioCodecCollection.h b/include_internal/manager/dependence/CAudioCodecCollection.h new file mode 100644 index 0000000..15b6633 --- /dev/null +++ b/include_internal/manager/dependence/CAudioCodecCollection.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CAUDIO_CODEC_COLLECTION_H__ +#define __CAUDIO_CODEC_COLLECTION_H__ + +#include +#include + +class CAudioCodec; +class CAudioCodecCollection { +public: + static CAudioCodecCollection *getInstance(); + ~CAudioCodecCollection(); + + void registerAudioCodec(const char *name, int count); + CAudioCodec *findAudioCodec(std::string name); +private: + CAudioCodecCollection(); + + static CAudioCodecCollection *m_instance; + std::map m_audio_codecs; +}; + +#endif //__CAUDIO_CODEC_COLLECTION_H__ diff --git a/include_internal/manager/dependence/CBandwidth.h b/include_internal/manager/dependence/CBandwidth.h new file mode 100644 index 0000000..68bdfdc --- /dev/null +++ b/include_internal/manager/dependence/CBandwidth.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CBANDWIDTH_H__ +#define __CBANDWIDTH_H__ + +#include +#include + +class CBandwidth +{ +public: + static CBandwidth *GetInstance(); + + void SetMax(unsigned int max) { m_max = m_avail = max; } + unsigned int GetMax(void) { return m_max; } + unsigned int GetAvail(void) { return m_avail; } + void AddConsumer(int device_id, int consumer_id, int category_id, int category_class); + void RemoveConsumer(int device_id, int category_id, int category_class); + void Decrease(unsigned int bw, int category_id, int category_class, int device_id); + void Increase(unsigned int bw, int category_id, int category_class, int device_id); + int GetNConsumersNDec(int category_id); + void GetConsumersNDec(int category_id, std::map *consumers); + std::map GetConsumers(void) { return m_consumers; } + +private: + static CBandwidth *m_instance; + + void AddConsumerNDec(int device_id, int consumer_id, int category_id); + void RemoveConsumerNDec(int device_id, int category_id); + bool IncludeSameDeviceGroup(int category_id, int device_id); + bool IsSameMemClusters(std::set c_mc, std::set u_mc); + + std::map m_consumers; // device_id, consumer_id + std::map> m_ndec_consumers; // category id, + unsigned int m_max; + unsigned int m_avail; +}; + +#endif //__CBANDWIDTH_H__ diff --git a/include_internal/manager/dependence/CDependencyController.h b/include_internal/manager/dependence/CDependencyController.h new file mode 100644 index 0000000..d85fe4f --- /dev/null +++ b/include_internal/manager/dependence/CDependencyController.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CDEPENDENCY_CONTROLLER_H__ +#define __CDEPENDENCY_CONTROLLER_H__ + +#include +#include +#include + +class CMemCluster; +class CMixingMode; +class CAudioCodec; +class CResourceObserver; +class CDependencyController : public CResourceObserver +{ +public: + static CDependencyController *getInstance(void); + ~CDependencyController(); + + void RegisterMemCluster(unsigned int id); + bool isAvailableMemClusters(std::set mc_ids); + bool isAvailableMemClusters(std::set mc_ids, int category_class, int category_id); + bool isAvailableMemClusters(std::set mc_ids, std::string app_id); + bool isSharableMemClusters(std::set mc_ids, int device_id); + bool canReclaimMemClusters(std::set mc_ids, int consumer_id); + bool canReclaimMemClusters(std::set mc_ids, int consumer_id, std::string app_id); + int getReclaimableMemClusterConsumers(std::set mc_ids, int consumer_id, std::multimap* reclaimables); + int getReclaimableMemClusterConsumers(std::set mc_ids, int consumer_id, std::multimap* reclaimables, std::string app_id); + void SwapConsumers(int device_id_a, std::set consumers_a, int device_id_b, std::set consumers_b); + + bool isAvailableAudioCodec(std::string name); + bool isAudioCodecBeingUsed(void) { return (m_acodec_consumers.size() > 0); } + std::map> getAudioCodecConsumers(void); + + CMixingMode *getCurMixingMode(void) { return m_cur_mixing_mode; } + CMixingMode *findMixingMode(rms_mixing_mode_e mode); + void Update(resource_update_type_e type, const int device_id, const int consumer_id); +private: + CDependencyController(); + + void registerMixingModes(void); + bool IsRegisteredMemCluster(unsigned int id); + void addMemClusterConsumer(int device_id, int consumer_id); + void removeMemClusterConsumer(int device_id, int consumer_id); + void ClearMemClusterConsumer(int device_id); + CMemCluster *findMemCluster(unsigned int id); + + static CDependencyController *m_instance; + std::map m_mem_clusters; + + void addAudioCodecConsumer(int device_id, int consumer_id); + void removeAudioCodecConsumer(int device_id, int consumer_id); + void setCurMixingMode(int device_id, int consumer_id); + void resetCurMixingMode(int device_id, int consumer_id); + + std::map m_acodec_consumers; // device id, consumer id + unsigned int m_acodec_ref_count_max = 2; + + std::map m_mixing_modes; + CMixingMode *m_cur_mixing_mode; +}; + +#endif // __CDEPENDENCY_CONTROLLER_H__ diff --git a/include_internal/manager/dependence/CMemCluster.h b/include_internal/manager/dependence/CMemCluster.h new file mode 100644 index 0000000..12aa539 --- /dev/null +++ b/include_internal/manager/dependence/CMemCluster.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CMEM_CLUSTER_H__ +#define __CMEM_CLUSTER_H__ + +#include +#include + +class CMemCluster{ +public: + CMemCluster(unsigned int m_id); + ~CMemCluster(); + + bool IsUsed(void); + bool IsUsedBy(std::string app_id); + bool IsSharable(int device_id); + + unsigned int GetId(void) { return m_id; } + std::set GetAssignedDeviceId(int consumer_id); + int GetCategoryClass(void) { return m_category_class; } + int GetCategoryId(void) { return m_category_id; } + + void AddConsumer(int consumer_id, int device_id, int category_class, int category_id); + void RemoveConsumer(int consumer_id, int device_id); + void ClearConsumers(void); + std::set GetConsumers(void); +private: + unsigned int m_id; + std::map> m_consumers; // consumer, device ids + int m_category_class; + int m_category_id; +}; + +#endif //__CMEM_CLUSTER_H__ diff --git a/include_internal/manager/dependence/CMixingMode.h b/include_internal/manager/dependence/CMixingMode.h new file mode 100644 index 0000000..002ca7e --- /dev/null +++ b/include_internal/manager/dependence/CMixingMode.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CMIXING_MODE_H__ +#define __CMIXING_MODE_H__ + +#include +#include +#include + +class CAudioCodec; +class CMixingMode{ +public: + CMixingMode(rms_mixing_mode_e mode) { m_mode = mode; } + ~CMixingMode() = default; + + int AddConsumer(int device_id, int consumer_id); + int RemoveConsumer(int device_id, int consumer_id); + rms_mixing_mode_e getMode(void) { return m_mode; } + std::map GetConsumers(void) { return m_consumers; } +private: + rms_mixing_mode_e m_mode; + std::map m_audio_codecs; + std::map m_consumers; // device id, consumer id +}; + +#endif //__CAUDIO_MIXING_MODE_H__ diff --git a/include_internal/manager/strategy/CAllocateModeStrategy.h b/include_internal/manager/strategy/CAllocateModeStrategy.h new file mode 100644 index 0000000..95f584d --- /dev/null +++ b/include_internal/manager/strategy/CAllocateModeStrategy.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CALLOCATE_MODE_STRATEGY_H__ +#define __CALLOCATE_MODE_STRATEGY_H__ + +#include +#include + +class CRequest; +class CAllocateModeStrategy +{ +public: + virtual ~CAllocateModeStrategy() {} + + virtual bool CanAllocateResources(std::vector requests, rms_allocate_result_s *result) = 0; + virtual void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices) = 0; +}; + + +#endif //__CALLOCATE_MODE_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CAllocateModeStrategyProvider.h b/include_internal/manager/strategy/CAllocateModeStrategyProvider.h new file mode 100644 index 0000000..356813f --- /dev/null +++ b/include_internal/manager/strategy/CAllocateModeStrategyProvider.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CALLOCATE_MODE_STRATEGY_PROVIDER_H__ +#define __CALLOCATE_MODE_STRATEGY_PROVIDER_H__ + +#include + +class CAllocateModeStrategy; +class CAllocateModeStrategyProvider +{ +public: + static CAllocateModeStrategyProvider *getInstance(); + ~CAllocateModeStrategyProvider(); + + CAllocateModeStrategy *GetStrategy(rms_msg_request *req); +private: + CAllocateModeStrategyProvider(); + + int getAllocateMode(rms_msg_request *req); + + static CAllocateModeStrategyProvider *m_instance; +}; + +#endif //__CALLOCATE_MODE_PROVIDER_H__ diff --git a/include_internal/manager/strategy/CAllocateStrategy.h b/include_internal/manager/strategy/CAllocateStrategy.h new file mode 100644 index 0000000..2449c6f --- /dev/null +++ b/include_internal/manager/strategy/CAllocateStrategy.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CALLOCATE_STRATEGY_H__ +#define __CALLOCATE_STRATEGY_H__ + +#include +#include +#include + +class CVirtualResource; +class CRequest; +class CAllocateStrategy +{ +public: + virtual ~CAllocateStrategy() {} + virtual CVirtualResource *findCandidate(std::map vresources, CRequest *req) = 0; + virtual int reserveResource(CVirtualResource *vrsc, CRequest *req) = 0; + virtual void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) = 0; + +protected: + void ExcludeResources(std::map vresources, std::map* filtered_resources, CRequest *req); + void ExcludeResources(std::multimap vresources, std::multimap* filtered_resources, CRequest *req); + void ExcludeDuplicatedNDecoders(std::multimap *retirables, std::set *excluded); + void updateReasonByResourceState(int device_id, CRequest *req); + void updateReasonBySharableCount(int device_id, CRequest *req); + int GetReclaimedBW(std::multimap *retirables); +}; + +#endif //__CALLOCATE_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CAllocateStrategyProvider.h b/include_internal/manager/strategy/CAllocateStrategyProvider.h new file mode 100644 index 0000000..d93a831 --- /dev/null +++ b/include_internal/manager/strategy/CAllocateStrategyProvider.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CALLOCATE_STRATEGY_PROVIDER_H__ +#define __CALLOCATE_STRATEGY_PROVIDER_H__ + +#include + +class CAllocateStrategy; +class CAllocateStrategyProvider +{ +public: + static CAllocateStrategyProvider *getInstance(); + ~CAllocateStrategyProvider(); + + CAllocateStrategy *GetStrategy(rms_rsc_category_e category, int category_class); + +private: + CAllocateStrategyProvider(); + + bool IsAudioDecoderCategory(rms_rsc_category_e category); + bool IsVideoDecoderCategory(rms_rsc_category_e category); + bool IsBGScalerCategory(rms_rsc_category_e category); + bool IsNDecordingVideoDecoderCategory(int category_class); + bool IsMultiviewScalerCategory(rms_rsc_category_e category); + bool IsSubScalerCategory(rms_rsc_category_e category); + + static CAllocateStrategyProvider *m_instance; +}; + +#endif //__CALLOCATE_STRATEGY_PROVIDER_H__ diff --git a/include_internal/manager/strategy/CAudioDecoderStrategy.h b/include_internal/manager/strategy/CAudioDecoderStrategy.h new file mode 100644 index 0000000..cacf8c6 --- /dev/null +++ b/include_internal/manager/strategy/CAudioDecoderStrategy.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CAUDIO_DECODER_STRATEGY_H__ +#define __CAUDIO_DECODER_STRATEGY_H__ + +#include +#include + +class CRequest; +class CVirtualResource; +class CAllocateStrategy; +class CAudioDecoderStrategy: public CAllocateStrategy +{ +public: + CAudioDecoderStrategy() = default; + ~CAudioDecoderStrategy() = default; + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource *vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); +private: + int GetRetirableConsumers(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); +}; + +#endif //__CAUDIO_DECODER_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CExclusiveStrategy.h b/include_internal/manager/strategy/CExclusiveStrategy.h new file mode 100644 index 0000000..1a54657 --- /dev/null +++ b/include_internal/manager/strategy/CExclusiveStrategy.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CEXCLUSIVE_STRATEGY_H__ +#define __CEXCLUSIVE_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CAllocateStrategy; +class CExclusiveStrategy: public CAllocateStrategy +{ +public: + CExclusiveStrategy() = default; + ~CExclusiveStrategy() = default; + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource * vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + +private: + int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + int getRetirableConsumersShare(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req); + bool isAllocatableResource(CVirtualResource *vresource, CRequest *req); + bool ContainAvailableResource(std::multimap vresources); + bool isSharableResource(CVirtualResource *vresource, CRequest *req); + bool ContainSharableResource(std::multimap vresources); +}; + +#endif //__CEXCLUSIVE_STRATEGY_H__ + diff --git a/include_internal/manager/strategy/CInvalidModeStrategy.h b/include_internal/manager/strategy/CInvalidModeStrategy.h new file mode 100644 index 0000000..82e363e --- /dev/null +++ b/include_internal/manager/strategy/CInvalidModeStrategy.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CINVALID_MODE_STRATEGY_H__ +#define __CINVALID_MODE_STRATEGY_H__ + +#include +#include + +class CRequest; +class CAllocateModeStrategy; +class CInvalidModeStrategy: public CAllocateModeStrategy +{ +public: + CInvalidModeStrategy(); + ~CInvalidModeStrategy(); + + bool CanAllocateResources(std::vector requests, rms_allocate_result_s *result); + void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices); +}; + +#endif// __CINVALID_MODE_STRATEGY_H__ + diff --git a/include_internal/manager/strategy/CMixingStrategy.h b/include_internal/manager/strategy/CMixingStrategy.h new file mode 100644 index 0000000..f27b8ff --- /dev/null +++ b/include_internal/manager/strategy/CMixingStrategy.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CMIXING_STRATEGY_H__ +#define __CMIXING_STRATEGY_H__ + +#include +#include + +class CRequest; +class CAudioCodec; +class CVirtualResource; +class CMixingMode; +class CMixingStrategy +{ +public: + static CMixingStrategy *getInstance(); + ~CMixingStrategy() = default; + + bool isAvailableAudioCodec(std::string name, int consumer_id, rms_error_type_e *reason); + int getReclaimableAudioCodecConsumers(std::string codec_name, int consumer_id, CRequest *req, std::multimap* reclaimables, rms_error_type_e *err_type); + void updateReasonByAudioCodec(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason); + + int getReclaimableMixingModeConsumers(rms_mixing_mode_e mode, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type); + void updateReasonByMixingMode(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason); + bool isAvailableMixingMode(rms_mixing_mode_e mode); + +private: + CMixingStrategy() = default; + + bool needReclaimCheck(rms_error_type_e reason); + bool canReclaimAudioCodec(std::string codec_name, int consumer_id); + bool canReclaimMixingMode(rms_mixing_mode_e mode, int consumer_id); + bool canReclaimMixingMode(rms_mixing_mode_e mode, CMixingMode *cur_mode, int consumer_id); + + static CMixingStrategy *m_instance; +}; + +#endif //__CMIXING_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h b/include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h new file mode 100644 index 0000000..e36812b --- /dev/null +++ b/include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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. +*/ + +#ifndef __C_NDECODING_VIDEO_DECODER_STRATEGY_H__ +#define __C_NDECODING_VIDEO_DECODER_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CAllocateStrategy; +class CNDecodingVideoDecoderStrategy: public CAllocateStrategy +{ +public: + CNDecodingVideoDecoderStrategy() = default; + ~CNDecodingVideoDecoderStrategy() = default; + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource *vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type); + +private: + int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req); + void updateReasonByBW(CVirtualResource *vresource, CRequest *req); + void updateReasonByTripleDecoding(CRequest *req); + bool isAllocatableResource(CVirtualResource *vresource, CRequest *req); + bool ContainAvailableResource(std::multimap vresources); + bool canReclaimRequiredBW(CRequest *req, unsigned int bw); + int GetConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap* return_ids); + bool canReclaimActiveVideoDecoders(CRequest *req); + int GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap* reclaimables, CRequest *req, rms_error_type_e *err_type); + void SelectDevicesByMainSub(CRequest *req, std::map *src, std::map *result); + int GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map bw_consumers, std::multimap *reclaimed_consumers); +}; + +#endif //__C_NDECODING_VIDEO_DECODER_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CNormalModeStrategy.h b/include_internal/manager/strategy/CNormalModeStrategy.h new file mode 100644 index 0000000..92d9219 --- /dev/null +++ b/include_internal/manager/strategy/CNormalModeStrategy.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CNORMAL_MODE_STRATEGY_H__ +#define __CNORMAL_MODE_STRATEGY_H__ + +#include +#include + +class CRequest; +class CAllocateModeStrategy; +class CNormalModeStrategy:public CAllocateModeStrategy +{ +public: + CNormalModeStrategy(); + ~CNormalModeStrategy(); + + bool CanAllocateResources(std::vector requests, rms_allocate_result_s *result); + void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices); +private: + rms_error_type_e GetCandidateFindResult(std::vector requests); +}; + +#endif //__CNORMAL_MODE_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CNormalStrategy.h b/include_internal/manager/strategy/CNormalStrategy.h new file mode 100644 index 0000000..d7bb414 --- /dev/null +++ b/include_internal/manager/strategy/CNormalStrategy.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CNORMAL_STRATEGY_H__ +#define __CNORMAL_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CNormalStrategy: public CAllocateStrategy +{ +public: + CNormalStrategy(); + ~CNormalStrategy(); + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource *vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type); + +private: + bool ContainFreeResource(std::multimap vresources); +}; + +#endif //__CALLOCATE_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CPreferenceModeStrategy.h b/include_internal/manager/strategy/CPreferenceModeStrategy.h new file mode 100644 index 0000000..e1fcb29 --- /dev/null +++ b/include_internal/manager/strategy/CPreferenceModeStrategy.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CPREFERENCE_MODE_STRATEGY_H__ +#define __CPREFERENCE_MODE_STRATEGY_H__ + +#include +#include + +class CRequest; +class CAllocateModeStrategy; +class CPreferenceModeStrategy: public CAllocateModeStrategy +{ +public: + CPreferenceModeStrategy(); + ~CPreferenceModeStrategy(); + + bool CanAllocateResources(std::vector requests, rms_allocate_result_s *result); + void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices); +}; + +#endif //__CPREFERENCE_MODE_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CScalerStrategy.h b/include_internal/manager/strategy/CScalerStrategy.h new file mode 100644 index 0000000..5bbd14c --- /dev/null +++ b/include_internal/manager/strategy/CScalerStrategy.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CSCALER_STRATEGY_H__ +#define __CSCALER_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CScalerStrategy: public CAllocateStrategy +{ +public: + CScalerStrategy(); + ~CScalerStrategy(); + + CVirtualResource * findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource * vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type); + void SelectConsumersByZoneId(int zone_id, std::map> *candidates, std::multimap *result); + void SelectConsumersByAllocationTime(std::map> *candidates, std::multimap *result); + +private: + bool ContainFreeResource(std::multimap vresources); + bool ContainInterlacedNotSupportedApp(std::map> *candidates); + int FindScalerInSameZone(int zone_id); + int FindScalerUsedByAppInterlacedNotSupported(std::map> *candidates); + void SelectConsumersBySwap(int zone_id, std::map> *candidates, std::multimap *result); + void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req); +}; + +#endif //__CSCALER_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CVideoDecoderStrategy.h b/include_internal/manager/strategy/CVideoDecoderStrategy.h new file mode 100644 index 0000000..9552d08 --- /dev/null +++ b/include_internal/manager/strategy/CVideoDecoderStrategy.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CVIDEO_DECODER_STRATEGY_H__ +#define __CVIDEO_DECODER_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CAllocateStrategy; +class CVideoDecoderStrategy: public CAllocateStrategy +{ +public: + CVideoDecoderStrategy(); + ~CVideoDecoderStrategy() = default; + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource *vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type); + +private: + int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req); + void updateReasonByBW(CVirtualResource *vresource, CRequest *req); + void updateReasonByTripleDecoding(CRequest *req); + bool isAllocatableResource(CVirtualResource *vresource, CRequest *req); + bool ContainAvailableResource(std::multimap vresources); + bool canReclaimRequiredBW(CRequest *req, unsigned int bw); + int getConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap* return_ids); + int GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int bw, std::map candidates, std::multimap* return_ids); + bool canReclaimActiveVideoDecoders(CRequest *req); + int GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap* reclaimables, CRequest *req, rms_error_type_e *err_type); + void SelectConsumersByAllocationTime(std::map> *candidates, std::multimap *result); + void SelectConsumersByZoneId(int zone_id, std::map> *candidates, std::multimap *result); + void SelectInSameCategoryAndZone(int zone_id, std::map> *candidates, std::multimap *result); + void SelectInSameZone(int zone_id, std::map> candidates, std::multimap *result); + void SelectDevicesByMainSub(CRequest *req, std::map *src, std::map *result); + int GetConflictScore(int n_conflicts); + + bool m_reclaim_policy_by_zone_id; +}; + +#endif //_CVIDEO_DECODER_STRATEGY_H__ diff --git a/include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h b/include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h new file mode 100644 index 0000000..c982a24 --- /dev/null +++ b/include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__ +#define __CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__ + +#include +#include +#include + +class CRequest; +class CVirtualResource; +class CAllocateStrategy; +class CVideoEncoderExclusiveStrategy: public CAllocateStrategy +{ +public: + CVideoEncoderExclusiveStrategy() = default; + ~CVideoEncoderExclusiveStrategy() = default; + + CVirtualResource *findCandidate(std::map vresources, CRequest *req); + int reserveResource(CVirtualResource *vrsc, CRequest *req); + void GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type); + +private: + int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type); + void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req); + bool isAllocatableResource(CVirtualResource *vresource, CRequest *req); + bool ContainAvailableResource(std::multimap vresources, CRequest *req); +}; + +#endif //__CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__ diff --git a/include_internal/rms-dbus-interface.xml b/include_internal/rms-dbus-interface.xml new file mode 100644 index 0000000..9a251e1 --- /dev/null +++ b/include_internal/rms-dbus-interface.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include_internal/rms_debug.h b/include_internal/rms_debug.h new file mode 100644 index 0000000..26214bf --- /dev/null +++ b/include_internal/rms_debug.h @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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. +*/ + +#ifndef __RMS_DEBUG_H__ +#define __RMS_DEBUG_H__ + +#include + + +#ifdef LOG_TAG +#undef LOG_TAG +#endif//LOG_TAG + +#define LOG_TAG "RSC_MGR_SERVER" + +#ifndef SERVER_ERR +#define SERVER_ERR(fmt, args...)SLOGE(fmt, ##args) +#endif + +#ifndef SERVER_DBG +#define SERVER_DBG(fmt, args...)SLOGD(fmt, ##args) +#endif + +#ifndef SERVER_INFO +#define SERVER_INFO(fmt, args...)SLOGI(fmt, ##args) +#endif + +#ifndef SERVER_WARN +#define SERVER_WARN(fmt, args...)SLOGW(fmt, ##args) +#endif + + +#endif//__RMS_DEBUG_H__ + diff --git a/include_internal/rms_log.h b/include_internal/rms_log.h new file mode 100644 index 0000000..fa8ae0a --- /dev/null +++ b/include_internal/rms_log.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_LOG_H__ +#define __RMS_LOG_H__ + +#include + +static char g_rms_dlog_msg[4096] = {0,}; +static int g_rms_dlog_msg_pose = 0; + +static void rms_log_reset() { g_rms_dlog_msg_pose = 0; } +static void rms_log_add(const char *format_str, ...) __attribute__ ((format (printf, 1, 2))); +static void rms_log_add(const char *format_str, ...) { + va_list argptr; + va_start(argptr, format_str); + g_rms_dlog_msg_pose += vsnprintf(g_rms_dlog_msg + g_rms_dlog_msg_pose, sizeof(g_rms_dlog_msg) - 1 - g_rms_dlog_msg_pose, format_str, argptr); + va_end(argptr); +} + +#define RMS_LOGE_FLUSH() SLOGE("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0 +#define RMS_LOGI_FLUSH() SLOGI("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0 +#define RMS_LOGD_FLUSH() SLOGD("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0 + +#endif //__RMS_LOG_H__ + diff --git a/include_internal/rms_type.h b/include_internal/rms_type.h new file mode 100644 index 0000000..ce9eecc --- /dev/null +++ b/include_internal/rms_type.h @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __RMS_TYPE_H__ +#define __RMS_TYPE_H__ + +#include + +#define IN +#define OUT + +#define RMS_REMOTE_CONSUMER_ID 1000 +#define RMS_APPID_LENGTH 1024 +#define RMS_NAME_BUF_SIZE 128 +#define RMS_MAX_DEVICE 10 + +typedef enum { + RMS_CALLBACK_TYPE_UNKNOWN = 1, + RMS_CALLBACK_TYPE_RESOURCE_CONFLICT, // common resource conflict + RMS_CALLBACK_TYPE_RESOURCE_CONFLICT_UD, // resource conflict by ud device +} rms_callback_type_e; + +typedef enum { + RMS_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED = RI_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED, + RMS_CATEGORY_NOT_PERMITTED = RI_CATEGORY_NOT_PERMITTED, /**< Not permitted category by resource policy */ + RMS_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED = RI_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED, + RMS_CATEGORY_JPEG_DECODER_NOT_SUPPORTED = RI_CATEGORY_JPEG_DECODER_NOT_SUPPORTED, + RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED = RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, + RMS_CATEGORY_NONE = RI_CATEGORY_NONE, + RMS_CATEGORY_AUDIO_DECODER = RI_CATEGORY_AUDIO_DECODER, /* Audio Decoder */ + RMS_CATEGORY_AUDIO_EVENT_COMPRESS = RI_CATEGORY_AUDIO_EVENT_COMPRESS, + RMS_CATEGORY_AUDIO_SPDIF_ES_OUTPUT = RI_CATEGORY_AUDIO_SPDIF_ES_OUTPUT, + RMS_CATEGORY_VIDEO_DECODER = RI_CATEGORY_VIDEO_DECODER, /* Video Decoder - MFD (Multi Format Decoder), FullHD */ + RMS_CATEGORY_DEMUX = RI_CATEGORY_DEMUX, /* Demux */ + RMS_CATEGORY_AUDIO_ENCODER = RI_CATEGORY_AUDIO_ENCODER, /* Audio Encoder */ + RMS_CATEGORY_VIDEO_ENCODER = RI_CATEGORY_VIDEO_ENCODER, /* Video Encoder */ + RMS_CATEGORY_SCALER = RI_CATEGORY_SCALER, /* Main Scaler */ + RMS_CATEGORY_TUNER = RI_CATEGORY_TUNER, /* Tuner */ + RMS_CATEGORY_AUDIO_MAIN_OUT = RI_CATEGORY_AUDIO_MAIN_OUT, /* Logical resource to manage ALSA main out source */ + RMS_CATEGORY_AUDIO_REMOTE_OUT = RI_CATEGORY_AUDIO_REMOTE_OUT, /* Logical resource to manage ALSA remote out source */ + RMS_CATEGORY_AUDIO_SCART_OUT = RI_CATEGORY_AUDIO_SCART_OUT, /* Logical resource to manage ALSA scart out source */ + RMS_CATEGORY_MM_PCM_OUT = RI_CATEGORY_MM_PCM_OUT, /* PCM out - used by mm-player */ + RMS_CATEGORY_AUDIO_DECODER_SUB = RI_CATEGORY_AUDIO_DECODER_SUB, /* Sub Audio Decoder */ + RMS_CATEGORY_AUDIO_DECODER_PRIMARY = RI_CATEGORY_AUDIO_DECODER_PRIMARY, /* Sub Audio Decoder */ + RMS_CATEGORY_JPEG_DECODER = RI_CATEGORY_JPEG_DECODER, /* JPEG Decoder */ + RMS_CATEGORY_SCALER_SUB = RI_CATEGORY_SCALER_SUB, /* Sub Scaler */ + RMS_CATEGORY_EXT_VIDEO_SRC = RI_CATEGORY_EXT_VIDEO_SRC, /* Logical resource to manage video input path - used by player */ + RMS_CATEGORY_EXT_AUDIO_SRC = RI_CATEGORY_EXT_AUDIO_SRC, /* Logical resource to manage audio input path - used by player */ + RMS_CATEGORY_EXT_HDMI_SRC = RI_CATEGORY_EXT_HDMI_SRC, /* Logical resource to manage hdmi input path - used by player */ + RMS_CATEGORY_VIDEO_DECODER_SUB = RI_CATEGORY_VIDEO_DECODER_SUB, /* Sub Video Decoder - MFD (Multi Format Decoder), FullHD */ + RMS_CATEGORY_CAMERA = RI_CATEGORY_CAMERA, /* Logical resource to manage camera device */ + RMS_CATEGORY_DEMUX_REC = RI_CATEGORY_DEMUX_REC, /* Demux for recording */ + RMS_CATEGORY_TUNER_SUB = RI_CATEGORY_TUNER_SUB, /* Sub Tuner */ + RMS_CATEGORY_MJPEG_DECODER = RI_CATEGORY_MJPEG_DECODER, /* MJPEG decoder */ + + RMS_CATEGORY_INPUT_SRC_DTV = RI_CATEGORY_INPUT_SRC_DTV, + RMS_CATEGORY_INPUT_SRC_ATV = RI_CATEGORY_INPUT_SRC_ATV, + RMS_CATEGORY_INPUT_SRC_HDMI = RI_CATEGORY_INPUT_SRC_HDMI, + RMS_CATEGORY_INPUT_SRC_COMP = RI_CATEGORY_INPUT_SRC_COMP, + RMS_CATEGORY_INPUT_SRC_AV = RI_CATEGORY_INPUT_SRC_AV, + RMS_CATEGORY_INPUT_SRC_SCART = RI_CATEGORY_INPUT_SRC_SCART, + + RMS_CATEGORY_MIC = RI_CATEGORY_MIC, /* MIC */ + RMS_CATEGORY_EXT_COMP_SRC = RI_CATEGORY_EXT_COMP_SRC, + RMS_CATEGORY_EXT_AV_SRC = RI_CATEGORY_EXT_AV_SRC, + RMS_CATEGORY_SW_DECODER = RI_CATEGORY_SW_DECODER, + RMS_CATEGORY_MMP_MEMORY_CLUSTER = RI_CATEGORY_MMP_MEMORY_CLUSTER, + + RMS_CATEGORY_EXT_AUDIO_SRC_DVI = RI_CATEGORY_EXT_AUDIO_SRC_DVI, //LFD only + RMS_CATEGORY_EXT_AUDIO_SRC_HDMI = RI_CATEGORY_EXT_AUDIO_SRC_HDMI,//LFD only + RMS_CATEGORY_EXT_AUDIO_SRC_DP = RI_CATEGORY_EXT_AUDIO_SRC_DP, //LFD only, Diplay Port + RMS_CATEGORY_EXT_AUDIO_SRC_SBB = RI_CATEGORY_EXT_AUDIO_SRC_SBB, //LFD only, MagicInfo I + RMS_CATEGORY_EXT_AUDIO_SRC_OPS = RI_CATEGORY_EXT_AUDIO_SRC_OPS, //LFD only, PIM(Plug In Module) + RMS_CATEGORY_EXT_VIDEO_SRC_DVI = RI_CATEGORY_EXT_VIDEO_SRC_DVI, //LFD only + RMS_CATEGORY_EXT_VIDEO_SRC_HDMI = RI_CATEGORY_EXT_VIDEO_SRC_HDMI,//LFD only + RMS_CATEGORY_EXT_VIDEO_SRC_DP = RI_CATEGORY_EXT_VIDEO_SRC_DP, //LFD only, Diplay Port + RMS_CATEGORY_EXT_VIDEO_SRC_SBB = RI_CATEGORY_EXT_VIDEO_SRC_SBB, //LFD only, MagicInfo I + RMS_CATEGORY_EXT_VIDEO_SRC_OPS = RI_CATEGORY_EXT_VIDEO_SRC_OPS, //LFD only, PIM(Plug In Module) + RMS_CATEGORY_EXT_PC_SRC = RI_CATEGORY_EXT_PC_SRC, + + RMS_CATEGORY_SCALER_BG = RI_CATEGORY_SCALER_BG, + RMS_CATEGORY_AUDIO_SUB_OUT = RI_CATEGORY_AUDIO_SUB_OUT, + RMS_CATEGORY_GRAPHIC_PLANE = RI_CATEGORY_GRAPHIC_PLANE, + RMS_CATEGORY_DISPLAY_OUT = RI_CATEGORY_DISPLAY_OUT, + RMS_CATEGORY_IMAGE_DECODER = RI_CATEGORY_IMAGE_DECODER, + RMS_CATEGORY_VIDEO_ENCODER_EXCLUSIVE = RI_CATEGORY_VIDEO_ENCODER_EXCLUSIVE, + + RMS_CATEGORY_JPEG_DECODER_OPTION = RI_CATEGORY_JPEG_DECODER_OPTION, + RMS_CATEGORY_JPEG_DECODER_FHD = RI_CATEGORY_JPEG_DECODER_FHD, + RMS_CATEGORY_JPEG_DECODER_UHD = RI_CATEGORY_JPEG_DECODER_UHD, + RMS_CATEGORY_JPEG_DECODER_8K = RI_CATEGORY_JPEG_DECODER_8K, + RMS_CATEGORY_JPEG_DECODER_OPTION_MAX = (RMS_CATEGORY_JPEG_DECODER_8K + 1), + + RMS_CATEGORY_MJPEG_DECODER_OPTION = RI_CATEGORY_MJPEG_DECODER_OPTION, + RMS_CATEGORY_MJPEG_DECODER_FHD = RI_CATEGORY_MJPEG_DECODER_FHD, + RMS_CATEGORY_MJPEG_DECODER_UHD = RI_CATEGORY_MJPEG_DECODER_UHD, + RMS_CATEGORY_MJPEG_DECODER_8K = RI_CATEGORY_MJPEG_DECODER_8K, + RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX = (RMS_CATEGORY_MJPEG_DECODER_8K + 1), + + RMS_CATEGORY_HEIC_DECODER_OPTION = RI_CATEGORY_HEIC_DECODER_OPTION, + RMS_CATEGORY_HEIC_DECODER = RI_CATEGORY_HEIC_DECODER, + RMS_CATEGORY_HEIC_DECODER_OPTION_MAX = (RMS_CATEGORY_HEIC_DECODER + 1), + + RMS_CATEGORY_AUDIO_DECODER_OPTION = RI_CATEGORY_AUDIO_DECODER_OPTION, /**< Audio Decoder option min*/ + RMS_CATEGORY_AUDIO_DECODER_ANY = RI_CATEGORY_AUDIO_DECODER_ANY, /**< Available audio Decoder will be allocated*/ + RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED = RI_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED, /**< Audio Decoder is not supported*/ + RMS_CATEGORY_AUDIO_DECODER_MPEG = RI_CATEGORY_AUDIO_DECODER_MPEG, + RMS_CATEGORY_AUDIO_DECODER_AC3 = RI_CATEGORY_AUDIO_DECODER_AC3, + RMS_CATEGORY_AUDIO_DECODER_E_AC3 = RI_CATEGORY_AUDIO_DECODER_E_AC3, + RMS_CATEGORY_AUDIO_DECODER_TRUEHD = RI_CATEGORY_AUDIO_DECODER_TRUEHD, + RMS_CATEGORY_AUDIO_DECODER_AC4 = RI_CATEGORY_AUDIO_DECODER_AC4, + RMS_CATEGORY_AUDIO_DECODER_VORBIS = RI_CATEGORY_AUDIO_DECODER_VORBIS, + RMS_CATEGORY_AUDIO_DECODER_G2COOK = RI_CATEGORY_AUDIO_DECODER_G2COOK, + RMS_CATEGORY_AUDIO_DECODER_AAC = RI_CATEGORY_AUDIO_DECODER_AAC, + RMS_CATEGORY_AUDIO_DECODER_HE_AAC = RI_CATEGORY_AUDIO_DECODER_HE_AAC, + RMS_CATEGORY_AUDIO_DECODER_WMA = RI_CATEGORY_AUDIO_DECODER_WMA, + RMS_CATEGORY_AUDIO_DECODER_ADPCM = RI_CATEGORY_AUDIO_DECODER_ADPCM, + RMS_CATEGORY_AUDIO_DECODER_MPEG_H = RI_CATEGORY_AUDIO_DECODER_MPEG_H, + RMS_CATEGORY_AUDIO_DECODER_OPUS = RI_CATEGORY_AUDIO_DECODER_OPUS, + RMS_CATEGORY_AUDIO_DECODER_PCM = RI_CATEGORY_AUDIO_DECODER_PCM, + RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX = (RMS_CATEGORY_AUDIO_DECODER_PCM + 1), + + RMS_CATEGORY_SCALER_OPTION = RI_CATEGORY_SCALER_OPTION, + RMS_CATEGORY_SCALER_MULTIVIEW = RI_CATEGORY_SCALER_MULTIVIEW, + RMS_CATEGORY_SCALER_SUB2 = RI_CATEGORY_SCALER_SUB2, + RMS_CATEGORY_SCALER_SUB3 = RI_CATEGORY_SCALER_SUB3, + RMS_CATEGORY_SCALER_VR360_DETILED = RI_CATEGORY_SCALER_VR360_DETILED, + RMS_CATEGORY_SCALER_VR360_NATIVE_OUT = RI_CATEGORY_SCALER_VR360_NATIVE_OUT, + RMS_CATEGORY_SCALER_INTERLACED = RI_CATEGORY_SCALER_INTERLACED, + RMS_CATEGORY_SCALER_OPTION_MAX = (RMS_CATEGORY_SCALER_INTERLACED + 1), + + RMS_CATEGORY_VIDEO_DECODER_OPTION = RI_CATEGORY_VIDEO_DECODER_OPTION, + RMS_CATEGORY_VIDEO_DECODER_UHD = RI_CATEGORY_VIDEO_DECODER_UHD, /* Video Decoder, UHD */ + RMS_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_H264_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_H264_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_H264_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_420_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_60P, + RMS_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_60P, + + //VR360 + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_420_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_420_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_422_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_422_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_422_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_FHD_10BIT_422_60P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_422_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_422_30P, + RMS_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_422_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_VR360_UHD_10BIT_422_60P, + RMS_CATEGORY_VIDEO_DECODER_H264_VR360_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_VR360_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_H264_VR360_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_H264_VR360_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_H264_VR360_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_VR360_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_H264_VR360_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_H264_VR360_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_8BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_8BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_FHD_10BIT_420_60P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_420_30P, + RMS_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_VP9_VR360_UHD_10BIT_420_60P, + + RMS_CATEGORY_VIDEO_DECODER_HEVC_SHVC_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_SHVC_8BIT_30P, /**< video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_SHVC_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_SHVC_8BIT_60P, /**< video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_SHVC_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_SHVC_10BIT_30P, /**< video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_SHVC_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_SHVC_10BIT_60P, /**< video decoder for hevc */ + + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_8BIT_30P, /**< 1080: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_8BIT_60P, /**< 1081: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_30P, /**< 1082: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_60P, /**< 1083: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_420_30P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_420_30P, /**< 1084: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_420_60P = RI_CATEGORY_VIDEO_DECODER_HEVC_8K_10BIT_420_60P, /**< 1085: video decoder for hevc 8k */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_120P, /**< 1086: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_120P, /**< 1087: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_120P, /**< 1088: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_422_120P, /**< 1089: video decoder for hevc */ + + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_30P, /**< 1090: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_60P, /**< 1091: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_30P, /**< 1092: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_60P, /**< 1093: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_30P, /**< 1094: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_60P, /**< 1095: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_30P, /**< 1096: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_60P, /**< 1097: video decoder for av1 */ + + RMS_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_30P, /**< 1098: video decoder for av1 8k */ + RMS_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_60P, /**< 1099: video decoder for av1 8k */ + RMS_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_30P, /**< 1100: video decoder for av1 8k */ + RMS_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_60P, /**< 1101: video decoder for av1 8k */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_30P, /**< 1102: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_60P, /**< 1103: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_30P,/**< 1104: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_60P,/**< 1105: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_30P, /**< 1106: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_60P, /**< 1107: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_30P,/**< 1108: video decoder for vp9 vr360 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_60P,/**< 1109: video decoder for vp9 vr360 */ + + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_120P, /**< 1110: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_120P, /**< 1111: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_120P = RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_422_120P, /**< 1112: video decoder for hevc */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_120P, /**< 1113: video decoder for h264 */ + RMS_CATEGORY_VIDEO_DECODER_H264_HD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_HD_8BIT_30P, /**< 1114: video decoder for h264 */ + RMS_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_120P, /**< 1115: video decoder for mpeg1 */ + RMS_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_120P, /**< 1116: video decoder for mpeg2 */ + RMS_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_120P, /**< 1117: video decoder for mpeg4 */ + RMS_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_120P, /**< 1118: video decoder for h263 */ + RMS_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_120P, /**< 1119: video decoder for vp8 */ + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_120P, /**< 1120: video decoder for vp8 */ + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_120P, /**< 1121: video decoder for vp8 */ + RMS_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_120P, /**< 1122: video decoder for rv */ + RMS_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_120P, /**< 1123: video decoder for wmv9 */ + RMS_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_120P, /**< 1124: video decoder for avs */ + RMS_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_120P, /**< 1125: video decoder for avs+ */ + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_120P, /**< 1126: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_120P, /**< 1127: video decoder for av1 */ + + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_30P, /**< 1128: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_60P, /**< 1129: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_8BIT_120P, /**< 1130: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_30P, /**< 1131: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_60P, /**< 1132: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_AVS2_FHD_10BIT_120P, /**< 1133: video decoder for avs2 */ + + RMS_CATEGORY_VIDEO_DECODER_AVS2_UHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS2_UHD_8BIT_30P, /**< 1134: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_UHD_8BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS2_UHD_8BIT_60P, /**< 1135: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_AVS2_UHD_10BIT_30P, /**< 1136: video decoder for avs2 */ + RMS_CATEGORY_VIDEO_DECODER_AVS2_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_AVS2_UHD_10BIT_60P, /**< 1137: video decoder for avs2 */ + + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_30P, /**< 1138: video decoder for vp9 */ + RMS_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_60P, /**< 1139: video decoder for vp9 */ + RMS_CATEGORY_VIDEO_DECODER_VP9_UHD_10BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP9_UHD_10BIT_30P, /**< 1140: video decoder for vp9 */ + RMS_CATEGORY_VIDEO_DECODER_VP9_UHD_10BIT_60P = RI_CATEGORY_VIDEO_DECODER_VP9_UHD_10BIT_60P, /**< 1141: video decoder for vp9 */ + + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_120P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_120P, /**< 1142: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_120P = RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_120P, /**< 1143: video decoder for av1 */ + RMS_CATEGORY_VIDEO_DECODER_VP8_qHD_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_VP8_qHD_8BIT_30P, /**< 1144: video decoder for vp8 */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_N_8BIT_30P = RI_CATEGORY_VIDEO_DECODER_H264_FHD_N_8BIT_30P, /**< 1145: video decoder for h264 */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P_MV = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P_MV, /**< 1146: video decoder for h264 multiview scenario */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P_MV = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P_MV, /**< 1147: video decoder for h264 multiview scenario */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P_PORTRAIT = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P_PORTRAIT, /**< 1148: video decoder for h264 portrait */ + RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P_PORTRAIT = RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P_PORTRAIT, /**< 1149: video decoder for h264 portrait */ + RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX = (RMS_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P_PORTRAIT + 1) +} rms_rsc_category_e; + +typedef enum { + RMS_DEVICE_NONE = RI_DEVICE_UNDEFINED, + RMS_DEVICE_AUDIO_MAIN_OUT = RI_DEVICE_AUDIO_MAIN_OUT, + RMS_DEVICE_AUDIO_REMOTE_OUT = RI_DEVICE_AUDIO_REMOTE_OUT, + RMS_DEVICE_AUDIO_SCART_OUT = RI_DEVICE_AUDIO_SCART_OUT, + RMS_DEVICE_AUDIO_EVENT_COMPRESS = RI_DEVICE_AUDIO_EVENT_COMPRESS, + RMS_DEVICE_MM_PCM_OUT = RI_DEVICE_MM_PCM_OUT, + RMS_DEVICE_JPEG_DECODER = RI_DEVICE_JPEG_DECODER, + RMS_DEVICE_DEMUX0 = RI_DEVICE_DEMUX0, + RMS_DEVICE_DEMUX1 = RI_DEVICE_DEMUX1, + RMS_DEVICE_DEMUX2 = RI_DEVICE_DEMUX2, + RMS_DEVICE_AUDIO_ENCODER = RI_DEVICE_AUDIO_ENCODER, + RMS_DEVICE_VIDEO_ENCODER = RI_DEVICE_VIDEO_ENCODER, + RMS_DEVICE_SCALER = RI_DEVICE_SCALER, + RMS_DEVICE_EXT_VIDEO_SRC = RI_DEVICE_EXT_VIDEO_SRC, + RMS_DEVICE_EXT_AUDIO_SRC = RI_DEVICE_EXT_AUDIO_SRC, + RMS_DEVICE_EXT_HDMI_SRC = RI_DEVICE_EXT_HDMI_SRC, + RMS_DEVICE_CAMERA = RI_DEVICE_CAMERA, + RMS_DEVICE_TUNER = RI_DEVICE_TUNER, + RMS_DEVICE_TUNER_SUB = RI_DEVICE_TUNER_SUB, + RMS_DEVICE_SCALER_SUB = RI_DEVICE_SCALER_SUB, + RMS_DEVICE_AUDIO_DECODER = RI_DEVICE_AUDIO_DECODER, + RMS_DEVICE_AUDIO_DECODER_SUB = RI_DEVICE_AUDIO_DECODER_SUB, + RMS_DEVICE_AUDIO_DECODER_PRIMARY = RI_DEVICE_AUDIO_DECODER_PRIMARY, + RMS_DEVICE_VIDEO_DECODER_MAIN = RI_DEVICE_VIDEO_DECODER_MAIN, + RMS_DEVICE_VIDEO_DECODER_SUB = RI_DEVICE_VIDEO_DECODER_SUB, + RMS_DEVICE_VIDEO_DECODER_UDDEC = RI_DEVICE_VIDEO_DECODER_UDDEC, + RMS_DEVICE_VIDEO_DECODER_UDHEVC = RI_DEVICE_VIDEO_DECODER_UDHEVC, + RMS_DEVICE_AUDIO_SPDIF_ES_OUTPUT = RI_DEVICE_AUDIO_SPDIF_ES_OUTPUT, + RMS_DEVICE_MIC = RI_DEVICE_MIC, + RMS_DEVICE_EXT_COMP_SRC = RI_DEVICE_EXT_COMP_SRC, + RMS_DEVICE_EXT_AV_SRC = RI_DEVICE_EXT_AV_SRC, + RMS_DEVICE_MJPEG_DECODER = RI_DEVICE_MJPEG_DECODER, + RMS_DEVICE_JPEG_DECODER_UHD = RI_DEVICE_JPEG_DECODER_UHD, + RMS_DEVICE_MJPEG_DECODER_UHD = RI_DEVICE_MJPEG_DECODER_UHD, + RMS_DEVICE_SW_DECODER = RI_DEVICE_SW_DECODER, + RMS_DEVICE_DEMUX3 = RI_DEVICE_DEMUX3, + RMS_DEVICE_MMP_MEMORY_CLUSTER1 = RI_DEVICE_MMP_MEMORY_CLUSTER1, + RMS_DEVICE_MMP_MEMORY_CLUSTER2 = RI_DEVICE_MMP_MEMORY_CLUSTER2, + RMS_DEVICE_MMP_MEMORY_CLUSTER3 = RI_DEVICE_MMP_MEMORY_CLUSTER3, + RMS_DEVICE_MMP_MEMORY_CLUSTER4 = RI_DEVICE_MMP_MEMORY_CLUSTER4, + RMS_DEVICE_MMP_MEMORY_CLUSTER5 = RI_DEVICE_MMP_MEMORY_CLUSTER5, + RMS_DEVICE_EXT_AUDIO_SRC_DVI = RI_DEVICE_EXT_AUDIO_SRC_DVI, //LFD only + RMS_DEVICE_EXT_AUDIO_SRC_HDMI = RI_DEVICE_EXT_AUDIO_SRC_HDMI,//LFD only + RMS_DEVICE_EXT_AUDIO_SRC_DP = RI_DEVICE_EXT_AUDIO_SRC_DP, //LFD only, Diplay Port + RMS_DEVICE_EXT_AUDIO_SRC_SBB = RI_DEVICE_EXT_AUDIO_SRC_SBB, //LFD only, MagicInfo I + RMS_DEVICE_EXT_AUDIO_SRC_OPS = RI_DEVICE_EXT_AUDIO_SRC_OPS, //LFD only, PIM(Plug In Module) + RMS_DEVICE_EXT_VIDEO_SRC_DVI = RI_DEVICE_EXT_VIDEO_SRC_DVI, //LFD only + RMS_DEVICE_EXT_VIDEO_SRC_HDMI = RI_DEVICE_EXT_VIDEO_SRC_HDMI,//LFD only + RMS_DEVICE_EXT_VIDEO_SRC_DP = RI_DEVICE_EXT_VIDEO_SRC_DP, //LFD only, Diplay Port + RMS_DEVICE_EXT_VIDEO_SRC_SBB = RI_DEVICE_EXT_VIDEO_SRC_SBB, //LFD only, MagicInfo I + RMS_DEVICE_EXT_VIDEO_SRC_OPS = RI_DEVICE_EXT_VIDEO_SRC_OPS, //LFD only, PIM(Plug In Module) + RMS_DEVICE_VIDEO_DECODER_DVDE0 = RI_DEVICE_VIDEO_DECODER_DVDE0, + RMS_DEVICE_VIDEO_DECODER_DVDE1 = RI_DEVICE_VIDEO_DECODER_DVDE1, + RMS_DEVICE_VIDEO_DECODER_HEN = RI_DEVICE_VIDEO_DECODER_HEN, + RMS_DEVICE_DEMUX4 = RI_DEVICE_DEMUX4, + RMS_DEVICE_DEMUX5 = RI_DEVICE_DEMUX5, + RMS_DEVICE_DEMUX6 = RI_DEVICE_DEMUX6, + RMS_DEVICE_DEMUX7 = RI_DEVICE_DEMUX7, + RMS_DEVICE_EXT_PC_SRC = RI_DEVICE_EXT_PC_SRC, + RMS_DEVICE_VIDEO_DECODER_VR360DEC = RI_DEVICE_VIDEO_DECODER_VR360DEC, + RMS_DEVICE_VIDEO_DECODER_HEVC_8K = RI_DEVICE_VIDEO_DECODER_HEVC_8K, + RMS_DEVICE_AUDIO_SUB_OUT = RI_DEVICE_AUDIO_SUB_OUT, + RMS_DEVICE_MJPEG_DECODER_SUB = RI_DEVICE_MJPEG_DECODER_SUB, + RMS_DEVICE_GRAPHIC_PLANE = RI_DEVICE_GRAPHIC_PLANE, + RMS_DEVICE_VIDEO_DECODER_DVDE2 = RI_DEVICE_VIDEO_DECODER_DVDE2, + RMS_DEVICE_VIDEO_DECODER_DVDE3 = RI_DEVICE_VIDEO_DECODER_DVDE3, + RMS_DEVICE_HEIC_DECODER = RI_DEVICE_HEIC_DECODER, + RMS_DEVICE_VIDEO_DECODER_DVDE4 = RI_DEVICE_VIDEO_DECODER_DVDE4, + RMS_DEVICE_VIDEO_DECODER_DVDE5 = RI_DEVICE_VIDEO_DECODER_DVDE5, + RMS_DEVICE_VIDEO_DECODER_DVDE6 = RI_DEVICE_VIDEO_DECODER_DVDE6, + RMS_DEVICE_VIDEO_DECODER_DVDE7 = RI_DEVICE_VIDEO_DECODER_DVDE7, + RMS_DEVICE_VIDEO_DECODER_OVDE = RI_DEVICE_VIDEO_DECODER_OVDE, + RMS_DEVICE_SCALER_SUB2 = RI_DEVICE_SCALER_SUB2, + RMS_DEVICE_SCALER_SUB3 = RI_DEVICE_SCALER_SUB3, + RMS_DEVICE_VIDEO_DECODER_MFC2 = RI_DEVICE_VIDEO_DECODER_MFC2, + RMS_DEVICE_VIDEO_DECODER_MFC3 = RI_DEVICE_VIDEO_DECODER_MFC3, + RMS_DEVICE_VIDEO_DECODER_MFC4 = RI_DEVICE_VIDEO_DECODER_MFC4, + RMS_DEVICE_JPEG_DECODER_SUB = RI_DEVICE_JPEG_DECODER_SUB, + RMS_DEVICE_VIDEO_ENCODER_EXCLUSIVE = RI_DEVICE_VIDEO_ENCODER_EXCLUSIVE +} rms_device_e; + +typedef enum { + RMS_STATE_PASSIVE, + RMS_STATE_SHARABLE, + RMS_STATE_EXCLUSIVE, + RMS_STATE_EXCLUSIVE_CONDITIONAL, //no need to request for deallocating resource in case that resource is used by other consumer + RMS_STATE_EXCLUSIVE_AUTO, + RMS_STATE_EXCLUSIVE_PREFERENCE, +} rms_requests_resource_state_e; + +typedef enum { + RMS_INTERNAL_STATE_FREE, + RMS_INTERNAL_STATE_SHARABLE, + RMS_INTERNAL_STATE_SHARED, + RMS_INTERNAL_STATE_EXCLUSIVE, + RMS_INTERNAL_STATE_ERROR +} rms_resource_internal_state_e; + +typedef enum { + RMS_CONFLICT_NORMAL, + RMS_CONFLICT_UHD_RESOURCE_REQUEST +} rms_resource_conflict_msg_e; + +typedef struct { + int device_id; + rms_requests_resource_state_e requested_state; +} rms_device_s; + +typedef struct { + int resources_num; + rms_device_s devices[RMS_MAX_DEVICE]; +} rms_requests_device_s; + +typedef struct { + int device_id; + const char *device_path; +} rms_return_device_info_s; + +typedef struct { + int result; + int error_type; + int resources_num; + int *device_ids; + rms_return_device_info_s *devices; +} rms_return_device_s; + +typedef struct { + int main; + int sub; +} rms_priority_s; + +typedef struct { + int consumer_id; + long process_id; + rms_priority_s priority; + int app_pid; + char app_id[RMS_APPID_LENGTH]; +} rms_consumer_s; + +typedef struct { + rms_rsc_category_e category_id; + int device_id; + int virtual_id; +} rms_conflicted_resource_info_s; + +typedef struct { + int consumer_id; + long process_id; + int n_conflicted; //needs to be released + rms_conflicted_resource_info_s *conflicted_resources; + int resources_num; //The number of resources consumer is using +} rms_consumer_tobe_returned_s; + +typedef struct { + int ret_quantity; //num of consumer who needs to release resources + rms_consumer_tobe_returned_s *consumer_info; +} consumer_reclaim_s; + +typedef enum { + RMS_OK, // success + RMS_ERROR, // error + RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER, // other consumer who has low or same priority is using resource + RMS_OK_UHD_RESOURCE_CONFLICT, // UHD device is conflicted + RMS_ERROR_HIGH_PRIORITY_CONSUMER_IS_USING, // other consumer who has high priority is using resource +} rms_return_code_e; + +// request type from client +typedef enum { + RMS_REQUEST_DATA_TYPE_ALL = 0, + RMS_REQUEST_DATA_TYPE_COMMON = 1, + RMS_REQUEST_DATA_TYPE_REGISTER = (0x2 << 29) +} rms_request_data_type; + +// response type to client +typedef enum { + RMS_RESPONSE_DATA_TYPE_COMMON = 1, + RMS_RESPONSE_DATA_TYPE_REGISTER = (0x2 << 29) +} rms_response_data_type; + +typedef enum { + RMS_REQUEST_REGISTER, + RMS_REQUEST_UNREGISTER, + RMS_REQUEST_ALLOCATE_RESOURCE, + RMS_REQUEST_RELEASE_RESOURCES, + RMS_REQUEST_QUERY, + RMS_REQUEST_SET_PRIORITY, + RMS_REQUEST_SET_APPID, + RMS_REQUEST_MAX, +} rms_request_type_e; + +typedef enum { + RMS_RESPONSE_REGISTER, + RMS_RESPONSE_UNREGISTER, + RMS_RESPONSE_ALLOCATE_RESOURCE, + RMS_RESPONSE_RELEASE_RESOURCES, + RMS_RESPONSE_QUERY, + RMS_RESPONSE_SET_PRIORITY, + RMS_RESPONSE_SET_APPID, + RMS_RESPONSE_MAX, +} rms_response_type_e; + +typedef enum { + RMS_ERR_TYPE_TERMINATED_PROCESS = -1, + RMS_ERR_TYPE_NONE = 0, + RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS = 1, + RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS, + RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE, + RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST, + RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER, + RMS_ERR_TYPE_RESOURCE_EXHAUSTED, + RMS_ERR_TYPE_INVALID_REQUEST, + RMS_ERR_TYPE_NOT_PERMITTED +} rms_error_type_e; + +#define RMS_REQUEST_RESOURCE_MAX 10 + +typedef struct { + long data_type; + int type; + int handle; + int pid; + int request_num; + int resource[RMS_REQUEST_RESOURCE_MAX]; + int resource_option[RMS_REQUEST_RESOURCE_MAX]; + int state[RMS_REQUEST_RESOURCE_MAX]; + int main_priority; + int sub_priority; + int app_pid; + char app_id[RMS_APPID_LENGTH]; + int device_id[RMS_REQUEST_RESOURCE_MAX]; + int sub_type; + unsigned long time; +} rms_msg_request; + +typedef struct { + long data_type; + rms_response_type_e type; + int result; + int resource_num; + int resource[RMS_REQUEST_RESOURCE_MAX]; + rms_resource_internal_state_e resource_state[RMS_REQUEST_RESOURCE_MAX]; + int is_available; + int handle; + rms_error_type_e error_type; + int pid; +} rms_msg_response; + +typedef enum { + RMS_HANDLE_NOT_AVAILABLE = -1, + RMS_HANDLE_FREE = 0, + RMS_HANDLE_USE = 1 +} rms_handle_used; + +typedef struct { + int pid; + int is_used; + int handle; + int main_priority; + int sub_priority; + int app_pid; + char app_id[RMS_APPID_LENGTH]; + char process_name[RMS_NAME_BUF_SIZE]; +} rms_register_handle_s; + +/** + * @enum rm_emergency_error_e + * @brief these values are used to handle emergency + * + */ + +typedef enum { + RMS_EMERGENCY_UNKNOWN = -1, + RMS_EMERGENCY_CONSUMER_NOT_RESPONDING = 0 +} rms_emergency_error_e; + +typedef enum { + RMS_DEVICE_OPT_NONE = 0, + RMS_DEVICE_OPT_MAIN = (0x1 << 29), + RMS_DEVICE_OPT_SUB = (0x1 << 28), +} rms_device_option_e; + +typedef enum { + RMS_FORCE_TO_MAIN = (0x1 << 27), + RMS_FORCE_TO_SUB = (0x1 << 26) +} rms_device_request_e; + +typedef enum { + RMS_MIXING_MODE_DEFAULT = RI_MIXING_MODE_DEFAULT, + RMS_MIXING_MODE_MULTIVIEW = RI_MIXING_MODE_MULTIVIEW, + RMS_MIXING_MODE_INTERACTION_SOUND = RI_MIXING_MODE_INTERACTION_SOUND +} rms_mixing_mode_e; + +typedef enum { + RMS_VIDEO_DEC_OPT_AI = (0x1 << 25) +} rms_video_dec_option_e; + +typedef enum { + RMS_MIXING_OPT_DEFAULT = 0, + RMS_MIXING_OPT_MULTIVIEW = RMS_MIXING_OPT_DEFAULT, + RMS_MIXING_OPT_INTERACTION_SOUND = (0x1 << 24) +} rms_mixing_option_e; + +typedef struct { + int cid; + rms_requests_resource_state_e state; + int option; //main, sub + int device_id; + rms_priority_s priority; + char app_id[RMS_APPID_LENGTH]; +} rms_allocate_request_s; + +typedef struct { + rms_return_code_e result; + rms_error_type_e reason; +} rms_allocate_result_s; + +typedef enum { + RMS_QUERY_NONE, + RMS_QUERY_ALLOCATION, + RMS_QUERY_TERMINATE, + RMS_QUERY_ACTIVE_DECS +} query_type_e; + +typedef enum { + RMS_RSC_COLLECTION_MAIN = 0, + RMS_RSC_COLLECTION_SUB, + RMS_RSC_COLLECTION_ACTIVE_VIDEO_DECODER +} _rsc_collection_e; + +typedef enum { + RMS_AUDIO_OUT_NONE = 0, + RMS_AUDIO_OUT_MAIN = 0x1, + RMS_AUDIO_OUT_SUB = 0x2, +} rms_audio_out_e; + +typedef enum { + RMS_CATEGORY_CLASS_NORMAL = 0, + RMS_CATEGORY_CLASS_N_DECODING = 100 +} rms_category_class_e; + +enum class ResourceType { + VIDEO_SCALER +}; + +#define RM_DBUS_BUS_NAME "rscmgr.resource" +#define RM_DBUS_INTERFACE_NAME "rscmgr.resource" +#define RM_DBUS_OBJ_PATH "/rscmgr/resource" + +#endif //__RMS_TYPE_H__ diff --git a/packaging/rscmgr-service.service b/packaging/rscmgr-service.service new file mode 100644 index 0000000..6e89c2d --- /dev/null +++ b/packaging/rscmgr-service.service @@ -0,0 +1,12 @@ +[Unit] +Description=service for resource manager +DefaultDependencies=no + +[Service] +Type=simple +Environment=LD_USE_LOAD_BIAS=1 +ExecStartPre=/usr/bin/gen_rm_msgq +ExecStart=/usr/bin/rscmgr-service +Restart=always +MemoryMax=10M +RestartSec=0 diff --git a/packaging/rscmgr-service.spec b/packaging/rscmgr-service.spec new file mode 100644 index 0000000..d98cdeb --- /dev/null +++ b/packaging/rscmgr-service.spec @@ -0,0 +1,79 @@ +Name: rscmgr-service +Summary: Daemon for resource manager +Version: 0.1 +Release: 1 +Group: Multimedia/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1: rscmgr-service.service +BuildRequires: cmake >= 2.8.12 +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(resource-information) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(aul) +BuildRequires: python +BuildRequires: python-xml +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(syspopup) +BuildRequires: pkgconfig(syspopup-caller) +BuildRequires: pkgconfig(wayland-client) + +%description +This package provides service for vconf key usage + +%package devel +Summary: The development package for daemon +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +The development package for vconf daemon + +%prep +%setup -q + +%build +export CFLAGS="$CFLAGS %{?_vd_cflags}" +export CXXFLAGS="$CXXFLAGS %{?__vd_cxxflags}" +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +cmake . \ + -DPACKAGE_NAME=%{name} \ + -DINCLUDEDIR=%{_includedir} \ + -DVERSION=%{version} \ + -DBINDIR=%{TZ_SYS_BIN} \ + -DMAJORVERSION=%{MAJORVER} \ + -DLIBDIR=%{_libdir} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install +mkdir -p %{buildroot}%{_unitdir}/basic.target.wants +mkdir -p %{buildroot}%{_sbindir} +install -m 0644 %SOURCE1 %{buildroot}%{_unitdir}/rscmgr-service.service +%install_service basic.target.wants rscmgr-service.service +ln -sf ../rscmgr-service.service %{buildroot}%{_unitdir}/basic.target.wants/ + +%clean +rm -rf %{buildroot} + +%post + +%{TZ_SYS_BIN}/chsmack -e "System::Run" %{TZ_SYS_BIN}/gen_rm_msgq + +%files +%manifest rscmgr-service.manifest +%license LICENSE.APLv2 +%defattr(-,root,root,-) +%{TZ_SYS_BIN}/rscmgr-service +%{TZ_SYS_BIN}/gen_rm_msgq +%{_unitdir}/rscmgr-service.service +%{_unitdir}/basic.target.wants/rscmgr-service.service + +%files devel +%defattr(-,root,root,-) diff --git a/rscmgr-service.manifest b/rscmgr-service.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/rscmgr-service.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/src/CAsyncQueue.cpp b/src/CAsyncQueue.cpp new file mode 100644 index 0000000..537d878 --- /dev/null +++ b/src/CAsyncQueue.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CAsyncQueue::CAsyncQueue(void) +{ + queue = g_async_queue_new(); +} + +CAsyncQueue::CAsyncQueue(destoryNotify destory_cb) +{ + queue = g_async_queue_new_full(destory_cb); +} + +CAsyncQueue::~CAsyncQueue(void) +{ + g_async_queue_unref(queue); +} + +void CAsyncQueue::push(void *data) +{ + g_async_queue_push(queue, data); +} + +void CAsyncQueue::push(CAsyncQueue *src_queue) +{ + if (src_queue->length() <= 0) + return; + + SERVER_INFO("push given queue (%d)", src_queue->length()); + + g_async_queue_lock(queue); + + while (src_queue->length() > 0) { + g_async_queue_push_unlocked(queue, src_queue->pop()); + } + + g_async_queue_unlock(queue); +} + +void CAsyncQueue::push_front(void *data) +{ + g_async_queue_push_front(queue, data); +} + +void CAsyncQueue::push_front(CAsyncQueue *src_queue) +{ + if (src_queue->length() <= 0) + return; + + SERVER_INFO("push_front given queue (%d)", src_queue->length()); + + g_async_queue_lock(queue); + + while (src_queue->length() > 0) { + g_async_queue_push_front_unlocked(queue, src_queue->pop()); + } + + g_async_queue_unlock(queue); +} + +void *CAsyncQueue::pop(void) +{ + return g_async_queue_pop(queue); +} + +void *CAsyncQueue::pop(unsigned int timeout_ms) +{ + guint64 timeout_us = (guint64)((guint64) timeout_ms * 1000); + + return g_async_queue_timeout_pop(queue, timeout_us); +} + +int CAsyncQueue::length(void) +{ + return g_async_queue_length(queue); +} + diff --git a/src/CCallback.cpp b/src/CCallback.cpp new file mode 100644 index 0000000..214943c --- /dev/null +++ b/src/CCallback.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#define CB_TIMEOUT_3_SEC_IN_MS 3000 +#define CB_TIMEOUT_10_SEC_IN_MS 10000 + +#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) + +unsigned int CCallback::GetTimeout(void) +{ + return (RMS_IS_DEBUG_IMAGE) ? CB_TIMEOUT_10_SEC_IN_MS : CB_TIMEOUT_3_SEC_IN_MS; +} + +void CCallback::InitCallback(void) +{ + const char *cb_path = "/run/rsc_mgr"; + mode_t dir_mode = 0666 | 0111; + + if (mkdir(cb_path, dir_mode) !=0) { + SERVER_ERR("failed to create cb directory (%d)", errno); + return; + } + + chmod(cb_path, dir_mode); +} + +int CCallback::SendCallbackMessage(int cid, int pid, void *callback_data, int size, int *err) +{ + int fd = -1; + int ret = 0; + + char callback_path[256] = {0,}; + + snprintf(callback_path, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid); + + if ((fd = open(callback_path, O_WRONLY|O_NONBLOCK)) < 0) { + SERVER_ERR("open error (%s), errno(%d)\n", callback_path, errno); + *err = errno; + return RMS_ERROR; + } + + if (is_symlink_file(callback_path)) { + SERVER_ERR("%s is symbolic link file", callback_path); + *err = EPERM; + close(fd); + return RMS_ERROR; + } + + ret = write(fd, callback_data, size); + + if (ret <= 0) { + SERVER_ERR("failed to write callback.(%s) ret(%d), errno(%d)\n", callback_path, ret, errno); + *err = errno; + close(fd); + return RMS_ERROR; + } + + SERVER_DBG("succeeded to write callback.(%s)", callback_path); + + close(fd); + + return RMS_OK; +} + +int CCallback::RemoveFIFOServerToClient(int pid, int cid) +{ + struct stat stat_info; + char cb_path_s2c[256] = {0, }; + + snprintf(cb_path_s2c, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid); + + if (stat(cb_path_s2c, &stat_info) != 0) { + SERVER_INFO("%s not exists", cb_path_s2c); + return RMS_OK; + } + + if (remove(cb_path_s2c) != 0) { + SERVER_ERR("failed to remove cb for S2C(%s)-(%d)", cb_path_s2c, errno); + return RMS_ERROR; + } + + SERVER_DBG("Removed cb for S2C(%s)", cb_path_s2c); + return RMS_OK; +} + +int CCallback::ConvertCallbackType(int rm_return_type) +{ + switch (rm_return_type) { + case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + return RMS_CALLBACK_TYPE_RESOURCE_CONFLICT; + case RMS_OK_UHD_RESOURCE_CONFLICT: + return RMS_CALLBACK_TYPE_RESOURCE_CONFLICT_UD; + default: + break; + } + + SERVER_ERR("return RMS_CALLBACK_TYPE_UNKNOWN(%d)", RMS_CALLBACK_TYPE_UNKNOWN); + + return RMS_CALLBACK_TYPE_UNKNOWN; +} diff --git a/src/CDbusHandler.cpp b/src/CDbusHandler.cpp new file mode 100644 index 0000000..d04f6f0 --- /dev/null +++ b/src/CDbusHandler.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +const GDBusInterfaceVTable CDbusHandler::m_vtable = { CDbusHandler::OnMethodCall, NULL, NULL, {0} }; + +const std::string CDbusHandler::m_methods = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + +CDbusHandler::CDbusHandler(CAsyncQueue *queue) +{ + assert(queue); + m_async_queue = queue; + m_reg_id = 0; + + if (!MakeDbusConnection()) + return; + + RegisterObjects(); +} + +bool CDbusHandler::MakeDbusConnection(void) +{ + m_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); + + if (!m_conn) { + SERVER_ERR("failed to make dbus connection"); + return false; + } + + SERVER_INFO("making dbus connection success"); + return true; +} + +void CDbusHandler::OnMethodCall(GDBusConnection *conn, const gchar *sender, const gchar *obj_path, const gchar *ifname, const gchar *method_name, GVariant *params, GDBusMethodInvocation *invoc, gpointer data) +{ + CDbusHandler *handler = static_cast(data); + CAsyncQueue *queue = handler->m_async_queue; + CMessage *msg = new CMessage(invoc); + + SERVER_INFO("push msg(%s)", method_name); + + queue->push(msg); +} + +void CDbusHandler::GenerateReadyEvent(void) +{ + SERVER_INFO("We will notify clients when the server is ready by generating a ready event"); +} + +void CDbusHandler::OnBusAcquired(GDBusConnection *conn, const gchar *bus_name, gpointer data) +{ + trace_begin("[RSC_MGR] OnBusAcquired"); + trace_end(); + SERVER_INFO("bus acquired (%s)", bus_name); + + CDbusHandler *handler = static_cast(data); + handler->GenerateReadyEvent(); +} + +void CDbusHandler::OnNameLost(GDBusConnection *conn, const gchar *bus_name, gpointer data) +{ + SERVER_ERR("name lost (%s)", bus_name); +} + +void CDbusHandler::RegisterObjects(void) +{ + assert(m_conn); + GError *err = NULL; + + GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(m_methods.c_str(), &err); + + if (!node_info) { + SERVER_ERR("failed to get node_info (%s)", err ? err->message : "unknown"); + g_clear_error(&err); + return; + } + + m_reg_id = g_dbus_connection_register_object(m_conn, RM_DBUS_OBJ_PATH, *(node_info->interfaces), &m_vtable, this, NULL, &err); + + if (m_reg_id == 0) { + SERVER_ERR("failed to register objects (%s)", err ? err->message : "unknown"); + g_clear_error(&err); + return; + } + + m_own_id = g_bus_own_name_on_connection(m_conn, RM_DBUS_BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, CDbusHandler::OnBusAcquired, CDbusHandler::OnNameLost, this, NULL); + + if (m_own_id == 0) { + SERVER_ERR("failed to own dbus name (%s)", RM_DBUS_BUS_NAME); + return; + } + + SERVER_INFO("registering dbus objects success"); +} diff --git a/src/CHandle.cpp b/src/CHandle.cpp new file mode 100644 index 0000000..3d53c3d --- /dev/null +++ b/src/CHandle.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +CHandle::CHandle(int in_handle, int in_is_used, int in_pid) +{ + handle = in_handle; + is_used = in_is_used; + pid = in_pid; + rms_get_cmd_name(pid,process_name,RMS_NAME_BUF_SIZE); +} diff --git a/src/CHandleManager.cpp b/src/CHandleManager.cpp new file mode 100644 index 0000000..6be09f2 --- /dev/null +++ b/src/CHandleManager.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +static const int M_MIN_HANDLE = 101; +static const int M_MAX_HANDLE = 200; + +CHandleManager::CHandleManager(CResourceManager *rsc_mgr) +{ + assert(rsc_mgr); + m_rsc_mgr = rsc_mgr; + m_next_handle = M_MIN_HANDLE; +} + +int CHandleManager::m_IsValidHandle(int handle) +{ + return ((handle >= M_MIN_HANDLE) && (handle <= M_MAX_HANDLE)) ? 1 : 0; +} + +int CHandleManager::m_ReclaimHandle(void) +{ + for (int i = M_MIN_HANDLE; i < M_MAX_HANDLE; i++) { + CHandle *handle_info = findHandle(i); + + if (!handle_info) + return i; + + if (!rm_is_valid_pid(handle_info->pid)) { + SERVER_INFO("reclaim pid(%d)/handle(%d)", handle_info->pid, handle_info->handle); + + // release resources allocated to terminated process + m_rsc_mgr->UnregisterConsumer(handle_info->handle); + m_RemoveHandle(handle_info->handle, handle_info->pid); + return i; + } + } + + return RMS_HANDLE_NOT_AVAILABLE; +} + +void CHandleManager::m_PrintHandleList(void) +{ + for (int i = M_MIN_HANDLE; i < M_MAX_HANDLE; i++) { + std::map::iterator it = m_handles.find(i); + + if (it == m_handles.end()) + return ; + + CHandle *handle_info = (*it).second; + m_PrintHandleInfo(handle_info->handle, handle_info->pid); + } +} + +int CHandleManager::m_AddNewHandle(int handle, int pid, int main_priority, int sub_priority, int app_pid, char *app_id) +{ + CHandle *handle_info = new(std::nothrow) CHandle(handle, RMS_HANDLE_USE, pid); + if (!handle_info) { + SERVER_ERR("cannot create handle class"); + return RMS_ERROR; + } + + handle_info->main_priority = main_priority; + handle_info->sub_priority = sub_priority; + handle_info->app_pid = app_pid; + handle_info->app_id = strndup(app_id, strlen(app_id)); + + m_handles.insert(std::pair(handle, handle_info)); + SERVER_DBG("handle(%d) pid(%d) inserted", handle, pid); + + return RMS_OK; +} +int CHandleManager::m_RemoveHandle(int handle, int pid) +{ + CHandle *handle_info = findHandle(handle); + + if (!handle_info) { + SERVER_ERR("can't find handle (%d) in list. no need to remove", handle); + return RMS_OK; + } + + if (handle_info->pid != pid) { + SERVER_ERR("cannot remove handle (%d) - owner(%d)/requester(%d)", handle, handle_info->pid, pid); + return RMS_ERROR; + } + + if (handle_info->app_id) { + free(handle_info->app_id); + handle_info->app_id = NULL; + } + + for (int i = 0; i < RMS_NAME_BUF_SIZE; i++) { + handle_info->process_name[i] = 0; + } + + delete handle_info; + m_handles.erase(handle); + + CCallback::RemoveFIFOServerToClient(pid, handle); + + return RMS_OK; +} +int CHandleManager::GetNewHandle(int pid, int main_priority, int sub_priority, int app_pid, char *app_id) +{ + int handle = -1; + + if (m_next_handle >= (M_MAX_HANDLE - 1)) + m_next_handle = M_MIN_HANDLE; + + std::map::iterator it = m_handles.find(m_next_handle); + + handle = (it == m_handles.end()) ? m_next_handle:m_ReclaimHandle(); + + if (handle == RMS_HANDLE_NOT_AVAILABLE) { + SERVER_ERR("ERROR! can't assign new handle (FULL)"); + m_PrintHandleList(); + return RMS_HANDLE_NOT_AVAILABLE; + } + + m_AddNewHandle(handle, pid, main_priority, sub_priority, app_pid, app_id); + ++m_next_handle; + + return handle; +} + +int CHandleManager::RemoveHandle(int handle, int pid) +{ + return m_RemoveHandle(handle, pid); +} + +int CHandleManager::SetPriority(int handle, int main_priority, int sub_priority) +{ + CHandle *handle_info = findHandle(handle); + + if (!handle_info) { + SERVER_ERR("can't find handle (%d)", handle); + return RMS_ERROR; + } + + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle); + + if (!consumer) { + SERVER_ERR("handle[%d] not registered consumer", handle); + return RMS_ERROR; + } + + handle_info->main_priority = main_priority; + handle_info->sub_priority = sub_priority; + + rms_priority_s priority; + priority.main = main_priority; + priority.sub = sub_priority; + + consumer->SetPriority(priority); + + return RMS_OK; +} + +CHandle *CHandleManager::findHandle(int id) +{ + auto it = m_handles.find(id); + + return (it == m_handles.end()) ? NULL:it->second; +} + +int CHandleManager::GetPriority(int handle, int *main_priority, int *sub_priority) +{ + CHandle *handle_info = findHandle(handle); + + if (!handle_info) { + SERVER_ERR("can't find handle (%d)", handle); + return RMS_ERROR; + } + + *main_priority = handle_info->main_priority; + *sub_priority = handle_info->sub_priority; + + return RMS_OK; +} + +int CHandleManager::SetAppID(int handle, char *app_id) +{ + CHandle *handle_info = findHandle(handle); + + if (!handle_info) { + SERVER_ERR("can't find handle (%d)", handle); + return RMS_ERROR; + } + + if (handle_info->app_id) { + free(handle_info->app_id); + handle_info->app_id = NULL; + } + + handle_info->app_id = strndup(app_id, strlen(app_id)); + + return RMS_OK; +} + +char *CHandleManager::GetAppID(int handle) +{ + CHandle *handle_info = findHandle(handle); + + if (!handle_info) { + SERVER_ERR("can't find handle (%d)", handle); + return NULL; + } + + return strndup(handle_info->app_id, strlen(handle_info->app_id)); +} + +int CHandleManager::m_PrintHandleInfo(int handle, int pid) +{ + char name[RMS_NAME_BUF_SIZE] = {0,}; + rms_get_cmd_name(pid, name, sizeof(name)); + + rms_log_reset(); + rms_log_add("handle(%d) pid(%d) name(%s)", handle, pid, name); + + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle); + + if (!consumer) { + rms_log_add(": no consumer info"); + + RMS_LOGE_FLUSH(); + return RMS_OK; + } + + rms_log_add(": using %d resource(s)", consumer->GetResourceNum()); + + RMS_LOGE_FLUSH(); + return RMS_OK; +} + +void CHandleManager::ReclaimAllInvalidCustomer(int request_pid) +{ + for (std::map::iterator it = m_handles.begin(); it != m_handles.end(); it++) { + CHandle *handle_info = (*it).second; + int cid = handle_info->handle; + int pid = handle_info->pid; + + if ((pid != request_pid) &&(!rm_is_valid_pid(pid))) { + SERVER_ERR("Reclaim handle(%d)/pid(%d)", cid, pid); + m_rsc_mgr->ReleaseResourcesOfPid(pid); + RemoveHandle(cid, pid); + CCallback::RemoveFIFOServerToClient(pid, cid); + } + } +} diff --git a/src/CMessage.cpp b/src/CMessage.cpp new file mode 100644 index 0000000..68c1916 --- /dev/null +++ b/src/CMessage.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +CMessage::CMessage(std::string name) +{ + m_sender = MSG_SENDER_INTERNAL; + m_msgq_req = NULL; + m_name = name; +} + +CMessage::CMessage(rms_msg_request *req) +{ + assert(req); + + m_msgq_req = (rms_msg_request*) calloc(1, sizeof(rms_msg_request)); + assert(m_msgq_req); + memcpy(m_msgq_req, req, sizeof(rms_msg_request)); + + m_sender = MSG_SENDER_MSGQ; +} + +CMessage::CMessage(GDBusMethodInvocation *invoc) +{ + assert(invoc); + + m_invoc = invoc; + m_sender = MSG_SENDER_DBUS; + m_msgq_req = NULL; +} + +CMessage::~CMessage(void) +{ + if (m_msgq_req) + free(m_msgq_req); +} + +int CMessage::GetReqType(void) +{ + int req_type = RMS_REQUEST_MAX; + assert(m_msgq_req); + + switch (m_sender) { + case MSG_SENDER_MSGQ: + req_type = m_msgq_req->type; + break; + case MSG_SENDER_DBUS: + case MSG_SENDER_INTERNAL: + break; + default: + SERVER_ERR("undefined sender(%d)", m_sender); + break; + } + + return req_type; +} + +bool CMessage::IsMsgForScalerDbus(void) +{ + std::string method_name = g_dbus_method_invocation_get_method_name(m_invoc); + + if (!method_name.compare("FindDeviceId")) + return true; + if (!method_name.compare("SwapResources")) + return true; + if (!method_name.compare("GetScalerState")) + return true; + if (!method_name.compare("GetScalerHWID")) + return true; + if (!method_name.compare("RestoreResources")) + return true; + + return false; +} + +bool CMessage::IsMsgForScalerMsgQ(void) +{ + bool result = false; + switch (m_msgq_req->type) { + case RMS_REQUEST_ALLOCATE_RESOURCE: + for (int i = 0; i < m_msgq_req->request_num; i++) { + if (ri_is_video_scaler_category(m_msgq_req->resource[i])) + { + result = true; + break; + } + } + break; + case RMS_REQUEST_RELEASE_RESOURCES: + int category_type; + for (int i = 0; i < m_msgq_req->request_num; i++) { + ri_get_category_type_by_device_id(m_msgq_req->resource[i], &category_type); + if (ri_is_video_scaler_category(category_type)) + { + result = true; + break; + } + } + break; + case RMS_REQUEST_UNREGISTER: + case RMS_REQUEST_REGISTER: + case RMS_REQUEST_QUERY: + case RMS_REQUEST_SET_PRIORITY: + case RMS_REQUEST_SET_APPID: + result = false; + break; + default: + SERVER_ERR("undefined req type(%d)", m_msgq_req->type); + break; + } + + return result; +} + +void CMessage::PrintInfo(void) +{ + switch (m_sender) { + case MSG_SENDER_MSGQ: + PrintMsgQ(); + break; + case MSG_SENDER_DBUS: + PrintDbus(); + break; + case MSG_SENDER_INTERNAL: + PrintInternal(); + break; + default: + SERVER_ERR("undefined sender(%d)", m_sender); + break; + } +} + +void CMessage::PrintDbus(void) +{ + SERVER_ERR("Sender:Dbus/%s", g_dbus_method_invocation_get_method_name(m_invoc)); +} + +void CMessage::PrintInternal(void) +{ + SERVER_ERR("Sender:Internal/%s", m_name.c_str()); +} + +void CMessage::PrintMsgQ(void) +{ + SERVER_ERR("Sender:MsgQ/type(%d)/cid(%d)/num(%d)", m_msgq_req->type, m_msgq_req->handle, m_msgq_req->request_num); +} + +bool CMessage::IsUnlockMsg(void) +{ + if (m_sender != MSG_SENDER_INTERNAL) + return false; + + return (!m_name.compare("NotifyUnlock")); +} + +bool CMessage::IsMsgForScaler(void) +{ + bool result = false; + + switch (m_sender) { + case MSG_SENDER_MSGQ: + result = IsMsgForScalerMsgQ(); + break; + case MSG_SENDER_DBUS: + result = IsMsgForScalerDbus(); + break; + case MSG_SENDER_INTERNAL: + result = false; + break; + default: + SERVER_ERR("undefined sender(%d)", m_sender); + break; + } + + return result; +} + +bool CMessage::IsMsgFor(ResourceType rsc_type) +{ + bool result = false; + + switch (rsc_type) { + case ResourceType::VIDEO_SCALER: + result = IsMsgForScaler(); + break; + default: + break; + } + + return result; +} diff --git a/src/CMessageHandler.cpp b/src/CMessageHandler.cpp new file mode 100644 index 0000000..729d79c --- /dev/null +++ b/src/CMessageHandler.cpp @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RMS_HANLDE_COMMON 100 // common handle for the request rm_register() is not required +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +struct rms_msg_handler { + const char *msg_name; + CMessageHandler::MsgHandler handler; +}; + +CMessageHandler::CMessageHandler(CResourceManager *rsc_mgr) +{ + assert(rsc_mgr); + + msgq_rx = new CMessageQueue(MSG_QUEUE_RX); + msgq_tx = new CMessageQueue(MSG_QUEUE_TX); + async_queue = new CAsyncQueue(); + async_pending_queue = new CAsyncQueue(); + + m_rsc_mgr = rsc_mgr; + m_query_h = new CQueryHandler(rsc_mgr); + m_handle_mgr = new CHandleManager(rsc_mgr); + m_lock_ctr = CLockController::GetInstance(); + m_lock_ctr->SetMsgQ(async_queue); + + CCallback::InitCallback(); + InitDbusHandlers(); + InitInternalMsgHandlers(); +} + +CMessageHandler::~CMessageHandler(void) +{ + +} + +void CMessageHandler::InitDbusHandlers(void) +{ + struct rms_msg_handler dbus_handlers[] = { + {"RegisterResource", &CMessageHandler::RegisterResource}, + {"GetResourceState", &CMessageHandler::GetResourceState}, + {"GetResourceList", &CMessageHandler::GetResourceList}, + {"GetRscCollectionState", &CMessageHandler::GetResourceCollectionState}, + {"FindDeviceId", &CMessageHandler::FindDeviceId}, + {"SwapResources", &CMessageHandler::SwapResources}, + {"GetScalerState", &CMessageHandler::GetScalerState}, + {"GetAppId", &CMessageHandler::GetAppId}, + {"GetActiveAudioOut", &CMessageHandler::GetActiveAudioOut}, + {"GetScalerHWID", &CMessageHandler::GetScalerHWID}, + {"RestoreResources", &CMessageHandler::RestoreResources}, + {"NotifyResourcePolicy", &CMessageHandler::NotifyResourcePolicy}, + {"NotifyAppZoneInfo", &CMessageHandler::NotifyAppZoneInfo} + // Please add a new dbus message handler here + }; + + std::string msg_name; + for (unsigned int i = 0; i < ARRAY_SIZE(dbus_handlers); i++) { + msg_name.assign(dbus_handlers[i].msg_name); + m_dbus_handlers.insert(std::pair(msg_name, dbus_handlers[i].handler)); + } +} + +void CMessageHandler::InitInternalMsgHandlers(void) +{ + struct rms_msg_handler internal_msg_handlers[] = { + {"NotifyWatchdog", &CMessageHandler::NotifyWatchdog} + // Please add a new internal message handler here + }; + + std::string msg_name; + for (unsigned int i = 0; i < ARRAY_SIZE(internal_msg_handlers); i++) { + msg_name.assign(internal_msg_handlers[i].msg_name); + m_internal_msg_handlers.insert(std::pair(msg_name, internal_msg_handlers[i].handler)); + } +} + +void CMessageHandler::m_ConstructRequestedDevice(rms_msg_request *request, rms_requests_device_s *requested_resource) +{ + requested_resource->resources_num = request->request_num; + + for (int i = 0; i < requested_resource->resources_num; i++) { + requested_resource->devices[i].device_id = request->resource[i]; + requested_resource->devices[i].requested_state = (rms_requests_resource_state_e) request->state[i]; + } +} + +int CMessageHandler::Run(void) +{ + if (g_thread_new("rms_msgq_thread", msgQThread, this) == NULL) { + SERVER_ERR("failed to create rms_msgq thread"); + assert(0); + return RMS_ERROR; + } + + if (g_thread_new("rms_msg_thread", msgThread, this) == NULL) { + SERVER_ERR("event loop thread create failed\n"); + assert(0); + return RMS_ERROR; + } + + m_dbus_h = new CDbusHandler(async_queue); + return RMS_OK; +} + +gpointer CMessageHandler::msgQThread(gpointer data) +{ + assert(data); + + CMessageHandler *msg_handler = (CMessageHandler*) data; + CAsyncQueue *asyncq = msg_handler->async_queue; + CMessageQueue *msgq = msg_handler->msgq_rx; + rms_msg_request req; + + while (1) { + memset(&req, 0, sizeof(rms_msg_request)); + + if (msgq->receive(&req, RMS_REQUEST_DATA_TYPE_ALL) != RMS_OK) + continue; + + SERVER_DBG("push req type(%d)-pid(%d)-cid(%d)-len(%d)", req.type, req.pid, req.handle, asyncq->length()); + + CMessage *msg = new CMessage(&req); + asyncq->push(msg); + } + + return NULL; +} + +gpointer CMessageHandler::msgThread(gpointer data) +{ + assert(data); + SERVER_INFO("prepare to handle messages"); + + CMessageHandler *msg_handler = (CMessageHandler*) data; + + while (1) { + msg_handler->ProcessMessage(); + usleep(30000); + } + + return NULL; +} + +bool CMessageHandler::IsRegisteredHandle(int handle) +{ + return (CConsumerContainer::getInstance()->findConsumer(handle) != NULL); +} + +void CMessageHandler::SetRequesterInfo(rms_msg_request *request) +{ + char *app_id = m_handle_mgr->GetAppID(request->handle); + m_handle_mgr->GetPriority(request->handle, &request->main_priority, &request->sub_priority); + + snprintf(request->app_id, RMS_APPID_LENGTH, "%s", (app_id) ? app_id : ""); + + SERVER_INFO("handle(%d)-app_id(%s)", request->handle, request->app_id); + + if (app_id) + free(app_id); +} + + +void CMessageHandler::m_RegisterConsumer(rms_msg_request *request, rms_msg_response *response) +{ + char cmd[RMS_NAME_BUF_SIZE] = {0,}; + + int handle = m_handle_mgr->GetNewHandle(request->pid, request->main_priority, request->sub_priority, request->app_pid, request->app_id); + + response->result = (handle == RMS_HANDLE_NOT_AVAILABLE) ? RMS_ERROR : RMS_OK; + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_REGISTER, handle, request->pid); + + if (response->result == RMS_ERROR) + return; + + if (m_rsc_mgr->RegisterConsumer(handle, request->pid, request->app_id, request->main_priority, request->sub_priority) != RMS_OK) + SERVER_ERR("failed to add consumer to manager. handle[%d]", handle); + + rms_get_cmd_name(request->pid, cmd, sizeof(cmd)); + + SERVER_INFO("newly assigned handle(%d) - pid(%d)-(%s)", response->handle, request->pid, cmd); +} + +void CMessageHandler::m_UnregisterConsumer(rms_msg_request *request, rms_msg_response *response) +{ + SERVER_INFO("request for unregister handle(%d)", request->handle); + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_UNREGISTER, request->handle, request->pid); + + if (!IsRegisteredHandle(request->handle)) { + response->result = RMS_ERROR; + return; + } + + response->result = m_handle_mgr->RemoveHandle(request->handle, request->pid); + + if (response->result != RMS_OK) + return; + + m_rsc_mgr->UnregisterConsumer(request->handle); +} + +void CMessageHandler::m_FreeAllocatedDevice(rms_return_device_s *allocated_device) +{ + if (allocated_device->device_ids) { + free(allocated_device->device_ids); + allocated_device->device_ids = NULL; + } + + for (int i=0 ; i < allocated_device->resources_num; i++) { + if (allocated_device->devices[i].device_path) { + free((void*)allocated_device->devices[i].device_path); + allocated_device->devices[i].device_path = NULL; + } + } + + if (allocated_device->devices) { + free(allocated_device->devices); + allocated_device->devices = NULL; + } +} + +void CMessageHandler::m_Free(consumer_reclaim_s *consumer_info) +{ + if (!consumer_info) + return; + + if (!consumer_info->consumer_info) + return; + + for (int i = 0; i < consumer_info->ret_quantity; i++) { + if (consumer_info->consumer_info[i].conflicted_resources != NULL) + free(consumer_info->consumer_info[i].conflicted_resources); + } + + free(consumer_info->consumer_info); +} + +void CMessageHandler::m_AllocateResources(rms_msg_request *request, rms_msg_response *response) +{ + trace_begin("RSC ALLOCATE START"); + trace_end(); + + if (!IsRegisteredHandle(request->handle)) { + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_ALLOCATE_RESOURCE, request->handle, request->pid); + response->result = RMS_ERROR; + return; + } + + int result = RMS_OK; + bool need_response = true; + rms_return_device_s allocated_device; + memset(&allocated_device, 0, sizeof(rms_return_device_s)); + + m_handle_mgr->ReclaimAllInvalidCustomer(request->pid); + + SetRequesterInfo(request); + + result = m_rsc_mgr->AllocateResources(request, &allocated_device); + + bool needReclaimResources = (result == RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + + if (needReclaimResources) { + consumer_reclaim_s consumers_reclaim; + memset(&consumers_reclaim, 0, sizeof(consumers_reclaim)); + int zone_id = -1; + if (m_rsc_mgr->FindReclaimableConsumers(request, &consumers_reclaim, &zone_id) == RMS_OK) { + CResourceDB::getInstance()->AddReclaimResources(&consumers_reclaim); + if (ReclaimResources(result, request->handle, zone_id, &consumers_reclaim, &need_response) == RMS_OK) { + result = m_rsc_mgr->AllocateResources(request, &allocated_device); + } + CResourceDB::getInstance()->ClearReclaimResources(); + } + m_Free(&consumers_reclaim); + } + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_ALLOCATE_RESOURCE, request->handle, request->pid); + + response->result = result; + response->error_type = (result == RMS_OK) ? RMS_ERR_TYPE_NONE : (rms_error_type_e)allocated_device.error_type; + response->resource_num = allocated_device.resources_num; + + if (!need_response) + response->error_type = RMS_ERR_TYPE_TERMINATED_PROCESS; + + for (int i = 0; i < response->resource_num; i++) { + response->resource[i] = allocated_device.device_ids[i]; + } + + m_FreeAllocatedDevice(&allocated_device); + CCache::getInstance()->Drop(); + + trace_begin("RSC ALLOCATE END"); + trace_end(); +} + +void CMessageHandler::m_ReleaseResources(rms_msg_request *request, rms_msg_response *response) +{ + SERVER_DBG("request for deallocation"); + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_RELEASE_RESOURCES, request->handle, request->pid); + + if (!IsRegisteredHandle(request->handle)) { + response->result = RMS_ERROR; + return; + } + + rms_requests_device_s requested_resource; + memset(&requested_resource, 0, sizeof(rms_requests_device_s)); + + m_ConstructRequestedDevice(request, &requested_resource); + + response->result = m_rsc_mgr->ReleaseResources(request->handle, &requested_resource); +} + +void CMessageHandler::m_Query(rms_msg_request *request, rms_msg_response *response) +{ + int answer = 0; + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_QUERY, request->handle, request->pid); + + m_handle_mgr->ReclaimAllInvalidCustomer(request->handle); + + response->result = m_query_h->GetAnswer(request, &answer); + response->is_available = answer; + + SERVER_INFO("query on (%d), result(%d)", request->sub_type, answer); +} + +void CMessageHandler::m_SetConsumerPriority(rms_msg_request *request, rms_msg_response *response) +{ + SERVER_INFO("request for priority setting. priority(%d)", request->main_priority); + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_SET_PRIORITY, request->handle, request->pid); + + response->result = m_handle_mgr->SetPriority(request->handle, request->main_priority, request->sub_priority); +} + +void CMessageHandler::m_SetAppID(rms_msg_request *request, rms_msg_response *response) +{ + SERVER_INFO("request for appid setting. appid(%s)", request->app_id); + + m_ConstructResponse(response, request->data_type, RMS_RESPONSE_SET_APPID, request->handle, request->pid); + + int ret = m_handle_mgr->SetAppID(request->handle, request->app_id); + + if (ret != RMS_OK) { + SERVER_ERR("cannot update appid. handle(%d). ret(%d)", request->handle, ret); + + response->result = RMS_ERROR; + return; + } + + response->result = m_rsc_mgr->SetAppId(request->handle, request->app_id); +} + +CMessageHandler::msg_handler CMessageHandler::handlers[RMS_REQUEST_MAX] = { + &CMessageHandler::m_RegisterConsumer, + &CMessageHandler::m_UnregisterConsumer, + &CMessageHandler::m_AllocateResources, + &CMessageHandler::m_ReleaseResources, + &CMessageHandler::m_Query, + &CMessageHandler::m_SetConsumerPriority, + &CMessageHandler::m_SetAppID, +}; + +void CMessageHandler::ProcessMsgQMessage(CMessage *msg) +{ + if (!IsValidRequest(msg->GetReqType())) { + SERVER_ERR("invalid req type(%d)", msg->GetReqType()); + return; + } + + rms_msg_response resp; + memset(&resp, 0, sizeof(rms_msg_response)); + + rms_msg_request *req = msg->GetRequest(); + SERVER_INFO("req type(%d)-pid(%d)-cid(%d)-t(%lu)", req->type, req->pid, req->handle, req->time); + + (this->*handlers[req->type])(msg->GetRequest(), &resp); + + if (resp.error_type == RMS_ERR_TYPE_TERMINATED_PROCESS) { + SERVER_ERR("skip to send a response (%d)", req->pid); + return; + } + + if (msgq_tx->send(&resp) != RMS_OK) { + SERVER_ERR("failed to send response"); + } +} + +GVariant *CMessageHandler::RegisterResource(GVariant *params) +{ + char *dev_name; + char *dev_node; + int category; + int sharable_count; + + g_variant_get(params, "(&ssii)", &dev_name, &dev_node, &category, &sharable_count); + + SERVER_INFO("dev_name(%s)/dev_node(%s)/category(%d)/sharable(%d)", dev_name, dev_node, category, sharable_count); + return g_variant_new("(i)", RMS_OK); +} + +GVariant *CMessageHandler::GetResourceState(GVariant *params) +{ + int device_id; + int state; + + g_variant_get(params, "(i)", &device_id); + + state = m_rsc_mgr->GetResourceState(device_id); + + SERVER_INFO("state (%d:%d)", device_id, state); + + return g_variant_new("(i)", state); +} + +GVariant *CMessageHandler::FindDeviceId(GVariant *params) +{ + int virtual_id; + int real_id; + + g_variant_get(params, "(i)", &virtual_id); + + real_id = m_rsc_mgr->FindDeviceId(virtual_id); + + SERVER_INFO("real id (%d:%d)", virtual_id, real_id); + + return g_variant_new("(i)", real_id); +} + +GVariant *CMessageHandler::GetScalerHWID(GVariant *params) +{ + int zone_id; + int hw_id; + + g_variant_get(params, "(i)", &zone_id); + + hw_id = m_rsc_mgr->GetScalerHWId(zone_id); + + SERVER_INFO("hw id (%d:%d)", zone_id, hw_id); + + return g_variant_new("(i)", hw_id); +} + +GVariant *CMessageHandler::SwapResources(GVariant *params) +{ + int device_id_a; + int device_id_b; + int result = 0; + + g_variant_get(params, "(ii)", &device_id_a, &device_id_b); + + result = m_rsc_mgr->SwapResources(device_id_a, device_id_b); + + SERVER_INFO("swap result (%d:%d) > (%d)", device_id_a, device_id_b, result); + + return g_variant_new("(i)", result); +} + +GVariant *CMessageHandler::RestoreResources(GVariant *params) +{ + int category_id; + int result = 0; + + g_variant_get(params, "(i)", &category_id); + + result = m_rsc_mgr->RestoreResources(category_id); + + SERVER_INFO("restore result (%d) > (%d)", category_id, result); + + return g_variant_new("(i)", result); +} + +GVariant *CMessageHandler::NotifyResourcePolicy(GVariant *params) +{ + int policy; + int result = 0; + + g_variant_get(params, "(i)", &policy); + + m_rsc_mgr->ResetZoneIds(); + + SERVER_INFO("notify result (%d) > (%d)", policy, result); + return g_variant_new("(i)", result); +} + +GVariant *CMessageHandler::NotifyAppZoneInfo(GVariant *params) +{ + char *app_id; + int zone_id; + int result = 0; + + g_variant_get(params, "(&si)", &app_id, &zone_id); + + if (!app_id) { + result = -1; + SERVER_INFO("invalid param (%s:%d) - result(%d)", "null", zone_id, result); + return g_variant_new("(i)", result); + } + + m_rsc_mgr->UpdateZoneIds(app_id, zone_id); + + SERVER_INFO("notify result (%s:%d) > (%d)", app_id, zone_id, result); + return g_variant_new("(i)", result); +} + +GVariant *CMessageHandler::GetResourceList(GVariant *params) +{ + int category_id; + + g_variant_get(params, "(i)", &category_id); + + SERVER_DBG("category (%d)", category_id); + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(iissi))")); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iissi)")); + m_rsc_mgr->GetResourceList(category_id, &builder); + g_variant_builder_close(&builder); + + return g_variant_builder_end(&builder); +} + +GVariant *CMessageHandler::GetScalerState(GVariant *params) +{ + SERVER_INFO("GetScalerState"); + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(iiiiis))")); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iiiiis)")); + m_rsc_mgr->GetScalerState(&builder); + g_variant_builder_close(&builder); + + return g_variant_builder_end(&builder); +} + +GVariant *CMessageHandler::GetAppId(GVariant *params) +{ + int result = 0; + int handle; + g_variant_get(params, "(i)", &handle); + + SERVER_INFO("GetAppId(%d)", handle); + + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle); + if (!consumer) { + SERVER_ERR("consumer(%d) not found", handle); + result = -1; + return g_variant_new("(is)", result, ""); + } + + return g_variant_new("(is)", result, (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str()); +} + +GVariant *CMessageHandler::GetResourceCollectionState(GVariant *params) +{ + int collection; + + g_variant_get(params, "(i)", &collection); + + SERVER_INFO("collection (%d)", collection); + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(isiiis))")); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(isiiis)")); + m_rsc_mgr->GetResourceCollectionState(collection, &builder); + g_variant_builder_close(&builder); + + return g_variant_builder_end(&builder); +} + +GVariant *CMessageHandler::GetActiveAudioOut(GVariant *params) +{ + int cid; + int active_audio_out; + + g_variant_get(params, "(i)", &cid); + + active_audio_out = m_rsc_mgr->GetActiveAudioOut(cid); + SERVER_INFO("active_audio_out(%d:%d)", cid, active_audio_out); + + return g_variant_new("(i)", active_audio_out); +} + +void CMessageHandler::ProcessDbusMessage(CMessage *msg) +{ + GDBusMethodInvocation *invoc = msg->GetMethodInvocation(); + std::string method_name(g_dbus_method_invocation_get_method_name(invoc)); + + auto it = m_dbus_handlers.find(method_name); + if (it == m_dbus_handlers.end()) { + SERVER_ERR("handler is not found (%s)", method_name.c_str()); + return; + } + + GVariant *params = g_dbus_method_invocation_get_parameters(invoc); + GVariant *result = (this->*(it->second))(params); + + g_dbus_method_invocation_return_value(invoc, result); +} + +void CMessageHandler::ProcessInternalMessage(CMessage *msg) +{ + auto it = m_internal_msg_handlers.find(msg->GetName()); + if (it == m_internal_msg_handlers.end()) { + SERVER_ERR("handler is not found (%s)", msg->GetName().c_str()); + return; + } + + (this->*(it->second))(NULL); +} + +void CMessageHandler::EmptyPendingQueue(void) +{ + if (async_pending_queue->length() <= 0) + return; + + SERVER_WARN("empty pending queue(%d)", async_pending_queue->length()); + async_queue->push(async_pending_queue); +} + +void CMessageHandler::InsertPendingQueue(CMessage *msg) +{ + SERVER_WARN("msg locked"); + msg->PrintInfo(); + async_pending_queue->push(msg); +} + +int CMessageHandler::ProcessMessage(void) +{ + CMessage *msg = (CMessage*) async_queue->pop(); + assert(msg); + + if ((m_lock_ctr->GetLockCount() > 0) && m_lock_ctr->IsLocked(msg)) { + InsertPendingQueue(msg); + return 0; + } + + if (msg->IsUnlockMsg()) { + EmptyPendingQueue(); + delete msg; + return 0; + } + + switch (msg->GetSender()) { + case MSG_SENDER_MSGQ: + ProcessMsgQMessage(msg); + break; + case MSG_SENDER_DBUS: + ProcessDbusMessage(msg); + break; + case MSG_SENDER_INTERNAL: + ProcessInternalMessage(msg); + break; + default: + break; + } + + delete msg; + + return 0; +} + +bool CMessageHandler::IsAllResourcesReclaimed(rms_consumer_tobe_returned_s *consumer_info) +{ + for (int idx = 0; idx < consumer_info->n_conflicted; idx++) { + if (!m_rsc_mgr->IsReclaimed(consumer_info->conflicted_resources[idx].device_id, consumer_info->consumer_id)) { + SERVER_WARN("IsReclaimed is failed"); + return false; + } + } + + SERVER_WARN("all conflicted resources are freed"); + + return true; +} + +void CMessageHandler::ProcessMessage(CAsyncQueue *queue, CMessage *msg, int cid_requester, int cid_releaser) +{ + rms_msg_request *req = msg->GetRequest(); + rms_msg_response resp; + int handle; + char cmd[RMS_NAME_BUF_SIZE] = {0,}; + + switch (req->type) { + case RMS_REQUEST_RELEASE_RESOURCES: + + rms_requests_device_s requested_resource; + memset(&requested_resource, 0, sizeof(rms_requests_device_s)); + + m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_RELEASE_RESOURCES, req->handle, req->pid); + m_ConstructRequestedDevice(req, &requested_resource); + + if ((resp.result = m_rsc_mgr->ReleaseResources(req->handle, &requested_resource)) != RMS_OK) + SERVER_ERR("failed to release resources requested by (%d)", req->handle); + + SendResponse(&resp); + + break; + + case RMS_REQUEST_UNREGISTER: + + m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_UNREGISTER, req->handle, req->pid); + + SERVER_WARN("unregister requested by handle(%d)", req->handle); + + if (req->handle == cid_requester) { + SERVER_WARN("unregister request from requester(%d), send to internal queue", req->handle); + + PushMessage(queue, msg); + } else { + if ((resp.result = m_handle_mgr->RemoveHandle(req->handle, req->pid)) == RMS_OK) { + m_rsc_mgr->UnregisterConsumer(req->handle); + } + + SendResponse(&resp); + } + break; + + case RMS_REQUEST_REGISTER: + handle = m_handle_mgr->GetNewHandle(req->pid, req->main_priority, req->sub_priority, req->app_pid, req->app_id); + + resp.result = (handle == RMS_HANDLE_NOT_AVAILABLE) ? RMS_ERROR : RMS_OK; + m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_REGISTER, handle, req->pid); + + if (resp.result == RMS_ERROR) { + SendResponse(&resp); + break; + } + + if (m_rsc_mgr->RegisterConsumer(handle, req->pid, req->app_id, req->main_priority, req->sub_priority) != RMS_OK) + SERVER_ERR("failed to add consumer to manager. handle[%d]", handle); + + rms_get_cmd_name(req->pid, cmd, sizeof(cmd)); + + SERVER_INFO("newly assigned handle(%d) date type(%ld)- pid(%d)-(%s)", resp.handle, req->data_type, req->pid, cmd); + SendResponse(&resp); + break; + + default: + SERVER_ERR("unexpected request(%d) by handle(%d)/pid(%d)", req->type, req->handle, req->pid); + + if (req->handle == cid_releaser) { + m_ConstructResponse(&resp, req->data_type, (rms_response_type_e)req->type, req->handle, req->pid); + resp.result = RMS_ERROR; + + SendResponse(&resp); + } else { + PushMessage(queue, msg); + } + break; + } +} + +int CMessageHandler::ProcessCallbackMessage(rms_consumer_tobe_returned_s *consumer_info, int requester_cid) +{ + CMessage *msg = NULL; + int result = RMS_OK; + CAsyncQueue *queue = new CAsyncQueue(); + + unsigned int timeout_ms = CCallback::GetTimeout(); + + while (!IsAllResourcesReclaimed(consumer_info)) { + msg = (CMessage*) async_queue->pop(timeout_ms); + + if (!msg) { + SERVER_ERR("receive cb request timeout! CID[%d]/PID[%ld]", consumer_info->consumer_id, consumer_info->process_id); + result = RMS_ERROR; + goto out; + } + + if (msg->GetSender() == MSG_SENDER_DBUS) { + ProcessDbusMessage(msg); + } else if (msg->GetSender() == MSG_SENDER_MSGQ) { + SERVER_WARN("[MSG_SENDER_MSGQ] requester cid %d consumer id %d", requester_cid, consumer_info->consumer_id); + ProcessMessage(queue, msg, requester_cid, consumer_info->consumer_id); + } else { + ProcessInternalMessage(msg); + } + + delete msg; + } + +out: + async_queue->push_front(queue); + + delete queue; + + return result; +} + +int *CMessageHandler::m_SerializeCallbackData(const rms_consumer_tobe_returned_s *consumer_info, int reason, int *data_size) +{ + int num_conflicted_resources = consumer_info->n_conflicted; + + int *callback_data = (int*) calloc(num_conflicted_resources + 4, sizeof(int)); + assert(callback_data); + + callback_data[0] = CCallback::ConvertCallbackType(reason); + callback_data[1] = consumer_info->consumer_id; + callback_data[2] = consumer_info->process_id; + callback_data[3] = num_conflicted_resources; + + for (int res = 0; res < num_conflicted_resources; res++) { + callback_data[(res+4)] = consumer_info->conflicted_resources[res].virtual_id; + SERVER_DBG("- virtual_id:%d ", consumer_info->conflicted_resources[res].virtual_id); + } + + *data_size = (num_conflicted_resources + 4) * sizeof(int); + + return callback_data; +} + +bool CMessageHandler::IsValidProcess(int pid) +{ + return rm_is_valid_pid(pid); +} + +bool CMessageHandler::IsValidRequest(int req_type) +{ + return (req_type >= RMS_REQUEST_REGISTER && req_type < RMS_REQUEST_MAX); +} + +int CMessageHandler::ReleaseInvalidProcessResources(int pid, int handle) +{ + m_handle_mgr->RemoveHandle(handle, pid); + CCallback::RemoveFIFOServerToClient(pid, handle); + + return RMS_OK; +} + +void CMessageHandler::NotifyConflict(consumer_reclaim_s *conflict_info, int zone_id) +{ + if (!conflict_info) + return; + + int consumer_id = -1; + int device_id = -1; + int category_id = -1; + int app_zone_id = -1; + int n_consumer = conflict_info->ret_quantity; + CConsumer *consumer = NULL; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (!connection) { + SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + goto out; + } + + for (int i = 0; i < n_consumer; i++) { + consumer_id = conflict_info->consumer_info[i].consumer_id; + consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + for (int j = 0; j < conflict_info->consumer_info[i].n_conflicted; j++) { + device_id = conflict_info->consumer_info[i].conflicted_resources[j].device_id; + app_zone_id = m_rsc_mgr->GetZoneId(device_id); + category_id = conflict_info->consumer_info[i].conflicted_resources[j].category_id; + SERVER_INFO("send resource conflict (%d:%d:%d:%s:%d:%d)", + category_id, device_id, consumer_id, (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str(), app_zone_id, zone_id); + if (!g_dbus_connection_emit_signal(connection, + NULL, + RM_DBUS_OBJ_PATH, + RM_DBUS_INTERFACE_NAME, + "RscConflicted", + g_variant_new("(iiisii)", category_id, device_id, consumer_id, + (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str(), app_zone_id, zone_id), + &error)) { + SERVER_ERR("failed to send resource conflict (%d:%d:%d:%s)-%s", category_id, device_id, consumer_id, + (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str():consumer->GetAppID().c_str(), (error) ? error->message : "unknown"); + } + } + } +out: + if (error) + g_error_free(error); +} + +int CMessageHandler::ReclaimResources(int reason, int requester_cid, int requester_zone_id, consumer_reclaim_s *conflict_info, bool *need_response) +{ + int num_consumers = conflict_info->ret_quantity; + int data_size = 0; + int *callback_data = NULL; + char cmd[RMS_NAME_BUF_SIZE] = {0,}; + int err = 0; + int cid = 0; + int pid = 0; + + SERVER_WARN("start to reclaim - retirable consumers : (%d)", num_consumers); + + if (num_consumers > 0) + NotifyConflict(conflict_info, requester_zone_id); + + for (int i = 0; i < num_consumers; i++) { + pid = (int) conflict_info->consumer_info[i].process_id; + cid = conflict_info->consumer_info[i].consumer_id; + + if (!IsValidProcess(pid)) { + SERVER_ERR("handle(%d)/pid(%d) terminated", cid, pid); + m_rsc_mgr->ReleaseResourcesOfPid(pid); + ReleaseInvalidProcessResources(pid, cid); + continue; + } + + SERVER_DBG("[%d]th cid[%d]/rscs[%d]", i+1, cid, conflict_info->consumer_info[i].n_conflicted); + + callback_data = m_SerializeCallbackData(&conflict_info->consumer_info[i], reason, &data_size); + + if (CCallback::SendCallbackMessage(cid, pid, (void*) callback_data, data_size, &err) != RMS_OK) { + if (err == ENXIO) { //ENXIO No such device or address + SERVER_ERR("Process cannot get callback (CID:%d)/(PID:%d)", cid, pid); + m_rsc_mgr->ReleaseResourcesOfPid(pid); + ReleaseInvalidProcessResources(pid, cid); + free(callback_data); + continue; + } + + if (err == ENOENT && !IsRegisteredHandle(cid)) { + SERVER_ERR("already unregistred (%d)", cid); + free(callback_data); + continue; + } + + SERVER_ERR("failed to send callback message to (CID:%d)/(PID:%d), errno(%d)", cid, pid, err); + free(callback_data); + return RMS_ERROR; + } + + SERVER_WARN("[%d]th callback message sent to CID[%d]/PID[%d]/RSCS[%d]", i+1, cid, pid, conflict_info->consumer_info[i].n_conflicted); + + if (ProcessCallbackMessage(&conflict_info->consumer_info[i], requester_cid) != RMS_OK) { + if (!IsValidProcess(pid)) { + SERVER_ERR("handle(%d)/pid(%d) terminated", cid, pid); + m_rsc_mgr->ReleaseResourcesOfPid(pid); + ReleaseInvalidProcessResources(pid, cid); + free(callback_data); + + if (!IsRegisteredHandle(requester_cid)) { + SERVER_ERR("requester(%d:%d) terminated as well", pid, requester_cid); + *need_response = false; + return RMS_ERROR; + } + continue; + } + + rms_get_cmd_name(pid, cmd, sizeof(cmd)); + SERVER_ERR("failed to process callback request from : (%s) /(CID:%d)/(PID:%d)", cmd, cid, pid); + + rms_display_timeout_error_popup(RMS_ALARM_NO_DEALLOCATION, conflict_info->consumer_info[i]); + int ret = rms_report_emergency(cid, pid, RMS_EMERGENCY_CONSUMER_NOT_RESPONDING); + + SERVER_ERR("release resources of cosumer(%d) forcely", pid); + m_rsc_mgr->UnregisterConsumer(cid); + m_handle_mgr->RemoveHandle(cid, pid); + + free(callback_data); + return ret; + } + + free(callback_data); + } + + return RMS_OK; +} + +int CMessageHandler::SendResponse(rms_msg_response *response) +{ + return msgq_tx->send(response); +} + +int CMessageHandler::PushMessage(CAsyncQueue *queue, CMessage *msg) +{ + CMessage *msg_copy = new CMessage(msg->GetRequest()); + rms_msg_request *req = msg->GetRequest(); + SERVER_INFO("push_front msg type(%d)-pid(%d)-cid(%d)", req->type, req->pid, req->handle); + + queue->push_front(msg_copy); + + return RMS_OK; +} + +void CMessageHandler::m_ConstructResponse(rms_msg_response *response, int data_type, rms_response_type_e msg_type, int handle, int pid) +{ + assert(response); + + response->data_type = data_type; + response->type = msg_type; + response->handle = handle; + response->pid = pid; +} + +void CMessageHandler::NotifyWatchdog(void) +{ + if (!async_queue) + return; + + SERVER_INFO("push watchdog msg"); + async_queue->push(new CMessage("NotifyWatchdog")); +} + +GVariant *CMessageHandler::NotifyWatchdog(GVariant *params) +{ + SERVER_INFO("send watchdog notify completed"); + return NULL; +} diff --git a/src/CMessageQueue.cpp b/src/CMessageQueue.cpp new file mode 100644 index 0000000..8f114ba --- /dev/null +++ b/src/CMessageQueue.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include +#include + +CMessageQueue::CMessageQueue(msgq_type_e type) +{ + msgq_type = type; + + if (init() != RMS_OK) { + SERVER_ERR("failed to initialize message queue(%d)", type); + assert(0 && "failed to initialize message queue"); + } +} + +CMessageQueue::~CMessageQueue(void) +{ +} + +int CMessageQueue::init(void) +{ + int key = getKey(msgq_type); + + msgq_id = msgget((key_t) key, 0666 | IPC_CREAT); + if (msgq_id == -1) { + SERVER_ERR("failed to create a message queue (%d), errno(%d)", key, errno); + return RMS_ERROR; + } + + struct msqid_ds queue_stat; + long prev_size = 0; + + if (msgctl(msgq_id, IPC_STAT, &queue_stat) != 0) { + SERVER_ERR("failed to get queue info (%d:%d), errno(%d)", key, msgq_id, errno); + goto out; + } + + prev_size = queue_stat.msg_qbytes; + queue_stat.msg_qbytes = msgq_size; + + if (msgctl(msgq_id, IPC_SET, &queue_stat) != 0) { + SERVER_ERR("failed to set queue info (%d:%d), errno(%d)", key, msgq_id, errno); + goto out; + } + + SERVER_INFO("msgq(%d:%d) size changed (%ld) -> (%ld)", key, msgq_id, prev_size, msgq_size); + +out: + return RMS_OK; +} + +int CMessageQueue::send(rms_msg_response *response) +{ + int retry = 0; + + while (msgsnd(msgq_id, (void*) response, sizeof(rms_msg_response) - sizeof(long), 0) == -1) { + SERVER_ERR("failed to send response message (%d), retry(%d) - type(%d)/cid(%d)", errno, retry, response->type, response->handle); + + if (errno == EIDRM) { // errno 43 : identifier removed + SERVER_ERR("msgid removed from system"); + if (recover() != RMS_OK) + return RMS_ERROR; + } else if ((errno == EINVAL) && (response->data_type > 0)) { + SERVER_ERR("msgid might be removed from system"); + if (recover() != RMS_OK) { + return RMS_ERROR; + } + } + + if (retry >= 5) { //timeout + return RMS_ERROR; + } + + usleep(20*1000); // 20ms + retry++; + } + + return RMS_OK; + +} + +int CMessageQueue::receive(rms_msg_request *request, int msg_type) +{ + int ret = -1; + ret = msgrcv(msgq_id, (void*) request, sizeof(rms_msg_request) - sizeof(long), msg_type, 0); + + if (ret == -1) { + SERVER_ERR("failed to receive msg(%d:%d). errno(%d)", msgq_type, msgq_id, errno); + + if (errno == EIDRM) { // errno 43 : identifier removed + SERVER_ERR("WARNING! msgq(%d:%d) removed from system", msgq_type, msgq_id); + recover(); + } + + return RMS_ERROR; + } + + return RMS_OK; +} + +int CMessageQueue::recover(void) +{ + int key = getKey(msgq_type); + + msgq_id = msgget((key_t) key, 0666 | IPC_CREAT); + + if (msgq_id == -1) { + SERVER_ERR("failed to get new msgq_id, key(%d), errno(%d)", key, errno); + return RMS_ERROR; + } + + SERVER_ERR("message queue recovered - (%d:%d)", key, msgq_id); + return RMS_OK; +} + +int CMessageQueue::getKey(msgq_type_e type) +{ + return (type == MSG_QUEUE_RX) ? key_rx : key_tx; +} diff --git a/src/CQueryHandler.cpp b/src/CQueryHandler.cpp new file mode 100644 index 0000000..a3cf4b6 --- /dev/null +++ b/src/CQueryHandler.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include +#include +#include + +CQueryHandler::CQueryHandler(CResourceManager *rsc_mgr) +{ + assert(rsc_mgr); + m_rsc_mgr = rsc_mgr; +} + +CQueryHandler::~CQueryHandler(void) +{ +} + +int CQueryHandler::GetAnswer(rms_msg_request *request, int *answer_out) +{ + int result = RMS_OK; + int answer = 0; + char process_name[RMS_NAME_BUF_SIZE] = {0,}; + + switch (request->sub_type) { + case RMS_QUERY_ALLOCATION: + result = m_rsc_mgr->IsCategoryAvailableToUse(request, &answer); + *answer_out = answer; + break; + case RMS_QUERY_TERMINATE: + rms_get_cmd_name(request->pid, process_name, RMS_NAME_BUF_SIZE); + result = RMS_OK; + *answer_out = process_htable_contains(process_name); + break; + case RMS_QUERY_ACTIVE_DECS: + *answer_out = m_rsc_mgr->GetActiveDecoderNum(); + result = RMS_OK; + break; + default: + SERVER_ERR("not defined query type (%d)", request->sub_type); + break; + } + + return result; +} diff --git a/src/CRequest.cpp b/src/CRequest.cpp new file mode 100644 index 0000000..673ef53 --- /dev/null +++ b/src/CRequest.cpp @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "CSysInfo.h" +#include "CRequester.h" +#include "CRequest.h" + +CRequest::CRequest(CRequester *requester) +:m_requester(requester) +{ + m_device_id = 0; + m_category_id = 0; + m_category_option = 0; + m_category = RMS_CATEGORY_NONE; + m_result = RMS_ERROR; + m_candidate_device = RMS_DEVICE_NONE; + m_allocated_device = RMS_DEVICE_NONE; + m_virtual_device = RMS_DEVICE_NONE; +} + +CRequest::~CRequest() +{ +} + +CRequester *CRequest::getRequester(void) +{ + return m_requester; +} + +int CRequest::ToMultiviewZoneId(int category_option) +{ + const int ZONE_INFO = 0x1E00000; + int zone_id = ((category_option & ZONE_INFO) >> 21); + return zone_id; +} + +void CRequest::SetCategory(int category_id, int category_option) +{ + m_category_id = category_id; + m_category_option = category_option; + m_category = ToResourceCategory(category_id, category_option); + m_mixing_mode = ToMixingMode(category_id, category_option); + m_mv_zone_id = ToMultiviewZoneId(category_option); +} + +void CRequest::SetState(int req_state) +{ + m_state = (rms_requests_resource_state_e) req_state; +} + +void CRequest::SetResult(rms_return_code_e req_result) +{ + m_result = req_result; +} + +rms_return_code_e CRequest::GetResult(void) +{ + return m_result; +} + +rms_rsc_category_e CRequest::GetCategory(void) +{ + return m_category; +} + +bool CRequest::IsMainDeviceRequest(void) +{ + if (m_state == RMS_STATE_EXCLUSIVE_AUTO) + return false; + + SERVER_INFO("m_category_id(%d), option(%d)", m_category_id, m_category_option); + + if (IsSupportedCategory(m_category_option)) { + if ((m_category_option & RMS_DEVICE_OPT_MAIN) || (m_category_option & RMS_FORCE_TO_MAIN)) + return true; + } + + if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED)) { + return (m_category_option & RMS_DEVICE_OPT_MAIN); + } + + if (m_category_id == RMS_CATEGORY_AUDIO_DECODER) { + if (m_category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED) + return false; + if (m_category_option == RMS_DEVICE_OPT_NONE) + return true; + + return (m_category_option & RMS_DEVICE_OPT_MAIN); + } + + if (m_category_id == RMS_CATEGORY_MJPEG_DECODER) + return (m_category_option & RMS_DEVICE_OPT_MAIN); + + if (m_category == RMS_CATEGORY_SCALER_MULTIVIEW) + return (m_category_option & RMS_DEVICE_OPT_MAIN); + + return false; +} + +bool CRequest::IsAIDeviceRequest(void) +{ + if (m_state == RMS_STATE_EXCLUSIVE_AUTO) + return false; + + if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED)) + return (m_category_option & RMS_VIDEO_DEC_OPT_AI); + + return false; +} + +bool CRequest::IsSubDeviceRequest(void) +{ + if (m_state == RMS_STATE_EXCLUSIVE_AUTO) + return false; + + //SERVER_DBG("m_category_id(%d), option(%d)", m_category_id, m_category_option); + + if (IsSupportedCategory(m_category_option)) { + if ((m_category_option & RMS_DEVICE_OPT_SUB) || (m_category_option & RMS_FORCE_TO_SUB)) + return true; + } + + if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER_SUB) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED)) + return (m_category_option & RMS_DEVICE_OPT_SUB); + + if (m_category_id == RMS_CATEGORY_AUDIO_DECODER_SUB) { + if (m_category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED) + return false; + if (m_category_option == RMS_DEVICE_OPT_NONE) + return true; + + return (m_category_option & RMS_DEVICE_OPT_SUB); + } + + if (m_category_id == RMS_CATEGORY_MJPEG_DECODER) + return (m_category_option & RMS_DEVICE_OPT_SUB); + + if (m_category == RMS_CATEGORY_SCALER_MULTIVIEW) + return (m_category_option & RMS_DEVICE_OPT_SUB); + + return false; +} + +rms_rsc_category_e CRequest::ToVideoDecoderCategory(int category, int category_option, bool force_main, bool force_sub) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + + if (category_option == RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED) { + result = RMS_CATEGORY_NONE; + } else if ((category_option > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (category_option < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else { + if (category == RMS_CATEGORY_VIDEO_DECODER) { + result = (rms_rsc_category_e) ((force_sub) ? RMS_CATEGORY_VIDEO_DECODER_SUB : category); + } else if (category == RMS_CATEGORY_VIDEO_DECODER_SUB) { + result = (rms_rsc_category_e) ((force_main) ? (rms_rsc_category_e) RMS_CATEGORY_VIDEO_DECODER : category); + } else { + result = (rms_rsc_category_e) category; + } + } + + return result; +} + +rms_rsc_category_e CRequest::ToImageDecoderCategory(int category, int category_option) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + + SERVER_INFO("category(%d)/category_option(%d)", category, category_option); + + if (category_option == RMS_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED) { + result = RMS_CATEGORY_NONE; + } else if ((category_option > RMS_CATEGORY_HEIC_DECODER_OPTION) && (category_option < RMS_CATEGORY_HEIC_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else if ((category_option > RMS_CATEGORY_JPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else { + result = (rms_rsc_category_e) category; + } + + return result; +} + +rms_rsc_category_e CRequest::ToJpegDecoderCategory(int category, int category_option) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + + SERVER_INFO("category(%d)/category_option(%d)", category, category_option); + + if (category_option == RMS_CATEGORY_JPEG_DECODER_NOT_SUPPORTED) { + result = RMS_CATEGORY_NONE; + } else if ((category_option > RMS_CATEGORY_JPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else { + result = (rms_rsc_category_e) category; + } + + return result; +} + +rms_rsc_category_e CRequest::ToMJpegDecoderCategory(int category, int category_option) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + + if (category_option == RMS_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED) { + result = RMS_CATEGORY_NONE; + } else if ((category_option > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else { + result = (rms_rsc_category_e)category; + } + + return result; +} + +rms_rsc_category_e CRequest::ToAudioDecoderCategory(int category, int category_option, bool force_main, bool force_sub) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + bool support_mixing = CSysInfo::GetInstance()->IsAudioMixingSupported(); + + if (category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED) { + result = RMS_CATEGORY_NONE; + } else if (category_option == RMS_CATEGORY_NOT_PERMITTED) { + result = RMS_CATEGORY_NOT_PERMITTED; + } else if (support_mixing && (category_option > RMS_CATEGORY_AUDIO_DECODER_OPTION && category_option < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)) { + result = (rms_rsc_category_e) category_option; + } else { + if (category == RMS_CATEGORY_AUDIO_DECODER) { + result = (rms_rsc_category_e) ((force_sub) ? RMS_CATEGORY_AUDIO_DECODER_SUB : category); + } else if (category == RMS_CATEGORY_AUDIO_DECODER_SUB) { + result = (rms_rsc_category_e) ((force_main) ? RMS_CATEGORY_AUDIO_DECODER : category); + } else { + result = (rms_rsc_category_e) category; + } + } + + return result; +} + +rms_rsc_category_e CRequest::ToScalerCategory(int category, int category_option, bool force_main, bool force_sub) +{ + if (category_option == RMS_CATEGORY_NOT_PERMITTED) + return (rms_rsc_category_e) category_option; + + if (force_sub) + return RMS_CATEGORY_SCALER_SUB; + + if (force_main) + return RMS_CATEGORY_SCALER; + + if (category > RMS_CATEGORY_SCALER_OPTION && category < RMS_CATEGORY_SCALER_OPTION_MAX) + return (rms_rsc_category_e) category_option; + + if (category_option > RMS_CATEGORY_SCALER_OPTION && category_option < RMS_CATEGORY_SCALER_OPTION_MAX) + return (rms_rsc_category_e) category_option; + + return (rms_rsc_category_e) category; +} + +rms_rsc_category_e CRequest::ToAudioOutCategory(int category, int category_option, bool force_main, bool force_sub) +{ + if (category_option == RMS_CATEGORY_NOT_PERMITTED) + return (rms_rsc_category_e) category_option; + + if (force_sub) + return RMS_CATEGORY_AUDIO_SUB_OUT; + + if (force_main) + return RMS_CATEGORY_AUDIO_MAIN_OUT; + + return (rms_rsc_category_e) category; +} + +bool CRequest::IsSupportedCategory(int category_option) +{ + bool result = true; + + switch (category_option) { + case RMS_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED: + case RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED: + case RMS_CATEGORY_JPEG_DECODER_NOT_SUPPORTED: + case RMS_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED: + case RMS_CATEGORY_NOT_PERMITTED: + result = false; + break; + default: + result = true; + break; + } + + return result; +} + +int CRequest::UnmaskMainSubOptions(int category_option) +{ + int result = category_option; + + result = (result & ~RMS_DEVICE_OPT_MAIN); + result = (result & ~RMS_DEVICE_OPT_SUB); + + return result; +} + +int CRequest::UnmaskMixingOptions(int category_option) +{ + int result = category_option; + + result = (result & ~RMS_MIXING_OPT_DEFAULT); + result = (result & ~RMS_MIXING_OPT_MULTIVIEW); + result = (result & ~RMS_MIXING_OPT_INTERACTION_SOUND); + + return result; +} + +int CRequest::UnmaskForceOptions(int category_option) +{ + int result = category_option; + + result = (result & ~RMS_FORCE_TO_MAIN); + result = (result & ~RMS_FORCE_TO_SUB); + + return result; +} + +int CRequest::UnmaskMVZoneInfo(int category_option) +{ + const int ZONE_INFO = 0x1E00000; + + return (category_option & ~ZONE_INFO); +} + +rms_rsc_category_e CRequest::ToResourceCategory(int category, int category_option) +{ + rms_rsc_category_e result = RMS_CATEGORY_NONE; + bool supported = IsSupportedCategory(category_option); + bool force_main = false; + bool force_sub = false; + + if (supported) { + force_main = (category_option & RMS_FORCE_TO_MAIN); + force_sub = (category_option & RMS_FORCE_TO_SUB); + category_option = UnmaskMainSubOptions(category_option); + } + + switch (category) { + case RMS_CATEGORY_VIDEO_DECODER: + case RMS_CATEGORY_VIDEO_DECODER_SUB: + if (supported) { + category_option = UnmaskMVZoneInfo(category_option); + category_option = (category_option & ~RMS_VIDEO_DEC_OPT_AI); + category_option = UnmaskForceOptions(category_option); + } + result = ToVideoDecoderCategory(category, category_option, force_main, force_sub); + break; + case RMS_CATEGORY_JPEG_DECODER: + result = ToJpegDecoderCategory(category, category_option); + break; + case RMS_CATEGORY_MJPEG_DECODER: + if (supported) + category_option = UnmaskMVZoneInfo(category_option); + + result = ToMJpegDecoderCategory(category, category_option); + break; + case RMS_CATEGORY_IMAGE_DECODER: + result = ToImageDecoderCategory(category, category_option); + break; + case RMS_CATEGORY_AUDIO_DECODER: + case RMS_CATEGORY_AUDIO_DECODER_SUB: + if (supported) { + category_option = UnmaskMixingOptions(category_option); + category_option = UnmaskForceOptions(category_option); + } + + result = ToAudioDecoderCategory(category, category_option, force_main, force_sub); + break; + case RMS_CATEGORY_SCALER: + case RMS_CATEGORY_SCALER_SUB: + if (supported) + category_option = UnmaskMVZoneInfo(category_option); + + result = ToScalerCategory(category, category_option, force_main, force_sub); + break; + case RMS_CATEGORY_AUDIO_MAIN_OUT: + case RMS_CATEGORY_AUDIO_SUB_OUT: + result = ToAudioOutCategory(category, category_option, force_main, force_sub); + break; + default: + result = (rms_rsc_category_e) category; + break; + } + + return result; +} + +rms_mixing_mode_e CRequest::ToMixingMode(int category, int category_option) +{ + if (category != RMS_CATEGORY_AUDIO_DECODER && category != RMS_CATEGORY_AUDIO_DECODER_SUB) + return RMS_MIXING_MODE_DEFAULT; + + if (category_option & RMS_MIXING_OPT_MULTIVIEW) + return RMS_MIXING_MODE_MULTIVIEW; + + if (category_option & RMS_MIXING_OPT_INTERACTION_SOUND) + return RMS_MIXING_MODE_INTERACTION_SOUND; + + return RMS_MIXING_MODE_DEFAULT; +} + +void CRequest::PrintResult(void) +{ + SERVER_WARN("result (%d) - con(%d:%s) / cat(%d) / req(%d:%d) / devId(%d) / vId(%d) / rsn(%d)", + m_result, + m_requester->getHandle(), + m_requester->getAppId().empty() ? m_requester->GetCmdName().c_str() : m_requester->getAppId().c_str(), + m_category, m_category_id, m_category_option, m_allocated_device, m_virtual_device, m_reason); +} diff --git a/src/CRequester.cpp b/src/CRequester.cpp new file mode 100644 index 0000000..13de37d --- /dev/null +++ b/src/CRequester.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "CDebugUtils.h" +#include "CRequester.h" + +CRequester::CRequester() +{ + m_handle = 0; + m_pid = 0; + m_main_priority = 0; + m_sub_priority = 0; + m_app_id.assign(""); +} + +CRequester::CRequester(rms_msg_request *req) +{ + m_handle = req->handle; + m_pid = req->pid; + m_main_priority = req->main_priority; + m_sub_priority = req->sub_priority; + m_app_id.assign(req->app_id); + SetCmdName(req->pid); +} + +CRequester::~CRequester() +{ +} + +void CRequester::SetCmdName(int pid) +{ + char cmd_name[512] = {0, }; + std::string delimiter = "/"; + + rms_get_cmd_name(pid, cmd_name, 512); + m_cmd_name.assign(cmd_name); + m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length()); +} + +int CRequester::getHandle(void) +{ + return m_handle; +} + +int CRequester::getPid(void) +{ + return m_pid; +} + +int CRequester::getMainPriority(void) +{ + return m_main_priority; +} + +int CRequester::getSubPriority(void) +{ + return m_sub_priority; +} diff --git a/src/CResourceService.cpp b/src/CResourceService.cpp new file mode 100644 index 0000000..7fe4b7a --- /dev/null +++ b/src/CResourceService.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define RM_SERVER_SMART_DEADLOCK_WATCHDOG_TIME_90_SEC 90 +#define RM_SERVER_WATCHDOG_TIME_10000_MSEC 10000 +#define RM_SERVER_INVALID_TABLE_TIME_30000_MSEC 30000 + +int CResourceService::Init(GMainLoop *main_loop) +{ + CResourceManager *rsc_mgr = new CResourceManager(); + if (rsc_mgr->RegisterResources() != RMS_OK) { + SERVER_ERR("RegisterResources is failed"); + g_timeout_add(RM_SERVER_INVALID_TABLE_TIME_30000_MSEC, InvalidResourceTableMsgCallback, NULL); + return RMS_ERROR; + } + + m_msg_h = new CMessageHandler(rsc_mgr); + if (m_msg_h->Run() != RMS_OK) { + SERVER_ERR("RUN failed"); + return RMS_ERROR; + } + + SERVER_INFO("Done"); + return RMS_OK; +} + +int CResourceService::IsFirstLaunch(void) +{ + const char *vconf_key = "memory/rsc_mgr/is_launched_before"; + int is_launched_before = 0; + + if (vconf_get_int(vconf_key, &is_launched_before) != 0) + SERVER_ERR("Failed to get %s", vconf_key); + + if (is_launched_before == 1) { + SERVER_ERR("!!!!! Resource Manager 2nd Launch !!!!!"); + return 0; + } + + if (vconf_set_int(vconf_key, 1) != 0) + SERVER_ERR("Failed to set %s", vconf_key); + + return 1; +} + +void CResourceService::RequestColdPowerOff(void) +{ + const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg"; + + if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) { + SERVER_ERR("Failed to set %s", vconf_request_cold_poweroff); + } +} + +void CResourceService::CreateWatchDogTimer(void) +{ +} + +void CResourceService::SetVIPProcess(void) +{ + void *handle; + void (*vip_func)(void); + + handle = dlopen("/lib/libproc-stat.so.5", RTLD_LAZY); + + if (!handle) { + SERVER_ERR("failed to open libproc-stat.so (%s)", dlerror()); + return; + } + + *(void**)&vip_func = dlsym(handle, "proc_stat_set_vip_process"); + + if (!vip_func) { + SERVER_ERR("failed to find proc_stat_set_vip_process"); + dlclose(handle); + return; + } + + SERVER_INFO("set vip process"); + vip_func(); + dlclose(handle); +} + +gboolean CResourceService::WatchDogCallback(gpointer data) +{ + return G_SOURCE_CONTINUE; +} + +gboolean CResourceService::InvalidResourceTableMsgCallback(gpointer data) +{ + SERVER_ERR("resource table not loaded!"); + rms_print_model_info(); + return G_SOURCE_CONTINUE; +} diff --git a/src/CSysInfo.cpp b/src/CSysInfo.cpp new file mode 100644 index 0000000..e33c761 --- /dev/null +++ b/src/CSysInfo.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +CSysInfo *CSysInfo::m_instance = NULL; + +CSysInfo *CSysInfo::GetInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CSysInfo; + assert(m_instance); + } + + return m_instance; +} + +bool CSysInfo::IsAudioMixingSupported(void) +{ + static bool init = false; + bool supported = false; + + if (init) + return m_support_audio_mixing; + + if (system_info_get_custom_bool("com.samsung/featureconf/multiview.dualsound", &supported) != SYSTEM_INFO_ERROR_NONE) { + SERVER_ERR("failed to get com.samsung/featureconf/multiview.dualsound"); + return m_support_audio_mixing; + } + + m_support_audio_mixing = supported; + init = true; + SERVER_INFO("multiview.dualsound (%d)", supported); + return m_support_audio_mixing; +} diff --git a/src/gen_rm_msgq.cpp b/src/gen_rm_msgq.cpp new file mode 100644 index 0000000..92e8cd5 --- /dev/null +++ b/src/gen_rm_msgq.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define RM_MSGQ_KEY_TX 8212 +#define RM_MSGQ_KEY_RX 8211 + +static int _is_symlink_file(const char *path) +{ + struct stat st; + if (lstat(path, &st) == -1) { + SERVER_ERR("stat error. file path(%s)", path); + return 0; + } + + return (S_ISLNK(st.st_mode)) ? 1 : 0; +} + +static int _is_realpath(const char *path) +{ + char *rms_realpath = NULL; + int len_path = 0; + int len_realpath = 0; + int result = 1; + + rms_realpath = realpath(path, NULL); + + if (!rms_realpath) { + SERVER_INFO("realpath(%s) is null(%d)", path, errno); + return 0; + } + + len_path = strlen(path); + len_realpath = strlen(rms_realpath); + + if (len_path != len_realpath) { + SERVER_ERR("length mismatch(%d:%d)", len_path, len_realpath); + result = 0; + goto out; + } + + if (strncmp(path, rms_realpath, len_path)) { + SERVER_ERR("path mismatch(%s:%s)", path, rms_realpath); + result = 0; + goto out; + } + +out: + free(rms_realpath); + + return result; +} + +int main() +{ + int msgq_tx = -1, msgq_rx = -1; + msgq_tx = msgget((key_t)RM_MSGQ_KEY_TX, 0666 | IPC_CREAT); + msgq_rx = msgget((key_t)RM_MSGQ_KEY_RX, 0666 | IPC_CREAT); + + if ((msgq_tx == -1) || (msgq_rx == -1)) { + SERVER_ERR("NEW MSGQ_CREATE failed to get msgq_id - msgq_tx(%d), msgq_rx(%d)", msgq_tx, msgq_rx); + return -1; + } + + SERVER_INFO("msgq_tx (%d), msgq_rx(%d)", msgq_tx, msgq_rx); + + FILE *fp = NULL; + const char *flag_path = "/run/rsc_mgr_ready"; + + fp = fopen(flag_path,"w"); + + if (!fp) { + SERVER_ERR("NEW_MSGQ_CREATE Failed to create message queue(%s) errno(%d)", flag_path, errno); + return -1; + } + + if (!_is_realpath(flag_path)) { + SERVER_ERR("%s is not realpath", flag_path); + fclose(fp); + return -1; + } + + if (_is_symlink_file(flag_path)) { + SERVER_ERR("%s is symbolic link file", flag_path); + fclose(fp); + return -1; + } + + SERVER_INFO("NEW_MSGQ_CREATE resource manager message queue(%s) created", flag_path); + + fflush(fp); + fsync(fileno(fp)); + fclose(fp); + return 0; +} diff --git a/src/manager/CCache.cpp b/src/manager/CCache.cpp new file mode 100644 index 0000000..adde21f --- /dev/null +++ b/src/manager/CCache.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CCache *CCache::m_instance = NULL; + +CCache *CCache::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CCache; + } + + return m_instance; +} + +void CCache::SetAppStatus(std::string app_id, int status) +{ + m_visibility.insert(std::pair(app_id, status)); +} + +int CCache::GetAppStatus(std::string app_id) +{ + auto it = m_visibility.find(app_id); + + return (it == m_visibility.end()) ? -1 : it->second; +} + +void CCache::Drop(void) +{ + m_visibility.clear(); +} diff --git a/src/manager/CConsumer.cpp b/src/manager/CConsumer.cpp new file mode 100644 index 0000000..12bac79 --- /dev/null +++ b/src/manager/CConsumer.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +CConsumer::CConsumer(IN const rms_consumer_s *consumer) +{ + m_consumerID = consumer->consumer_id; + m_priority = consumer->priority; + m_pid = consumer->process_id; + m_app_id.assign(consumer->app_id); + + SetCmdName(m_pid); +} + +void CConsumer::SetCmdName(long pid) +{ + char cmd_name[RMS_NAME_BUF_SIZE] = {0, }; + std::string delimiter = "/"; + + rms_get_cmd_name(m_pid, cmd_name, RMS_NAME_BUF_SIZE); + m_cmd_name.assign(cmd_name); + SERVER_WARN("pid %ld cmd name %s", m_pid, cmd_name); + m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length()); + SERVER_WARN("m_cmd_name %s", m_cmd_name.c_str()); +} + +bool CConsumer::AddResource(IN int device_id) +{ + if (IsUsingResource(device_id)) { + SERVER_INFO("already registered device id(%d) in Consumer(%d)", device_id, m_consumerID); + return false; + } + + m_resources.insert(device_id); + return true; +} + +int CConsumer::ReleaseResource(IN int device_id) +{ + if (!IsUsingResource(device_id)) { + SERVER_WARN("CID[%d] / DevID[%d] the consumer does not use this device", m_consumerID, device_id); + return RMS_ERROR; + } + + m_resources.erase(device_id); + + return RMS_OK; +} + +bool CConsumer::IsUsingResource(IN int device_id) +{ + auto it = m_resources.find(device_id); + + return (it != m_resources.end()); +} + +void CConsumer::SetAppID(IN const char *app_id) +{ + m_app_id.assign(app_id); +} + +std::string CConsumer::GetAppId(int pid) +{ + char app_id[RMS_NAME_BUF_SIZE] ={0, }; + std::string result; + + if (aul_app_get_appid_bypid(pid, app_id, sizeof(app_id)) != AUL_R_OK) { + SERVER_ERR("failed to get appid of %d", pid); + return result; + } + + result.assign(app_id); + + return result; +} + +rms_error_type_e CConsumer::ComparePriority(CConsumer *requester) +{ + std::string app_id = requester->GetAppID(); + + m_app_id = (m_app_id.empty()) ? GetAppId((int) m_pid) : m_app_id; + + if (!CheckVisibility(app_id)) { + SERVER_ERR("The application is not visible. cannot take resource"); + return RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS; + } + + rms_priority_s requester_priority = requester->GetPriority(); + + if (!ComparePriority(requester_priority, m_priority)) { + char cmd[RMS_NAME_BUF_SIZE] = {0,}; + rms_get_cmd_name(m_pid, cmd, sizeof(cmd)); + SERVER_ERR("rqs_priority(%d/%d) - user_priority(%s-%d/%d)", requester_priority.main, requester_priority.sub, cmd, m_priority.main, m_priority.sub); + return RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + } + + return RMS_ERR_TYPE_NONE; +} + +bool CConsumer::ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2) +{ + if (priority1.main > priority2.main) { + return true; + } else if (priority1.main == priority2.main) { + return priority1.sub >= priority2.sub; + } else { + return false; + } +} + +bool CConsumer::CheckVisibility(IN std::string app_id_requester) +{ + if (app_id_requester.empty()) { + SERVER_INFO("requester app id : (null)"); + return true; + } + + bool visibility_consumer = (m_app_id.empty()) ? true : GetAppVisibility(m_app_id, false); + bool visibility_requester = GetAppVisibility(app_id_requester, true); + + if (visibility_requester) { + SERVER_INFO("requester is visible(%s)", app_id_requester.c_str()); + return true; + } + + if (!visibility_consumer) { + SERVER_INFO("current consumer(%d) is invisible(%s)", m_consumerID, m_app_id.c_str()); + return true; + } + + SERVER_ERR("current consumer(%s)- visibility:(%d)", (m_app_id.empty()) ? "null" : m_app_id.c_str(), visibility_consumer); + SERVER_ERR("requester(%s)- visibility:(%d)", app_id_requester.c_str(), visibility_requester); + + return false; +} + +int CConsumer::UpdateAppStatus(std::string app_id) +{ + char buf[RMS_NAME_BUF_SIZE]; + int status; + int n_max = 4; + snprintf(buf, RMS_NAME_BUF_SIZE, "Get visibility of application '%s'", app_id.c_str()); + + for (int i = 0; i < n_max; i++) { + usleep(50*1000); + + trace_begin(buf); + status = aul_app_get_status(app_id.c_str()); + trace_end(); + SERVER_INFO("app(%s) / status(%d) / (%d)", app_id.c_str(), status, i); + + if (IsVisibleStatus(status)) { + SERVER_ERR("status %d", status); + return status; + } + } + return status; +} + +bool CConsumer::NeedStatusUpdate(std::string app_id) +{ + return false; +} + +bool CConsumer::IsVisibleStatus(int status) +{ + return (status == STATUS_FOCUS || status == STATUS_VISIBLE); +} + +bool CConsumer::GetAppVisibility(std::string app_id, bool requester) +{ + CCache *cache = CCache::getInstance(); + int status = cache->GetAppStatus(app_id); + + if (status == -1) { + status = aul_app_get_status(app_id.c_str()); + + if (!IsVisibleStatus(status) && requester && NeedStatusUpdate(app_id)) + status = UpdateAppStatus(app_id); + + cache->SetAppStatus(app_id, status); + } + + return IsVisibleStatus(status); +} + +bool CConsumer::CheckWebAppState(IN std::string app_id_requesting) +{ + if (app_id_requesting.length() == 0) + return false; + + std::string webapp_vconf_key = std::string("rtc/memory/WebApp/") + app_id_requesting; + + char *status = vconf_get_str(webapp_vconf_key.c_str()); + if (!status) { + SERVER_INFO("%s is not webapp", app_id_requesting.c_str()); + return false; + } + + std::string webapp_status(status); + if (webapp_status.compare("resume")) { + SERVER_INFO("%s is not in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); + free(status); + return false; + } + + SERVER_INFO("%s is in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); + free(status); + + return true; +} diff --git a/src/manager/CConsumerContainer.cpp b/src/manager/CConsumerContainer.cpp new file mode 100644 index 0000000..3e75cb5 --- /dev/null +++ b/src/manager/CConsumerContainer.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CConsumerContainer *CConsumerContainer::m_instance = NULL; + +CConsumerContainer *CConsumerContainer::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CConsumerContainer; + assert(m_instance); + } + + return m_instance; +} + +CConsumer *CConsumerContainer::findConsumer(int consumer_id) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + return (it == m_consumers.end()) ? NULL : (*it).second; +} + +bool CConsumerContainer::AddConsumer(int consumer_id, CConsumer *consumer) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + if (it != m_consumers.end()) + return false; + + m_consumers.insert(std::pair(consumer_id, consumer)); + return true; +} + +void CConsumerContainer::RemoveConsumer(int consumer_id) +{ + m_consumers.erase(consumer_id); +} + +std::map CConsumerContainer::findConsumers(int pid) +{ + std::map result; + + for (auto const &it : m_consumers) { + CConsumer *consumer = it.second; + + if (consumer->GetPid() != pid) + continue; + + result.insert(std::pair(it.first, it.second)); + } + + return result; +} + +std::map CConsumerContainer::FindConsumers(std::string app_id) +{ + std::map result; + for (auto const &it : m_consumers) { + CConsumer *consumer = it.second; + if (app_id.compare(consumer->GetAppID())) + continue; + + result.insert(std::pair(it.first, it.second)); + } + + return result; +} diff --git a/src/manager/CDebugUtils.cpp b/src/manager/CDebugUtils.cpp new file mode 100644 index 0000000..5e24806 --- /dev/null +++ b/src/manager/CDebugUtils.cpp @@ -0,0 +1,734 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +static bool product_type_init = false; +static int product_type = 0; //SYSTEM_INFO_PRODUCT_TYPE_TV; + +// The process list which is killed by resource manager +static GHashTable *process_htable = NULL; + +#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) + +const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum) +{ + switch (state_enum) { + case RMS_INTERNAL_STATE_FREE: + return "FREE"; + case RMS_INTERNAL_STATE_SHARABLE: + return "SHARABLE"; + case RMS_INTERNAL_STATE_SHARED: + return "SHARED"; + case RMS_INTERNAL_STATE_EXCLUSIVE: + return "EXCLUSIVE"; + case RMS_INTERNAL_STATE_ERROR: + default: + return "NONE"; + } +} + +const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum) +{ + switch (state_enum) { + case RMS_STATE_PASSIVE: + return "PASSIVE"; + case RMS_STATE_SHARABLE: + return "SHARABLE"; + case RMS_STATE_EXCLUSIVE: + return "EXCLUSIVE"; + case RMS_STATE_EXCLUSIVE_CONDITIONAL: + return "EXCLUSIVE_CONDITIONAL"; + case RMS_STATE_EXCLUSIVE_AUTO: + return "EXCLUSIVE_AUTO"; + case RMS_STATE_EXCLUSIVE_PREFERENCE: + return "EXCLUSIVE_PREFERENCE"; + default: + return "NONE"; + } +} + +const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum) +{ + switch (category_enum) { + case RMS_CATEGORY_NONE: + return "NONE"; + case RMS_CATEGORY_AUDIO_DECODER: + return "Audio_Decoder"; + case RMS_CATEGORY_AUDIO_SPDIF_ES_OUTPUT: + return "Not Defined Yet"; + case RMS_CATEGORY_VIDEO_DECODER: + return "Video_Decoder"; + case RMS_CATEGORY_DEMUX: + return "Demux_Main"; + case RMS_CATEGORY_AUDIO_ENCODER: + return "Audio_Encoder"; + case RMS_CATEGORY_VIDEO_ENCODER: + return "Video_Encoder"; + case RMS_CATEGORY_SCALER: + return "Video_Scaler"; + case RMS_CATEGORY_TUNER: + return "Tuner"; + case RMS_CATEGORY_AUDIO_MAIN_OUT: + return "Audio_Main_Out"; + case RMS_CATEGORY_AUDIO_REMOTE_OUT: + return "Audio_Remote_Out"; + case RMS_CATEGORY_AUDIO_SCART_OUT: + return "Audio_Scart_Out"; + case RMS_CATEGORY_MM_PCM_OUT: + return "MM_PCM_playback"; + case RMS_CATEGORY_AUDIO_DECODER_SUB: + return "Audio_Decorder_Sub"; + case RMS_CATEGORY_JPEG_DECODER: + return "JPEG_Decoder"; + case RMS_CATEGORY_MJPEG_DECODER: + return "MJPEG_Decoder"; + case RMS_CATEGORY_SCALER_SUB: + return "Video_Scaler_Sub"; + case RMS_CATEGORY_EXT_VIDEO_SRC: + return "Ext_Video_Src"; + case RMS_CATEGORY_EXT_AUDIO_SRC: + return "Ext_Audio_Src"; + case RMS_CATEGORY_EXT_HDMI_SRC: + return "Ext_HDMI_Src"; + case RMS_CATEGORY_VIDEO_DECODER_SUB: + return "Video_Decoder_Sub"; + case RMS_CATEGORY_CAMERA: + return "Camera"; + case RMS_CATEGORY_DEMUX_REC: + return "Demux_Rec"; + case RMS_CATEGORY_TUNER_SUB: + return "Tuner_Sub"; + case RMS_CATEGORY_VIDEO_DECODER_UHD: + return "Video_Decoder UHD"; + case RMS_CATEGORY_INPUT_SRC_DTV: + return "Input_Src_DTV"; + case RMS_CATEGORY_INPUT_SRC_ATV: + return "Input_Src_ATV"; + case RMS_CATEGORY_INPUT_SRC_HDMI: + return "Input_Src_HDMI"; + case RMS_CATEGORY_INPUT_SRC_COMP: + return "Input_Src_COMP"; + case RMS_CATEGORY_INPUT_SRC_AV: + return "Input_Src_AV"; + case RMS_CATEGORY_INPUT_SRC_SCART: + return "Input_Src_SCART"; + case RMS_CATEGORY_MIC: + return "Mic"; + case RMS_CATEGORY_SW_DECODER: + return "SWDecoder"; + case RMS_CATEGORY_MMP_MEMORY_CLUSTER: + return "MMPlayer MemoryCluster"; + case RMS_CATEGORY_JPEG_DECODER_8K: + return "JPEG_Decoder 8K"; + case RMS_CATEGORY_SCALER_BG: + return "Video_Scaler_BG"; + default: + return ""; + } +} + +const char *rm_convert_device_enum_to_string(rms_device_e device_enum) +{ + switch (device_enum) { + case RMS_DEVICE_NONE: + return "NONE"; + case RMS_DEVICE_AUDIO_MAIN_OUT: + return "audio_main_out"; + case RMS_DEVICE_AUDIO_REMOTE_OUT: + return "audio_remote_out"; + case RMS_DEVICE_AUDIO_SCART_OUT: + return "audio_scart_out"; + case RMS_DEVICE_MM_PCM_OUT: + return "mm_pcm_out"; + case RMS_DEVICE_JPEG_DECODER: + return "jpeg_decoder"; + case RMS_DEVICE_DEMUX0: + return "demux0"; + case RMS_DEVICE_DEMUX1: + return "demux1"; + case RMS_DEVICE_DEMUX2: + return "demux2"; + case RMS_DEVICE_DEMUX3: + return "demux3"; + case RMS_DEVICE_AUDIO_ENCODER: + return "audio_encoder"; + case RMS_DEVICE_VIDEO_ENCODER: + return "video_encoder"; + case RMS_DEVICE_SCALER: + return "scaler"; + case RMS_DEVICE_EXT_VIDEO_SRC: + return "ext_video_src"; + case RMS_DEVICE_EXT_AUDIO_SRC: + return "ext_autio_src"; + case RMS_DEVICE_EXT_HDMI_SRC: + return "ext_hdmi_src"; + case RMS_DEVICE_CAMERA: + return "camera"; + case RMS_DEVICE_TUNER: + return "tuner"; + case RMS_DEVICE_TUNER_SUB: + return "tuner_sub"; + case RMS_DEVICE_SCALER_SUB: + return "scaler_sub"; + case RMS_DEVICE_AUDIO_DECODER: + return "audio_decoder"; + case RMS_DEVICE_AUDIO_DECODER_SUB: + return "audio_decoder_sub"; + case RMS_DEVICE_VIDEO_DECODER_MAIN: + return "video_decoder_main"; + case RMS_DEVICE_VIDEO_DECODER_SUB: + return "video_decoder_sub"; + case RMS_DEVICE_VIDEO_DECODER_UDDEC: + return "video_decoder_uddec"; + case RMS_DEVICE_VIDEO_DECODER_UDHEVC: + return "video_decoder_udhevc"; + case RMS_DEVICE_AUDIO_SPDIF_ES_OUTPUT: + return "audio_spdif_es_output"; + case RMS_DEVICE_MIC: + return "mic"; + case RMS_DEVICE_EXT_COMP_SRC: + return "ext_comp_src"; + case RMS_DEVICE_EXT_AV_SRC: + return "av_src"; + case RMS_DEVICE_MJPEG_DECODER: + return "mjpeg_decoder"; + case RMS_DEVICE_JPEG_DECODER_UHD: + return "jpeg_decoder_uhd"; + case RMS_DEVICE_MJPEG_DECODER_UHD: + return "mjpeg_decoder_uhd"; + case RMS_DEVICE_SW_DECODER: + return "sw_decoder"; + default: + return ""; + } +} + +const char *rm_print_allocation_failure_reason(int ret_value) +{ + switch (ret_value) { + case RMS_OK: + return "OK"; + case RMS_ERROR: + return "Cannot Allocate Resources"; + case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + return "RESOURCE CONFLICT - Other Consumer Is Using"; + case RMS_OK_UHD_RESOURCE_CONFLICT: + return "UHD RESOURCE CONFLICT - Other Consumer Is Using"; + default: + return ""; + } +} +void rms_create_popup(const char *title, const char *text) +{ + bundle *(*bundle_create_fp) (void); + int (*bundle_add_fp)(bundle*, const char*, const char*); + const char *(*bundle_get_val_fp) (bundle*, const char*); + int (*bundle_free_fp) (bundle*); + int (*syspopup_launch_fp) (char*, bundle*); + void *libsyspopup_handle = NULL; + void *libbundle_handle = NULL; + bundle *b = NULL; + char *error; + + libsyspopup_handle = dlopen(LIBDIR"/libsyspopup_caller.so.0.1.0", RTLD_LAZY); + if (!libsyspopup_handle) { + SERVER_ERR("failed to load syspopup library"); + goto end; + } + + libbundle_handle = dlopen(LIBDIR"/libbundle.so.0", RTLD_LAZY); + + if (!libbundle_handle) { + SERVER_ERR("failed to load bundle library"); + goto end; + } + + error = NULL; + + bundle_create_fp = (bundle *(*)(void)) dlsym(libbundle_handle, "bundle_create"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_create"); + goto end; + + } + + bundle_add_fp = (int (*)(bundle*, const char*, const char*)) dlsym(libbundle_handle, "bundle_add"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_add"); + goto end; + } + + bundle_get_val_fp = (const char *(*)(bundle*, const char*)) dlsym(libbundle_handle, "bundle_get_val"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_get_val"); + goto end; + } + + bundle_free_fp = (int (*)(bundle*)) dlsym(libbundle_handle, "bundle_free"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_free"); + goto end; + } + + syspopup_launch_fp = (int (*)(char*, bundle*)) dlsym(libsyspopup_handle, "syspopup_launch"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find alert-syspopup"); + goto end; + } + + b = bundle_create_fp(); + if (!b) { + SERVER_ERR("failed to create bundle"); + goto end; + } + + bundle_add_fp(b, "type", "title_message_1button"); + bundle_add_fp(b, "title", title); + bundle_add_fp(b, "text", text); + + bundle_get_val_fp(b, "type"); + bundle_get_val_fp(b, "title"); + bundle_get_val_fp(b, "text"); + + syspopup_launch_fp((char*)"alert-syspopup", b); + bundle_free_fp(b); + +end: + if (libsyspopup_handle) + dlclose(libsyspopup_handle); + + if (libbundle_handle) + dlclose(libbundle_handle); +} + +int rms_get_cmd_name(pid_t pid, char *name_out, int size) +{ + char name[RMS_NAME_BUF_SIZE] = {0,}; + FILE *f; + size_t sz; + + snprintf(name, sizeof(name), "/proc/%d/cmdline", pid); + f = fopen(name, "r"); + if (!f) { + SERVER_ERR("failed to open cmdline(%s) : %d", name, errno); + return RMS_ERROR; + } else { + sz = fread(name, sizeof(char), sizeof(name)-1, f); + name[sz] = '\0'; + fclose(f); + } + + snprintf(name_out, size, "%s", name); + return RMS_OK; +} + +void rms_print_log_console(char *buf) +{ + int fd, ret; + char output[RMS_CONSOLE_BUF_SIZE] ={0,}; + + struct timespec tnow; + + fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + + if (fd < 0) { + SERVER_ERR("console device open fail"); + return; + } + + if (is_symlink_file("/dev/console")) { + SERVER_ERR("%s is symbolic link file", "/dev/console"); + close(fd); + return; + } + + ret = clock_gettime(CLOCK_MONOTONIC, &tnow); + snprintf(output, RMS_CONSOLE_BUF_SIZE, "[RMS][%ld.%6ld] %s\n", tnow.tv_sec, tnow.tv_nsec/1000, buf); + ret = write(fd, output, strlen(output)); + + if (ret < 0) { + SERVER_ERR("Fail to write on console directly"); + } + + close(fd); +} + +int rm_get_product_type(void) +{ + if (product_type_init) + return product_type; + + int type = 0; /* SYSTEM_INFO_PRODUCT_TYPE_TV */ + + if (system_info_get_custom_int("com.samsung/featureconf/product.product_type", &type) != SYSTEM_INFO_ERROR_NONE) { + SERVER_ERR("Failed to get com.samsung/featureconf/product.product_type"); + } + + product_type_init = true; + product_type = type; + + return product_type; +} + +int rm_is_valid_pid(int pid) +{ + if (kill((pid_t) pid, 0) == 0) { + SERVER_INFO("pid(%d) is alive", pid); + return 1; + } + + SERVER_ERR("pid(%d)/errno(%d)", pid, errno); + + return (errno == ESRCH) ? 0 : 1; +} + +static void process_htable_destory_key(gpointer key) +{ + if (key) + free(key); +} + +static void process_htable_create(void) +{ + if (process_htable) { + SERVER_ERR("hash table already created"); + return; + } + + process_htable = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)process_htable_destory_key, NULL); + + SERVER_INFO("process hash table created"); +} + +static void process_htable_clear(void) +{ + SERVER_INFO("clear process hash table"); + + if (!process_htable) + return; + + g_hash_table_remove_all(process_htable); +} + +static void process_htable_insert(const char *name) +{ + const int PROCESS_DATA_LIMIT = 100; // The maxinum size is (RMS_NAME_BUF_SIZE * PROCESS_DATA_LIMIT) + + if (!process_htable) + process_htable_create(); + + if (g_hash_table_contains(process_htable, name)) + return; + + if (g_hash_table_size(process_htable) >= PROCESS_DATA_LIMIT) + process_htable_clear(); + + char *key_name = (char*) strndup(name, strlen(name)); + + g_hash_table_insert(process_htable, key_name, (gpointer) 1); + + SERVER_ERR("process info (%s) inserted to hash table (%d)", name, g_hash_table_size(process_htable)); +} + + +bool process_htable_contains(const char *name) +{ + bool result = false; + + if (!process_htable) { + SERVER_INFO("(%s) - no table", name); + return false; + } + + if (g_hash_table_size(process_htable) == 0) { + SERVER_INFO("(%s) - empty", name); + return false; + } + + result = g_hash_table_contains(process_htable, name); + + SERVER_INFO("(%s) - result(%d)", name, result); + + // resource manager is supposed to clear data once it's checked by application + process_htable_clear(); + + return result; +} + +int rms_report_emergency(IN int cid, IN int pid, IN int requester) +{ + const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg"; + int retry = 25; // 20ms * 25 times => 500ms + int ret = 0; + + SERVER_ERR("consumer is not responding....CID[%d]/PID[%d]/Requester(%d) - set cold power off mode", cid, pid, requester); + + if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) { + SERVER_ERR("Failed to set request cold power off"); + } else { + SERVER_ERR("memory/boot/cold_poweroff_request_pkg set as resource-manager"); + } + + char process_name[RMS_NAME_BUF_SIZE] = {0,}; + + if (rms_get_cmd_name(pid, process_name, RMS_NAME_BUF_SIZE) == RMS_OK) { + process_htable_insert(process_name); + } + + SERVER_ERR("kill PID(%d)", pid); + + int signal = SIGKILL; + + if (RMS_IS_DEBUG_IMAGE) { + signal = SIGABRT; + retry = 250; // 20ms * 250 times => 5 sec + } + + ret = kill(pid, signal); + + if (ret!=0) { + SERVER_ERR("Failed to kill(%d), errno(%d)", pid, errno); + } + + // wait until process is really terminated for 500ms + while (retry > 0 && rm_is_valid_pid(pid)) { + retry--; + SERVER_ERR("pid(%d) still alive(%d)", pid, retry); + usleep(20*1000); + continue; + } + + if (RMS_IS_DEBUG_IMAGE && retry <= 0) { + //process didn't get terminated for 5 seconds + SERVER_ERR("pid(%d) is not terminated.", pid); + return RMS_ERROR; + } + + return RMS_OK; +} + +void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info) +{ + const char *title = "Resource Allocation Failure"; + const char *style_notification_msg = ""; + const char *style_process_name = ""; + const char *indent = " "; + const char *notification_msg = "Please contact the owner(s) of process(es) below
"; + const char *reason0 = " Resource allocation failed because there is no callback response from below process(es)
"; + const char *reason1 = " Resource allocation failed because below process(es) did not request deallocation
"; + + char name[RMS_NAME_BUF_SIZE] = {0,}; + GString *gstr; + + if (!RMS_IS_DEBUG_IMAGE) { + SERVER_ERR("Not debug mode. Timeout alarm popup is not shown. reason(%d)", (int)reason); + return; + } + + SERVER_ERR("timeout alarm"); + + gstr = g_string_new(""); + + if (!gstr) { + SERVER_ERR("Failed to create debug popup command"); + return; + } + + g_string_append_printf(gstr, "%s", style_notification_msg); + + switch (reason) { + case RMS_ALARM_NO_CALLBACK_RESPONSE: + g_string_append_printf(gstr, "%s%s", indent, reason0); + break; + case RMS_ALARM_NO_DEALLOCATION: + g_string_append_printf(gstr, "%s%s", indent, reason1); + break; + default : + break; + } + + g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_process_name); + + rms_get_cmd_name(info.process_id, name, sizeof(name)); + g_string_append_printf(gstr, "%s%s : %d - %s%s", indent, "pid", (int)(info.process_id), name, "
"); + + for (int i = 0; i < info.n_conflicted; i++) { + g_string_append_printf(gstr, "%s [%d] %s%s", indent, i+1, rm_convert_category_enum_to_string(info.conflicted_resources[i].category_id), "
"); + } + rms_create_popup(title, gstr->str); + SERVER_ERR("Command: %s", gstr->str); + g_string_free(gstr, true); +} + +static bool rms_read_index(int *data) +{ + FILE *fp = NULL; + char str[10] = {0,}; + size_t str_size; + const char *filename = "/proc/device-tree/rm_tbl_idx"; + + if (!data) { + SERVER_ERR("invalid input : null data"); + return false; + } + + fp = fopen(filename, "rb"); + + if (!fp) { + SERVER_ERR("failed to open (%s) - errno(%d)", filename, errno); + return false; + } + + str_size = fread(str, sizeof(char), sizeof(str)-1, fp); + + str[str_size] = '\0'; + + if (str_size == 0) { + fclose(fp); + return false; + } + + *data = atoi(str); + + fclose(fp); + fp = NULL; + + return true; +} + +void rms_display_resource_table_error_popup(void) +{ + const char *title = "FATAL ERROR!!!"; + const char *reason = " Resource Manager can't find a resource table for this board
"; + const char *style_notification_msg = ""; + const char *indent = " "; + const char *notification_msg = "
"; + + GString *gstr = g_string_new(""); + char *chipset_info; + int model_index = -1; + + if (!gstr) { + SERVER_ERR("Failed to create debug popup command"); + return; + } + + g_string_append_printf(gstr, "%s%s", indent, reason); + g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_notification_msg); + g_string_append_printf(gstr, "%sProduct type : %d%s", indent, rm_get_product_type(), "
"); + + if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) { + SERVER_ERR("Failed to get chipset from system-info\n"); + goto end; + } + + g_string_append_printf(gstr, "%sChipset : %s%s", indent, chipset_info, "
"); + + if (!rms_read_index(&model_index)) { + SERVER_ERR("failed to read model index"); + } + + g_string_append_printf(gstr, "%sIndex : %d%s", indent, model_index, "
"); + + rms_create_popup(title,gstr->str); + + if (chipset_info) { + free(chipset_info); + } + +end: + g_string_free(gstr, true); + return; +} + +void rms_print_model_info(void) +{ + static char *chipset_info = NULL; + static int rm_index = -1; + + if (!chipset_info) { + if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) + SERVER_ERR("Failed to get chipset"); + } + + if (rm_index == -1) { + if (!rms_read_index(&rm_index)) + SERVER_ERR("failed to read rm index"); + } + + SERVER_ERR("> chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); + + char buf[512]; + snprintf(buf, 512, "resource table not loaded! > chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); + rms_print_log_console(buf); +} + +int is_symlink_file(const char *path) +{ + struct stat st; + if (lstat(path, &st) == -1) { + SERVER_ERR("stat error. file path(%s)", path); + return 0; + } + + return (S_ISLNK(st.st_mode)) ? 1 : 0; +} + +const char *rm_convert_error_type_to_string(rms_error_type_e error_type) +{ + switch (error_type) { + case RMS_ERR_TYPE_NONE: + return "None"; + case RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS: + return "Request of invisible process"; + case RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS: + return "Request of low priority process"; + case RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE: + return "Not available resource"; + case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST: + return "Requested resource does not exist"; + case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + return "Take resource from other consumer"; + default: + return ""; + } +} diff --git a/src/manager/CLockController.cpp b/src/manager/CLockController.cpp new file mode 100644 index 0000000..b094c2a --- /dev/null +++ b/src/manager/CLockController.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +std::mutex m; +CLockController *CLockController::m_instance = nullptr; + +CLockController *CLockController::GetInstance(void) +{ + if (m_instance == nullptr) + { + m_instance = new(std::nothrow) CLockController(); + } + + return m_instance; +} + +void CLockController::Lock(ResourceType rsc_type) +{ + std::unique_lock lock(m); + unsigned int count = 0; + auto it = m_locks.find(rsc_type); + + count = (it == m_locks.end()) ? 1 : ++it->second; + + m_locks.insert(std::pair(rsc_type, count)); +} + +void CLockController::Unlock(ResourceType rsc_type) +{ + std::unique_lock lock(m); + + auto it = m_locks.find(rsc_type); + if (it == m_locks.end()) + return; + + if (it->second == 0) + return; + + m_locks.at(rsc_type) = --it->second; + + if (m_locks.at(rsc_type) == 0) + NotifyUnlock(); +} + +unsigned int CLockController::GetLockCount(void) +{ + std::unique_lock lock(m); + unsigned int count = 0; + + for (auto &it : m_locks) + count += it.second; + + return count; +} + +void CLockController::NotifyUnlock(void) +{ + CMessage *msg = new CMessage("NotifyUnlock"); + m_msg_q->push(msg); +} + +bool CLockController::IsLocked(CMessage *msg) +{ + if ((m_locks.at(ResourceType::VIDEO_SCALER) > 0) && msg->IsMsgFor(ResourceType::VIDEO_SCALER)) + return true; + + return false; +} diff --git a/src/manager/CPriority.cpp b/src/manager/CPriority.cpp new file mode 100644 index 0000000..f85ee21 --- /dev/null +++ b/src/manager/CPriority.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include + +int CPriority::compare(int cur_consumer_id, int consumer_id) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *cur_consumer = c_container->findConsumer(cur_consumer_id); + if (!cur_consumer) + return HIGH_PRIORITY; + + CConsumer *consumer = c_container->findConsumer(consumer_id); + if (!consumer) + return LOW_PRIORITY; + + return (cur_consumer->ComparePriority(consumer) == RMS_ERR_TYPE_NONE) ? HIGH_PRIORITY : LOW_PRIORITY; +} + +int CPriority::compareCurConsumers(int device_id, int consumer_id) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + + CConsumer *consumer = c_container->findConsumer(consumer_id); + if (!consumer) + return LOW_PRIORITY; + + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + if (!resource) + return HIGH_PRIORITY; + + std::set rsc_consumers = resource->GetConsumers(); + + for (auto const &it : rsc_consumers) { + CConsumer *rsc_consumer = c_container->findConsumer(it); + + if (!rsc_consumer) + continue; + + if (rsc_consumer->GetId() == consumer_id) { + SERVER_WARN("consumer(%d) is already using (%d)", consumer_id, device_id); + return SAME_PRIORITY; + } + + if (rsc_consumer->ComparePriority(consumer) != RMS_ERR_TYPE_NONE) { + SERVER_WARN("LOW PRORITY consumer (%d) device (%d)", consumer_id, device_id); + return LOW_PRIORITY; + } + } + + return HIGH_PRIORITY; +} + +int CPriority::getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + if (!resource || !requester) + return RMS_ERROR; + + if (resource->IsSharableState()) + return RMS_ERROR; + + std::set consumers = resource->GetConsumers(); + + for (auto const &it : consumers) { + int cid = it; + + if (isReclaimableConsumer(cid , consumer_id, err_type)) { + reclaimables->insert(std::pair(device_id, cid)); + break; + } + } + + if (reclaimables->empty()) { + SERVER_ERR("high priority consumer is using device(%d)", device_id); + return RMS_ERROR; + } + + return RMS_OK; +} + +bool CPriority::isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *consumer = c_container->findConsumer(consumer_id); + CConsumer *requester = c_container->findConsumer(requester_id); + + if (!consumer || !requester) + return false; + + if (consumer_id == requester_id) + return false; + + rms_error_type_e error_type = consumer->ComparePriority(requester); + + if (error_type != RMS_ERR_TYPE_NONE) { + if (err_type) + *err_type = error_type; + + return false; + } + + return true; +} + +int CPriority::getReclaimableConsumers(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + if (!resource || !requester) + return RMS_ERROR; + + if (resource->IsFreeState()) + return RMS_ERROR; + + std::set consumers = resource->GetConsumers(); + + for (auto const &it : consumers) { + int cid = it; + + if (!isReclaimableConsumer(cid , consumer_id, err_type)) + continue; + + reclaimables->insert(std::pair(device_id, cid)); + } + + if (reclaimables->empty()) + { + SERVER_ERR("high priority consumer is using device(%d)", device_id); + return RMS_ERROR; + } + + return RMS_OK; +} diff --git a/src/manager/CResource.cpp b/src/manager/CResource.cpp new file mode 100644 index 0000000..11505ed --- /dev/null +++ b/src/manager/CResource.cpp @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define RMS_SUBSCALER_FLAG "memory/rsc_mgr/subscaler_status" + +using namespace std; +void CResource::m_SetSubScalerFlag(int next_state) +{ + if (next_state == RMS_INTERNAL_STATE_ERROR) + return; + int value = 0; + switch (next_state) { + case RMS_INTERNAL_STATE_FREE: + value = 0; + break; + case RMS_INTERNAL_STATE_SHARABLE: + case RMS_INTERNAL_STATE_SHARED: + case RMS_INTERNAL_STATE_EXCLUSIVE: + value = 1; + break; + } + if (vconf_set_int(RMS_SUBSCALER_FLAG,value) != 0) { + SERVER_ERR("Failed to Set vconf key - %s",RMS_SUBSCALER_FLAG); + return; + } + SERVER_INFO("Subscaler flag set to - %d", value); +} + +CResource::CResource(const int device_id, const rms_rsc_category_e category_type, const char *name, const char *path, + std::set mem_cluster, int is_main_device, const char *audio_codec, int sharable_count) +:m_id(device_id), m_device_name(name), m_device_path(path), m_is_main_device(is_main_device), m_sharable_count(sharable_count) +{ + m_state = RMS_INTERNAL_STATE_FREE; + m_occupied_bw = 0; + m_default_bw = 0; + m_is_reserved = false; + m_reserved_consumer_id = 0; + m_mixing_mode = RMS_MIXING_MODE_DEFAULT; + m_mem_clusters = mem_cluster; + m_virtual_id = 0; + m_mv_zone_id = -1; + + if (audio_codec) + m_audio_codec.assign(audio_codec); + + m_category_type = category_type; + m_cur_category = category_type; + m_is_scaler = IsScaler(category_type); +} + +CResource::~CResource() +{ +} + +bool CResource::IsScaler(rms_rsc_category_e category) +{ + bool result = false; + + switch (category) { + case RMS_CATEGORY_SCALER: + case RMS_CATEGORY_SCALER_BG: + case RMS_CATEGORY_SCALER_SUB: + case RMS_CATEGORY_SCALER_SUB2: + case RMS_CATEGORY_SCALER_SUB3: + result = true; + break; + default: + break; + } + + return result; +} + +void CResource::UpdateProperties(std::set mem_clusters, int bw, int category, int category_class, int vrsc_id) +{ + m_mem_clusters = mem_clusters; + m_occupied_bw = bw; + m_cur_category = category; + m_category_class = category_class; + m_vrsc_id = vrsc_id; +} + +int CResource::ReserveExclusive(int consumer_id) +{ + if (m_is_reserved && (consumer_id != m_reserved_consumer_id)) { + SERVER_ERR("rsc(%d) already reserved by(%d)", m_id, m_reserved_consumer_id); + return RMS_ERROR; + } + + m_reserved_consumer_id = consumer_id; + m_is_reserved = true; + + return RMS_OK; +} + +int CResource::ReserveShared(int consumer_id) +{ + if (m_is_reserved) { + SERVER_ERR("rsc(%d) already reserved by (%d) with exclusive mode", m_id, m_reserved_consumer_id); + return RMS_ERROR; + } + + m_reserved_count++; + + if ( (m_shared_count + m_reserved_count) > m_sharable_count) { + SERVER_ERR("can't reserve(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); + m_reserved_count--; + return RMS_ERROR; + } + + SERVER_INFO("reserve share(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); + + return RMS_OK; +} + +int CResource::Reserve(int consumer_id, rms_requests_resource_state_e state) +{ + return (state == RMS_STATE_SHARABLE) ? ReserveShared(consumer_id):ReserveExclusive(consumer_id); +} + +void CResource::CancelReservation(rms_requests_resource_state_e state) +{ + if (state == RMS_STATE_SHARABLE) + m_reserved_count = (--m_reserved_count < 0) ? 0 : m_reserved_count; + else + m_is_reserved = false; +} + +void CResource::AddConsumer(IN const int consumer_id, IN rms_requests_resource_state_e state) +{ + if (IsRegisteredConsumer(consumer_id)) { + IncreaseRefCount(consumer_id); + m_shared_count++; + SERVER_INFO("[rsc(%d)]increase ref count of (%d), shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); + return; + } + + m_consumers.insert(std::pair(consumer_id, 1)); + m_consumer_ids.insert(consumer_id); + + if (state == RMS_STATE_SHARABLE) { + m_shared_consumers.insert(consumer_id); + m_shared_count++; + SERVER_INFO("[rsc(%d)] consumer(%d) shares resource, shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); + } + + return; +} + +void CResource::ResetConsumer(std::set new_consumers) +{ + m_consumers.clear(); + m_consumer_ids.clear(); + m_shared_consumers.clear(); + m_shared_count = 0; + + for (auto &it : new_consumers) { + AddConsumer(it, RMS_STATE_EXCLUSIVE); + } +} + +bool CResource::IsRegisteredConsumer(int consumer_id) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + return (it != m_consumers.end()); +} + +int CResource::IncreaseRefCount(int consumer_id) +{ + int ref_count = 0; + std::map::iterator it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) + return 0; + + ref_count = it->second; + m_consumers[consumer_id] = ++ref_count; + + return ref_count; +} + +int CResource::DecreaseRefCount(int consumer_id) +{ + int ref_count = 0; + std::map::iterator it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) + return 0; + + ref_count = it->second; + --ref_count; + ref_count = (ref_count < 0) ? 0 : ref_count; + m_consumers[consumer_id] = ref_count; + + return ref_count; +} + +int CResource::RemoveConsumer(IN int consumer_id, IN bool force) +{ + if (!IsRegisteredConsumer(consumer_id)) { + SERVER_ERR("[rsc(%d)] consumer(%d) is not found in list", m_id, consumer_id); + return 0; + } + + int ref_count = DecreaseRefCount(consumer_id); + + if (m_state == RMS_INTERNAL_STATE_SHARABLE || m_state == RMS_INTERNAL_STATE_SHARED) { + m_shared_count = (--m_shared_count < 0) ? 0 : m_shared_count; + + if (force) + m_shared_count = ((m_shared_count -= ref_count) < 0) ? 0 : m_shared_count; + } + + if (ref_count > 0 && !force) { + SERVER_INFO("consumer(%d) is still sharing resource(%d), ref(%d)", consumer_id, m_id, ref_count); + return ref_count; + } + + m_consumer_ids.erase(consumer_id); + m_consumers.erase(consumer_id); + ChangeStateByRelease(consumer_id); + + return 0; +} + +void CResource::ChangeState(rms_resource_internal_state_e next_state) +{ + if (m_state == next_state) + return; + + SERVER_INFO("state changed (%s : %s) - (%s -> %s)", + rm_convert_category_enum_to_string(m_category_type), + m_device_name, + rm_convert_state_enum_to_string(m_state), + rm_convert_state_enum_to_string(next_state)); + + m_state = next_state; + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); +} + +bool CResource::ChangeStateByAllocation(IN rms_requests_resource_state_e requested_state, const int consumer_id, int mv_zone_id) +{ + if (requested_state == RMS_STATE_EXCLUSIVE_CONDITIONAL || requested_state == RMS_STATE_EXCLUSIVE_AUTO || requested_state == RMS_STATE_EXCLUSIVE_PREFERENCE) + requested_state = RMS_STATE_EXCLUSIVE; + + rms_resource_internal_state_e allocation_resource_state_matrix[4][3] = + {{RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_EXCLUSIVE}, + {RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, + {RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, + {RMS_INTERNAL_STATE_EXCLUSIVE, RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_ERROR}}; + + bool need_notify_by_alloc_matrix[4][3] = {{false, true, true}, + {false, true, false}, + {false, true, false}, + {false, false, true}}; + + rms_resource_internal_state_e next_state = allocation_resource_state_matrix[m_state][requested_state]; + SERVER_INFO("m_state %d requested_state %d next_state %d", m_state, requested_state, next_state); + + bool need_notify = need_notify_by_alloc_matrix[m_state][requested_state]; + + m_is_reserved = false; + m_reserved_consumer_id = 0; + + if (next_state == RMS_INTERNAL_STATE_ERROR) { + SERVER_ERR("state change error! device(%d) (%s) to (%s)", m_id, rm_convert_state_enum_to_string(m_state), rm_convert_state_enum_to_string(next_state)); + return false; + } + + m_state = next_state; + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); + + if (mv_zone_id > 0) { + m_mv_zone_id = mv_zone_id; + SERVER_INFO("(%d) > zone_id(%d)", m_id, m_mv_zone_id); + } + + if (need_notify) + NotifyObservers(UPDATED_BY_ALLOC, consumer_id); + + return true; +} + +bool CResource::ChangeStateByRelease(int consumer_id) +{ + rms_resource_internal_state_e current_state = m_state; + rms_resource_internal_state_e next_state = RMS_INTERNAL_STATE_ERROR; + + bool need_notify = false; + + SERVER_INFO("current_state %d m_shared_count %d", current_state, m_shared_count); + + switch (current_state) { + case RMS_INTERNAL_STATE_SHARED: + m_shared_consumers.erase(consumer_id); + need_notify = true; + + if (m_shared_count > 1) { + next_state = RMS_INTERNAL_STATE_SHARED; + } else if (m_shared_count == 1) { + next_state = RMS_INTERNAL_STATE_SHARABLE; + } else { + next_state = RMS_INTERNAL_STATE_FREE; + } + break; + case RMS_INTERNAL_STATE_EXCLUSIVE: + case RMS_INTERNAL_STATE_SHARABLE: + next_state = RMS_INTERNAL_STATE_FREE; + need_notify = true; + break; + case RMS_INTERNAL_STATE_FREE: + default: + SERVER_ERR("unexpected resource state (%d)", current_state); + next_state = RMS_INTERNAL_STATE_FREE; + break; + } + + m_state = next_state; + SERVER_INFO("m_state %d need notify %d", m_state, need_notify); + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); + + if (need_notify) { + m_mv_zone_id = -1; + NotifyObservers(UPDATED_BY_RELEASE, consumer_id); + } + + return true; +} + +bool CResource::IsAllocatableState(IN rms_requests_resource_state_e requested_state) +{ + bool can_allocation_matrix[4][6] = + /*requested_state*/ /* PASSIVE */ /*SHARABLE*/ /*EXCLUSIVE*/ /* EXCLUSIVE CON */ /* EXCLUSIVE AUTO */ /* EXCLUSIVE PREFERENCE */ + /* m_state */ /* FREE */{ {false, true, true, true, true, true }, + /* SHARABLE */ { true, true, false, false, false, false }, + /* SHARED */ { true, true, false, false, false, false }, + /* EXCLUSIVE */ { true, false, false, false, false, false } }; + + SERVER_INFO("Status - DevID[%d:%s] / CatID[%d] / CurState[%s] / ReqState[%s]", + m_id, m_device_name, m_category_type, rm_convert_state_enum_to_string(m_state), rm_convert_requested_state_enum_to_string(requested_state)); + + /* check requested_state is valid */ + if ((requested_state < RMS_STATE_PASSIVE) || (requested_state > RMS_STATE_EXCLUSIVE_PREFERENCE)) { + SERVER_ERR("rquested state is invalid"); + return false; + } + + return can_allocation_matrix[m_state][requested_state]; +} + +void CResource::SetDefaultBW(unsigned int bw) +{ + m_default_bw = bw; + m_occupied_bw = bw; +} +void CResource::SetAllocatedTime(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + unsigned long sec = t.tv_sec * 1000; + unsigned long nsec = t.tv_nsec / 1000000; + m_allocated_time = sec + nsec; +} + +void CResource::RegisterObserver(CResourceObserver *observer) +{ + if (!observer) { + SERVER_ERR("observer NULL"); + return; + } + + m_observers.push_back(observer); +} + +void CResource::UnregisterObserver(CResourceObserver *observer) +{ + auto it = std::find(m_observers.begin(), m_observers.end(), observer); + + if (it == m_observers.end()) { + SERVER_ERR("not registered observer"); + return; + } + + m_observers.erase(it); + + SERVER_INFO("observer removed"); +} + +void CResource::NotifyObservers(resource_update_type_e type, const int consumer_id) +{ + for (CResourceObserver *observer : m_observers) { + observer->Update(type, m_id, consumer_id); + } +} + +bool CResource::Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id) +{ + if (!ChangeStateByAllocation(state, consumer_id, mv_zone_id)) + return false; + + AddConsumer(consumer_id, state); + return true; +} + +void CResource::SetZoneId(int zone_id) +{ + SERVER_INFO("(%d) > zone_id(%d)", m_id, zone_id); + m_mv_zone_id = zone_id; +} + +void CResource::UpdateAudioCodec(std::string codec_name) +{ + m_audio_codec = codec_name; +} + +bool CResource::IsAudioDevice(void) +{ + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER) + return true; + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_SUB) + return true; + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_PRIMARY) + return true; + if ((m_category_type > RMS_CATEGORY_AUDIO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)) + return true; + + return false; +} + +bool CResource::IsVideoDecoder(void) +{ + if (m_category_type == RMS_CATEGORY_VIDEO_DECODER) + return true; + if (m_category_type == RMS_CATEGORY_VIDEO_DECODER_SUB) + return true; + if ((m_category_type > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)) + return true; + if (m_category_type == RMS_CATEGORY_MJPEG_DECODER) + return true; + if ((m_category_type > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX)) + return true; + + return false; +} + +int CResource::GetFirstConsumer(void) +{ + if (m_consumer_ids.empty()) + return -1; + + auto it = m_consumer_ids.begin(); + return *it; +} + +int CResource::GetVirtualDeviceId(void) +{ + return (m_virtual_id < RI_VIRTUAL_ID_SCALER) ? m_id : m_virtual_id; +} + +bool CResource::IsJpegDecoder(void) +{ + if (m_category_type == RMS_CATEGORY_JPEG_DECODER) + return true; + if ((m_category_type > RMS_CATEGORY_JPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) + return true; + + return false; +} diff --git a/src/manager/CResourceCategory.cpp b/src/manager/CResourceCategory.cpp new file mode 100644 index 0000000..0633a61 --- /dev/null +++ b/src/manager/CResourceCategory.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CResourceCategory::CResourceCategory(IN rms_rsc_category_e resource_category_id, IN int category_class) +:m_categoryID(resource_category_id) +{ + m_alloc_strategy = CAllocateStrategyProvider::getInstance()->GetStrategy(resource_category_id, category_class); + assert(m_alloc_strategy); +} + +void CResourceCategory::AddVirtualResource(IN int device_id, IN CVirtualResource *vresource) +{ + std::map::iterator it = m_device_id_to_vresource_map.find(device_id); + + if (it != m_device_id_to_vresource_map.end()) + return; + + m_device_id_to_vresource_map.insert(std::pair(device_id, vresource)); +} + +CResource *CResourceCategory::ReserveCandidate(CRequest *req, bool apply_promotion) +{ + CVirtualResource *vrsc = m_alloc_strategy->findCandidate(m_device_id_to_vresource_map, req); + + if (!vrsc) + return NULL; + + if (m_alloc_strategy->reserveResource(vrsc, req) != RMS_OK) { + SERVER_INFO("can't find candidate (%d)", m_categoryID); + return NULL; + } + + SERVER_INFO("candidate found (%d:%d)", m_categoryID, vrsc->GetResource()->GetDeviceID()); + + req->SetResult(RMS_OK); + req->SetReason(RMS_ERR_TYPE_NONE); + + return vrsc->GetResource(); +} + +bool CResourceCategory::hasFreeStateResource(void) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsFreeState()) + return true; + } + + return false; +} + +void CResourceCategory::MakeResourceMapSortedByAllocTime(std::multimap *resource_map) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *rsc = vresource->GetResource(); + + resource_map->insert(std::pair(rsc->GetAllocatedTime(), vresource)); + } +} + +void CResourceCategory::GetRetirableConsumers(CRequest *req, + std::multimap* return_ids_in_category, + rms_error_type_e *err_type) +{ + assert(return_ids_in_category); + + std::multimap sorted_resource_map; + MakeResourceMapSortedByAllocTime(&sorted_resource_map); + m_alloc_strategy->GetRetirableConsumers(sorted_resource_map, req, return_ids_in_category, err_type); +} + +bool CResourceCategory::IsAvailableToUse(rms_requests_resource_state_e request_state) +{ + CResource *resource; + CDependencyController *dc = CDependencyController::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { + SERVER_ERR("Not available: Mem Cluster is occupied."); + continue; + } + + if (vresource->GetBW() > bandwidth->GetAvail()) { + SERVER_ERR("Not available: BW is insufficient!!"); + continue; + } + + if ((request_state == RMS_STATE_SHARABLE) && (!resource->IsSharableDevice())) { + SERVER_ERR("Not available: resource(%d) cannot be shared", resource->GetDeviceID()); + continue; + } + + if (resource->IsAllocatableState(request_state)) + return true; + } + + return false; +} + +void CResourceCategory::GetResources(std::map *resource_map) +{ + int i = 0; + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + resource_map->insert(std::pair(i++, resource)); + } +} + +CResource *CResourceCategory::FindMainResource(void) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsMainDevice()) + return resource; + } + + return NULL; +} diff --git a/src/manager/CResourceDB.cpp b/src/manager/CResourceDB.cpp new file mode 100644 index 0000000..12751ec --- /dev/null +++ b/src/manager/CResourceDB.cpp @@ -0,0 +1,779 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CResourceDB *CResourceDB::m_instance = NULL; + +CResourceDB *CResourceDB::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CResourceDB; + assert(m_instance); + } + + return m_instance; +} + +CResourceCategory *CResourceDB::FindResourceCategory(IN rms_rsc_category_e category_id) +{ + std::map::iterator it = m_resourceCategoryMap.find(category_id); + + if (it == m_resourceCategoryMap.end()) + return NULL; + + return (*it).second; +} + +CResource *CResourceDB::FindResource(IN const int device_id) +{ + std::map::iterator it = m_deviceid_to_rsc.find(device_id); + + if (it == m_deviceid_to_rsc.end()) { + SERVER_ERR("no device id(%d) in DB", device_id); + return NULL; + } + + return (*it).second; +} + +CVirtualResource *CResourceDB::FindVirtualResource(const int vid) +{ + auto it = m_v_deviceid_to_rsc.find(vid); + + return (it == m_v_deviceid_to_rsc.end()) ? nullptr : it->second; +} + +void CResourceDB::AddVirtualDeviceID(IN CVirtualResource *vresource) +{ + int vrsc_id = vresource->GetVResourceID(); + + std::map::iterator it = m_v_deviceid_to_rsc.find(vrsc_id); + + if (it != m_v_deviceid_to_rsc.end()) + return; + + m_v_deviceid_to_rsc.insert(std::pair(vrsc_id, vresource)); +} + +void CResourceDB::AddDeviceID(IN int device_id, IN CResource *resource) +{ + std::map::iterator it = m_deviceid_to_rsc.find(device_id); + + if (it != m_deviceid_to_rsc.end()) + return; + + m_deviceid_to_rsc.insert(std::pair(device_id, resource)); +} + +void CResourceDB::AddDeviceName(IN const char *device_name, IN CResource *resource) +{ + auto it = m_devicename_to_rsc.find(std::string(device_name)); + + if (it != m_devicename_to_rsc.end()) { + SERVER_DBG("already registered device name(%s) in DB", device_name); + return; + } + + m_devicename_to_rsc.insert(std::pair(std::string(device_name), resource)); +} + +void CResourceDB::AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category) +{ + std::map::iterator it = m_resourceCategoryMap.find(category_id); + + if (it != m_resourceCategoryMap.end()) + return; + + m_resourceCategoryMap.insert(std::pair(category_id, resource_category)); +} + +CResource *CResourceDB::FindResource(const char *device_name) +{ + auto it = m_devicename_to_rsc.find(std::string(device_name)); + + return (it == m_devicename_to_rsc.end()) ? NULL : it->second; +} + +void CResourceDB::AddVirtualResource(IN CVirtualResource *vrsc, + IN rms_rsc_category_e resource_category_id, + IN const char *name, + IN const char *path, + IN std::set mem_cluster_info, + IN unsigned int device_id_unique, + IN int is_main_device, + IN const char *audio_codec, + IN int sharable_count, + IN int mixing_count, + IN CResourceObserver *observer) +{ + assert(name); + assert(path); + + CResource *rsc = FindResource(name); + + if (!rsc) { + rsc = new CResource(device_id_unique, resource_category_id, name, path, mem_cluster_info, is_main_device, audio_codec, sharable_count); + + AddDeviceName(name, rsc); + AddDeviceID(device_id_unique, rsc); + + rsc->RegisterObserver(this); + rsc->RegisterObserver(observer); + } + + vrsc->SetResource(rsc); + + CAudioCodecCollection::getInstance()->registerAudioCodec(audio_codec, mixing_count); + + if (rsc->GetDefaultBW() == 0) + rsc->SetDefaultBW(vrsc->GetBW()); + + AddVirtualDeviceID(vrsc); +} + +void CResourceDB::UpdateBWbyRelease(CResource *rsc) +{ + if (!rsc) + return; + + if (rsc->GetBW() == 0) + return; + + CBandwidth *bw = CBandwidth::GetInstance(); + bw->RemoveConsumer(rsc->GetDeviceID(), rsc->GetCurCategory(), rsc->GetCategoryClass()); + bw->Increase(rsc->GetBW(), rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); + + return; +} + +void CResourceDB::UpdateByRelease(CResource *resource, const int device_id, const int consumer_id) +{ + UpdateBWbyRelease(resource); + + if (resource->IsVideoDecoder()) + RemoveActiveVideoDecoder(device_id, resource->GetCategoryClass()); + + if (resource->IsJpegDecoder()) + RemoveActiveJpegDecoder(device_id); + + RemoveResourceHasZoneId(resource->GetDeviceID()); +} + +void CResourceDB::UpdateBWbyAllocation(const unsigned int bandwidth, CResource *rsc) +{ + CBandwidth *bw = CBandwidth::GetInstance(); + bw->Decrease(bandwidth, rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); + + //SERVER_INFO("bw updated avail(%d)/max(%d)", bw->GetAvail(), bw->GetMax()); +} + +void CResourceDB::UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id) +{ + unsigned int bw = resource->GetBW(); + + if (bw > 0) { + UpdateBWbyAllocation(bw, resource); + CBandwidth::GetInstance()->AddConsumer(device_id, consumer_id, resource->GetCurCategory(), resource->GetCategoryClass()); + } + + if (resource->IsVideoDecoder()) + AddActiveVideoDecoder(device_id, consumer_id, resource->GetCategoryClass()); + + if (resource->IsScaler()) + SetVirtualScalerId(resource); + + if (resource->IsJpegDecoder()) + AddActiveJpegDecoder(device_id, consumer_id); + + if (resource->GetZoneId() > 0) + InsertResourceHasZoneId(resource); +} + +void CResourceDB::SetVirtualScalerId(CResource *resource) +{ + int scaler_id = GetVirtualScalerId(resource); + + SERVER_INFO("map scaler (%d:%d)", scaler_id, resource->GetDeviceID()); + + resource->SetVirtualDeviceId(scaler_id); + InsertVirtualScaler(scaler_id, resource); +} + +void CResourceDB::PrintVirtualScalerMap(void) +{ + for (auto &it : m_scaler_map) { + if (it.second == nullptr) { + //SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); + continue; + } + //SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); + } +} + +int CResourceDB::GetVirtualScalerId(CResource *resource) +{ + CResource *rsc = nullptr; + + for (auto &it : m_scaler_map) { + rsc = it.second; + if (rsc == nullptr) + continue; + if (rsc->GetDeviceID() == resource->GetDeviceID()) + return it.first; + } + + return resource->GetDedicatedVirtualDeviceId(); +} + +void CResourceDB::AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class) +{ + m_active_vdecs.insert(std::pair(device_id, consumer_id)); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + m_active_nvdecs.insert(std::pair(device_id, consumer_id)); +} + +void CResourceDB::RemoveActiveVideoDecoder(const int device_id, const int category_class) +{ + m_active_vdecs.erase(device_id); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + m_active_nvdecs.erase(device_id); +} + +void CResourceDB::AddActiveJpegDecoder(const int device_id, const int consumer_id) +{ + m_active_jdecs.insert(std::pair(device_id, consumer_id)); +} + +void CResourceDB::RemoveActiveJpegDecoder(const int device_id) +{ + m_active_jdecs.erase(device_id); +} + +int CResourceDB::GetActiveDecoderNum(void) +{ + int num = 0; + + num += m_active_vdecs.size(); + num += m_active_jdecs.size(); + + return num; +} + +void CResourceDB::PrintVideoDecoderConsumers(void) +{ + for (auto const &it : m_active_vdecs) { + SERVER_INFO("dev(%d) by (%d)", it.first, it.second); + } +} + +bool CResourceDB::HasAvailableDecoder(void) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + + SERVER_INFO("active(%d) / n_dec(%d) / max(%d / %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); + + if (active_ndecs > 0) + active_vdecs = active_vdecs + (1 - active_ndecs); + + if (active_vdecs >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (active_vdecs < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoderNDecoding(void) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + + SERVER_INFO("active(%d) / n_dec(%d) / max(%d %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); + + if (active_ndecs > 0) { + active_vdecs = active_vdecs + (1 - active_ndecs); + return true; + } + + if (active_vdecs >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (active_vdecs < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoder(std::multimap retirables) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + std::map retirables_vdecs; + + SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); + + for (auto &it : retirables) { + CResource *rsc = FindResource(it.first); + if (!rsc) + continue; + + if (rsc->IsVideoDecoder()) + retirables_vdecs.insert(std::pair(it.first, it.second)); + } + + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + int retirable_vdecs = retirables_vdecs.size(); + int retirable_ndecs = CountNDecoders(retirables_vdecs); + + int remain = 0; + + if ((active_ndecs - retirable_ndecs) > 0) + remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); + else + remain = active_vdecs - retirable_vdecs; + + SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); + + if (remain >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (remain < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoderNDecoding(std::multimap retirables) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + std::map retirables_vdecs; + + SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); + + for (auto &it : retirables) { + CResource *rsc = FindResource(it.first); + if (!rsc) + continue; + + if (rsc->IsVideoDecoder()) + retirables_vdecs.insert(std::pair(it.first, it.second)); + } + + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + int retirable_vdecs = retirables_vdecs.size(); + int retirable_ndecs = CountNDecoders(retirables_vdecs); + + int remain = 0; + + if ((active_ndecs - retirable_ndecs) > 0) + remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); + else + remain = active_vdecs - retirable_vdecs; + + SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); + + if (active_ndecs > 0 && retirable_ndecs > 0) + return true; + + if (remain >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (remain < max_vdecs); +} + +int CResourceDB::CountNDecoders(std::map retirables_vdecs) +{ + int ndecs = 0; + for (auto &it_rsc : retirables_vdecs) { + auto it_ndec = m_active_nvdecs.find(it_rsc.first); + + if (it_ndec != m_active_nvdecs.end()) + ndecs++; + } + + SERVER_INFO("ndecs(%d) in retirables(%zu)", ndecs, retirables_vdecs.size()); + return ndecs; +} + +void CResourceDB::Update(resource_update_type_e type, const int device_id, const int consumer_id) +{ + CResource *resource = FindResource(device_id); + + if (!resource) + return; + + switch (type) { + case UPDATED_BY_ALLOC: + SERVER_WARN("UPDATED_BY_ALLOC"); + UpdateByAllocation(resource, device_id, consumer_id); + break; + case UPDATED_BY_RELEASE: + SERVER_WARN("UPDATED_BY_RELEASE"); + UpdateByRelease(resource, device_id, consumer_id); + break; + default: + SERVER_ERR("unexpected update type (%d)", type); + break; + } + + NotifyResourceStateUpdatedAsync(resource, consumer_id); +} + +void CResourceDB::AddReclaimResources(consumer_reclaim_s *consumers) +{ + for (int i = 0; i < consumers->ret_quantity; i++) { + for (int j = 0; j < consumers->consumer_info[i].n_conflicted; j++) { + SERVER_INFO("add reclaim rsc (%d)", consumers->consumer_info[i].conflicted_resources[j].device_id); + m_reclaim_rscs.insert(consumers->consumer_info[i].conflicted_resources[j].device_id); + } + } +} + +void CResourceDB::ClearReclaimResources(void) +{ + m_reclaim_rscs.clear(); +} + +gboolean CResourceDB::NotifyResourceStateUpdated(gpointer data) +{ + if (!data) { + SERVER_ERR("invalid data"); + return G_SOURCE_REMOVE; + } + + CResourceState *state = (CResourceState*) data; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (!connection) { + SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + goto out; + } + + SERVER_INFO("notify state changed (device id %d( type %d) : state %d)", state->GetDeviceId(), state->GetCategoryType(), state->GetState()); + + if (!g_dbus_connection_emit_signal(connection, + NULL, + RM_DBUS_OBJ_PATH, + RM_DBUS_INTERFACE_NAME, + "RscStateChanged", + g_variant_new("(iiiis)", state->GetDeviceId(), state->GetCategoryType(), state->GetState(), state->GetConsumerId(), state->GetAppId().c_str()), + &error)) + SERVER_ERR("failed to send state changed (%d:%s)", state->GetDeviceId(), (error) ? error->message : "unknown"); + +out: + if (error) + g_error_free(error); + + delete state; + return G_SOURCE_REMOVE; +} + +void CResourceDB::NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id) +{ + int device_id = resource->GetDeviceID(); + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id); + std::string app_id = consumer->GetAppID(); + + if (app_id.empty()) + app_id = consumer->GetCmdName(); + + SERVER_INFO("device id (%d) consumer id (%d)", device_id, consumer_id); + + if (m_reclaim_rscs.find(device_id) != m_reclaim_rscs.end()) { + SERVER_DBG("skip to notify state updated (%d)", device_id); + return; + } + + CResourceState *state = new CResourceState(resource->GetDeviceID(), resource->GetCategoryType(), consumer_id, resource->GetState(), app_id); + g_idle_add(&CResourceDB::NotifyResourceStateUpdated, state); +} + +CResource *CResourceDB::FindMainResource(rms_rsc_category_e category_id) +{ + CResourceCategory *category = FindResourceCategory(category_id); + if (!category) { + SERVER_ERR("category(%d) not found", category_id); + return NULL; + } + + return category->FindMainResource(); +} + +void CResourceDB::FindMainResources(IN std::map *resource_map) +{ + rms_rsc_category_e categories[5] = {RMS_CATEGORY_VIDEO_DECODER, RMS_CATEGORY_VIDEO_DECODER_UHD, RMS_CATEGORY_SCALER, RMS_CATEGORY_AUDIO_DECODER, RMS_CATEGORY_AUDIO_MAIN_OUT}; + CResource *resource = NULL; + + for (int i = 0; i < 6; i++) { + resource = FindMainResource(categories[i]); + if (!resource) { + SERVER_INFO("no main resource for (%d)", categories[i]); + continue; + } + + resource_map->insert(std::pair(resource->GetDeviceID(), resource)); + } +} + +void CResourceDB::FindActiveVideoDecoders(IN std::map *resource_map) +{ + CResource *rsc = nullptr; + for (auto const &it : m_active_vdecs) { + rsc = FindResource(it.first); + if (!rsc) + continue; + resource_map->insert(std::pair(it.first, rsc)); + } +} + +void CResourceDB::GetScalerList(std::map *scalers) +{ + CResource *rsc = nullptr; + for (auto &it : m_deviceid_to_rsc) { + rsc = it.second; + if (!rsc->IsScaler()) + continue; + + scalers->insert(std::pair(rsc->GetDeviceID(), rsc)); + } +} + +void CResourceDB::InitScalerTable(void) +{ + CResource *rsc = nullptr; + int sub_scaler_count = 0; + int vid = 0; + + std::map scalers; + GetScalerList(&scalers); + + for (auto &it : scalers) { + rsc = it.second; + + if (!rsc->IsMainDevice()) + sub_scaler_count++; + + vid = (rsc->IsMainDevice()) ? RI_VIRTUAL_ID_SCALER : (RI_VIRTUAL_ID_SCALER + sub_scaler_count); + rsc->SetDedicatedVirtualDeviceId(vid); + rsc->SetVirtualDeviceId(vid); + //SERVER_INFO("insert scaler (%d:%d)", vid, rsc->GetDeviceID()); + m_scaler_map.insert(std::pair(vid, rsc)); + } +} + +int CResourceDB::FindRealDeviceId(int virtual_id) +{ + auto it = m_scaler_map.find(virtual_id); + + if (it == m_scaler_map.end()) + return virtual_id; + + CResource *rsc = it->second; + + return (rsc == nullptr) ? virtual_id : rsc->GetDeviceID(); +} + +CResource *CResourceDB::FindScaler(int virtual_id) +{ + auto it = m_scaler_map.find(virtual_id); + if (it == m_scaler_map.end()) + return nullptr; + + return it->second; +} + +int CResourceDB::ToScalerId(int device_id) +{ + const int SCALER_ID_MAIN = 0; + const int SCALER_ID_SUB = 1; + const int SCALER_ID_SUB2 = 2; + const int SCALER_ID_SUB3 = 3; + const int SCALER_ID_UNKNOWN = 99; + int source_id = SCALER_ID_UNKNOWN; + + switch (device_id) { + case RMS_DEVICE_SCALER: + source_id = SCALER_ID_MAIN; + break; + case RMS_DEVICE_SCALER_SUB: + source_id = SCALER_ID_SUB; + break; + case RMS_DEVICE_SCALER_SUB2: + source_id = SCALER_ID_SUB2; + break; + case RMS_DEVICE_SCALER_SUB3: + source_id = SCALER_ID_SUB3; + break; + default: + SERVER_ERR("unexpected device_id(%d)", device_id); + break; + } + + return source_id; +} + +void CResourceDB::UpdateVirtualScalerIds(void) +{ + std::map scaler_map; + for (auto &it : m_scaler_map) { + if (it.second == nullptr) { + SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); + continue; + } + + scaler_map.insert(std::pair(it.first, ToScalerId(it.second->GetDeviceID()))); + SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); + } + + CVideoController::GetInstance()->UpdateVirtualScalerIds(scaler_map); +} + +void CResourceDB::InsertVirtualScaler(int virtual_id, CResource *resource) +{ + m_scaler_map.erase(virtual_id); + m_scaler_map.insert(std::pair(virtual_id, resource)); + PrintVirtualScalerMap(); +} + +int CResourceDB::SwapScaler(int id_a, int id_b) +{ + CResource *rsc_a = FindScaler(id_a); + CResource *rsc_b = FindScaler(id_b); + + SERVER_INFO("scaler swap (%d <-> %d)", id_a, id_b); + + if (!rsc_a || !rsc_b) { + SERVER_ERR("invalid scaler id_a(%d)/id_b(%d)", id_a, id_b); + return -1; + } + + std::set consumers_a = rsc_a->GetConsumers(); + std::set consumers_b = rsc_b->GetConsumers(); + + int zone_a = rsc_a->GetZoneId(); + int zone_b = rsc_b->GetZoneId(); + + rsc_a->SetZoneId(zone_b); + rsc_b->SetZoneId(zone_a); + + rms_resource_internal_state_e state_a = (rms_resource_internal_state_e) rsc_a->GetState(); + rms_resource_internal_state_e state_b = (rms_resource_internal_state_e) rsc_b->GetState(); + rsc_a->ChangeState(state_b); + rsc_b->ChangeState(state_a); + + UpdateConsumerInfoOfResource(rsc_a, consumers_b, id_b); + UpdateConsumerInfoOfResource(rsc_b, consumers_a, id_a); + + // update resource info of each consumer + SwapResource(consumers_a, rsc_a->GetDeviceID(), rsc_b->GetDeviceID()); + SwapResource(consumers_b, rsc_b->GetDeviceID(), rsc_a->GetDeviceID()); + + // update memcluster owners + CDependencyController::getInstance()->SwapConsumers(rsc_a->GetDeviceID(), consumers_a, rsc_b->GetDeviceID(), consumers_b); + + // update virtual scaler table + InsertVirtualScaler(id_a, rsc_b); + InsertVirtualScaler(id_b, rsc_a); + return 0; +} + +void CResourceDB::UpdateConsumerInfoOfResource(CResource *resource, std::set new_consumers, int new_virtual_id) +{ + resource->ResetConsumer(new_consumers); + resource->SetVirtualDeviceId(new_virtual_id); +} + +void CResourceDB::SwapResource(std::set consumers, int cur_device_id, int new_device_id) +{ + CConsumer *consumer; + for (auto &it : consumers) { + consumer = CConsumerContainer::getInstance()->findConsumer(it); + if (!consumer) { + SERVER_ERR("invalid consumer (%d)", it); + continue; + } + + SERVER_INFO("swap resource (%d):(%d>%d)", it, cur_device_id, new_device_id); + + if (consumer->IsUsingResource(new_device_id)) { + SERVER_INFO("no need to swap (%d:%d)", it, new_device_id); + continue; + } + consumer->ReleaseResource(cur_device_id); + consumer->AddResource(new_device_id); + } +} + +void CResourceDB::InsertResourceHasZoneId(CResource *rsc) +{ + int device_id = rsc->GetDeviceID(); + auto it = m_rscs_has_zone_id.find(device_id); + + if (it != m_rscs_has_zone_id.end()) + return; + + m_rscs_has_zone_id.insert(std::pair(device_id, rsc)); + SERVER_INFO("inserted (%d:%d:%zu)", device_id, rsc->GetZoneId(), m_rscs_has_zone_id.size()); +} + +void CResourceDB::RemoveResourceHasZoneId(int device_id) +{ + if (m_rscs_has_zone_id.empty()) + return; + + auto it = m_rscs_has_zone_id.find(device_id); + if (it != m_rscs_has_zone_id.end()) + return; + + m_rscs_has_zone_id.erase(device_id); + SERVER_INFO("removed (%d:%zu)", device_id, m_rscs_has_zone_id.size()); +} + +void CResourceDB::ResetZoneIds(void) +{ + CResource *rsc = nullptr; + SERVER_INFO("Reset zone ids"); + + for (auto &it : m_rscs_has_zone_id) { + rsc = it.second; + if (!rsc) + continue; + rsc->SetZoneId(-1); + } + m_rscs_has_zone_id.clear(); +} diff --git a/src/manager/CResourceManager.cpp b/src/manager/CResourceManager.cpp new file mode 100644 index 0000000..166b724 --- /dev/null +++ b/src/manager/CResourceManager.cpp @@ -0,0 +1,783 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void allocateCandidate(CRequest *req) +{ + if (req->GetResult() != RMS_OK) + return; + + CResource *rsc = CResourceDB::getInstance()->FindResource(req->GetCandidateDevice()); + CRequester *requester = req->getRequester(); + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(requester->getHandle()); + + if (!consumer) { + SERVER_ERR("unregister consumer (%d)", requester->getHandle()); + return; + } + + req->ResetResult(); + + if (!rsc->Allocate(consumer->GetId(), (rms_requests_resource_state_e) req->GetState(), req->GetMultiviewZoneId())) { + SERVER_ERR("can't allocate a resource(%d:%d) for %d", req->GetCategory(), req->GetState(), requester->getHandle()); + return; + } + + req->SetResult(RMS_OK); + req->SetAllocatedDevice(rsc->GetDeviceID()); + req->SetAllocatedVirtualDevice(rsc->GetVirtualDeviceId()); + + consumer->AddResource(rsc->GetDeviceID()); +} + +CResourceManager::CResourceManager(void) +{ + m_is_db_created = 0; + m_error_type = RMS_ERR_TYPE_NONE; + m_consumers = CConsumerContainer::getInstance(); + m_db = CResourceDB::getInstance(); +} + +void CResourceManager::MakeRequests(CRequester *requester, rms_msg_request *reqs, std::vector *requests) +{ + for (int i = 0; i < reqs->request_num; i++) { + CRequest *request = new CRequest(requester); + request->SetCategory(reqs->resource[i], reqs->resource_option[i]); + request->SetState(reqs->state[i]); + + requests->push_back(request); + } +} + +int CResourceManager::AllocateResources(rms_msg_request *req, rms_return_device_s *allocated_devices) +{ + CRequester *requester = new CRequester(req); + std::vector requests; + rms_allocate_result_s alloc_result; + + MakeRequests(requester, req, &requests); + + CAllocateModeStrategy *strategy = CAllocateModeStrategyProvider::getInstance()->GetStrategy(req); + + if (!strategy->CanAllocateResources(requests, &alloc_result)) + goto out; + + AllocateCandidates(requests); + +out: + strategy->WriteAllocResult(&alloc_result, requests, allocated_devices); + + std::for_each(requests.begin(), requests.end(), [](CRequest *request) { request->PrintResult(); delete request; }); + + delete requester; + delete strategy; + + //SERVER_INFO("cid(%d)/pid(%d)/requested(%d), result(%d)-reason(%d)", req->handle, req->pid, req->request_num, alloc_result.result, alloc_result.reason); + + return alloc_result.result; + +} + +void CResourceManager::AllocateCandidates(std::vector requests) +{ + std::for_each(requests.begin(), requests.end(), allocateCandidate); +} + +int CResourceManager::RegisterResources(void) +{ + if (m_is_db_created) { + SERVER_ERR("Resource manager DB exists"); + return RMS_OK; + } + + m_db->SetMaxVideoDecoders(ri_get_max_video_decoder_num()); + + CBandwidth *bandwidth = CBandwidth::GetInstance(); + bandwidth->SetMax((unsigned int) ri_get_system_bw()); + + int num_of_device = 0; + ri_device_common_attr_s *rm_device_list = NULL; + + if (ri_get_device_list(&num_of_device, &rm_device_list) != RI_OK) { + if (rm_device_list != NULL) + free(rm_device_list); + + SERVER_ERR("failed to get device list"); + return RMS_ERROR; + } + + //SERVER_INFO("system bw(%d), num of device(%d)", bandwidth->GetMax(), num_of_device); + + CDependencyController *dc = CDependencyController::getInstance(); + CResourceObserver *observer = dc; + + for (int i = 0; i < num_of_device; i++) { + ri_device_common_attr_s dev = rm_device_list[i]; + + std::set mem_clusters; + for (unsigned int j = 0; j < dev.n_mem_clusters; j++) { + mem_clusters.insert(dev.mem_clusters[j]); + dc->RegisterMemCluster(dev.mem_clusters[j]); + } + + int category_class = ri_get_category_class(dev.category); + CVirtualResource *vrsc = new CVirtualResource((int) dev.id, (rms_rsc_category_e)(dev.category), dev.bw, mem_clusters, dev.is_main_device, dev.audio_codec, category_class); + + m_db->AddVirtualResource(vrsc, (rms_rsc_category_e) dev.category_main, dev.name, + dev.path, mem_clusters, dev.id_unique, + dev.is_main_device, dev.audio_codec, dev.sharable_count, + dev.mixing_count, observer); + + CResourceCategory *category = m_db->FindResourceCategory((rms_rsc_category_e) dev.category); + + if (!category) { + category = new CResourceCategory((rms_rsc_category_e) dev.category, category_class); + } + + category->AddVirtualResource(vrsc->GetVResourceID(), vrsc); + m_db->AddResourceCategory((rms_rsc_category_e) dev.category, category); + } + + if (rm_device_list != NULL) + free(rm_device_list); + + m_db->InitScalerTable(); + + m_is_db_created = 1; + + return RMS_OK; +} + +int CResourceManager::ReleaseResourcesOfPid(IN const int pid) +{ + std::map consumers = m_consumers->findConsumers(pid); + + for (auto const &it : consumers) { + CConsumer *consumer = it.second; + + SERVER_INFO("release resources of pid(%d)/cid(%d)", pid, consumer->GetId()); + + ReleaseResources(consumer->GetId()); + + m_consumers->RemoveConsumer(it.first); + delete consumer; + } + + return RMS_OK; +} + +int CResourceManager::UnregisterConsumer(IN const int consumer_id) +{ + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + + if (!consumer) { + SERVER_INFO("not existing consumer(%d)", consumer_id); + return RMS_ERROR; + } + + ReleaseResources(consumer_id); + + m_consumers->RemoveConsumer(consumer_id); + delete consumer; + + SERVER_INFO("consumer(%d) removed", consumer_id); + + return RMS_OK; +} + +void CResourceManager::ReleaseResources(const int consumer_id) +{ + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + if (!consumer) { + SERVER_ERR("Request for Deallocation - cid[%d] : Failed (Not registered consumer)", consumer_id); + return; + } + + std::set resources = consumer->GetResources(); + CResource *rsc = nullptr; + + for (auto const &it : resources) { + consumer->ReleaseResource(it); + SERVER_INFO("result (0) - con(%d:%s)/devId(%d)", consumer->GetId(), consumer->GetAppID().empty() ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str(), it); + + if (!(rsc = m_db->FindResource(it))) + continue; + rsc->RemoveConsumer(consumer->GetId(), true); + } +} + +int CResourceManager::ReleaseResources(IN const int consumer_id, IN const rms_requests_device_s *req) +{ + SERVER_INFO("Request for Deallocation - cid[%d] / requested[%d]", consumer_id, req->resources_num); + int device_id = 0; + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + + if (!consumer) { + SERVER_ERR("Request for Deallocation - cid[%d] : Failed (Not registered consumer)", consumer_id); + return RMS_ERROR; + } + + for (int i = 0; i < req->resources_num; i++) { + device_id = m_db->FindRealDeviceId(req->devices[i].device_id); + + if (consumer->ReleaseResource(device_id) != RMS_OK) { + SERVER_WARN("Request for Deallocation - cid[%d]/DevID[%d] / RealDevID[%d] Req State[%d] : Failed (Invalid device id)", + consumer_id, req->devices[i].device_id, req->devices[i].requested_state, device_id); + return RMS_ERROR; + } + + CResource *rsc = m_db->FindResource(device_id); + + if (!rsc) + continue; + + rsc->RemoveConsumer(consumer_id, false); + rsc->ResetBW(); + SERVER_INFO("result (0) - con(%d:%s) / devId(%d) / rId(%d)", + consumer_id, consumer->GetAppID().empty() ? consumer->GetCmdName().c_str():consumer->GetAppID().c_str(), req->devices[i].device_id, device_id); + } + + SERVER_WARN("Request for Deallocation - cid[%d] / requested #[%d] / REMAINING[%d] : SUCCESS", consumer_id, req->resources_num, consumer->GetResourceNum()); + return RMS_OK; +} + +bool CResourceManager::IsReclaimed(IN const int device_id, IN const int consumer_id) +{ + CResource *rsc = m_db->FindResource(device_id); + + if (!rsc) { + SERVER_ERR("invalid device_id (%d)", device_id); + return true; + } + + if (rsc->IsFreeState()) { + SERVER_INFO("FreeState [device id %d consumer id %d]", device_id, consumer_id); + return true; + } + + if (rsc->IsSharableState()) { + SERVER_INFO("ShareState [device id %d consumer id %d]", device_id, consumer_id); + return true; + } + + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + + if (!consumer) { + SERVER_INFO("not existing consumer(%d). maybe unregistered", consumer_id); + return true; + } + + if (rsc->IsSharableState() && !consumer->IsUsingResource(device_id)) + return true; + + SERVER_WARN("device_id %d consumer_id %d state %d", device_id, consumer_id, rsc->GetState()); + + return false; +} + +void CResourceManager::MakeResourceMapPerConsumer(std::multimap *device_id_to_consumer_id_map, std::map > *consumer_id_to_resource_set_map) +{ + assert(device_id_to_consumer_id_map); + assert(consumer_id_to_resource_set_map); + + for (auto const &it_ret : *device_id_to_consumer_id_map) { + int device_id = it_ret.first; + int consumer_id = it_ret.second; + + auto it_count = consumer_id_to_resource_set_map->find(consumer_id); + + if (it_count != consumer_id_to_resource_set_map->end()) { // Already consumer id exists in the map, just add device id into it + std::set rsc_count = (*it_count).second; + rsc_count.insert(device_id); + + consumer_id_to_resource_set_map->operator[](consumer_id) = rsc_count; + } else { + std::set rsc_count; + rsc_count.insert(device_id); + consumer_id_to_resource_set_map->insert(std::pair< int, std::set >(consumer_id, rsc_count)); + } + } +} + +void CResourceManager::MakeConsumerInfoToBeReturned(consumer_reclaim_s *return_consumer, std::map > *consumer_id_to_resource_set_map) +{ + assert(return_consumer); + assert(consumer_id_to_resource_set_map); + + return_consumer->ret_quantity = consumer_id_to_resource_set_map->size(); + return_consumer->consumer_info = (rms_consumer_tobe_returned_s*) calloc(1, sizeof(rms_consumer_tobe_returned_s) * return_consumer->ret_quantity); + + assert(return_consumer->consumer_info); + + int consumer_idx = 0; + + for (std::map< int, std::set >::iterator it = consumer_id_to_resource_set_map->begin(); it != consumer_id_to_resource_set_map->end(); it++, consumer_idx++) { + int consumer_id = (*it).first; + std::set resource_set = (*it).second; + + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + assert(consumer); + + int process_id = consumer->GetPid(); + int resources_num = consumer->GetResourceNum(); + + return_consumer->consumer_info[consumer_idx].consumer_id = consumer_id; + return_consumer->consumer_info[consumer_idx].process_id = process_id; + return_consumer->consumer_info[consumer_idx].n_conflicted = resource_set.size(); + return_consumer->consumer_info[consumer_idx].resources_num = resources_num; + return_consumer->consumer_info[consumer_idx].conflicted_resources = (rms_conflicted_resource_info_s*) calloc(1, sizeof(rms_conflicted_resource_info_s) * resource_set.size()); + + assert(return_consumer->consumer_info[consumer_idx].conflicted_resources); + + int resource_idx = 0; + + for (std::set::iterator it_rsc = resource_set.begin(); it_rsc != resource_set.end(); it_rsc++, resource_idx++) { + int rsc_id = *it_rsc; + CResource *rsc = m_db->FindResource(rsc_id); + assert(rsc); + return_consumer->consumer_info[consumer_idx].conflicted_resources[resource_idx].virtual_id = rsc->GetVirtualDeviceId(); + return_consumer->consumer_info[consumer_idx].conflicted_resources[resource_idx].device_id = rsc_id; + return_consumer->consumer_info[consumer_idx].conflicted_resources[resource_idx].category_id = rsc->GetCategoryType();; + } + } +} + +void CResourceManager::PrintConsumerInfoToBeReturned(consumer_reclaim_s *consumer_info) +{ + char name[RMS_NAME_BUF_SIZE] = {0,}; + + for (int i = 0; i < consumer_info->ret_quantity; i++) { + rms_get_cmd_name(consumer_info->consumer_info[i].process_id, name, sizeof(name)); + + SERVER_WARN("(%d) Retirable cid[%d]/pid[%ld:%s] - conflicted [%d] of requested[%d]", + i + 1, + consumer_info->consumer_info[i].consumer_id, + consumer_info->consumer_info[i].process_id, + name, + consumer_info->consumer_info[i].n_conflicted, + consumer_info->consumer_info[i].resources_num); + + for (int rsc_cnt = 0; rsc_cnt < consumer_info->consumer_info[i].n_conflicted; rsc_cnt++) { + SERVER_WARN("(%d) conflicted - DevID[%d] / VID[%d] / catid[%d:%s]", rsc_cnt+1, consumer_info->consumer_info[i].conflicted_resources[rsc_cnt].device_id, + consumer_info->consumer_info[i].conflicted_resources[rsc_cnt].virtual_id, + consumer_info->consumer_info[i].conflicted_resources[rsc_cnt].category_id, + rm_convert_category_enum_to_string(consumer_info->consumer_info[i].conflicted_resources[rsc_cnt].category_id)); + } + } +} + +int CResourceManager::FindReclaimableConsumers(rms_msg_request *req, consumer_reclaim_s *return_consumer, int *zone_id) +{ + assert(return_consumer); + + CRequester *requester = new CRequester(req); + std::vector requests; + MakeRequests(requester, req, &requests); + + std::multimap retirable_device_to_consumer; //device id, consumer id + + for (auto const &it : requests) { + CRequest *request = it; + CResourceCategory *category = m_db->FindResourceCategory(request->GetCategory()); + + if (!category) { + SERVER_ERR("not existing category(%d)", request->GetCategory()); + continue; + } + + category->GetRetirableConsumers(request, &retirable_device_to_consumer, &m_error_type); + + if (request->GetMultiviewZoneId() > 0) + *zone_id = request->GetMultiviewZoneId(); + } + + std::map< int, std::set > consumer_id_resource; //consumer id, rsc set + + MakeResourceMapPerConsumer(&retirable_device_to_consumer, &consumer_id_resource); + MakeConsumerInfoToBeReturned(return_consumer, &consumer_id_resource); + PrintConsumerInfoToBeReturned(return_consumer); + + std::for_each(requests.begin(), requests.end(), [](CRequest *request) { delete request; }); + delete requester; + + return RMS_OK; +} + +void categoryAvailableToUse(CRequest *request) +{ + CResourceCategory *category = CResourceDB::getInstance()->FindResourceCategory(request->GetCategory()); + + if (!category) { + request->SetResult(RMS_ERROR); + SERVER_ERR("not existing category (%d)", request->GetCategory()); + return; + } + + rms_rsc_category_e category_id = request->GetCategory(); + + if (!category->hasFreeStateResource()) { + request->SetResult(RMS_ERROR); + SERVER_ERR("all resources of category (%d) are being used", category_id); + return; + } + + if (!category->IsAvailableToUse((rms_requests_resource_state_e) request->GetState())) { + request->SetResult(RMS_ERROR); + SERVER_ERR("category (%d) is NOT available (HW constraint condition)", category_id); + return; + } + + request->SetResult(RMS_OK); + + SERVER_INFO("category (%d) is available", category_id); +} + +int CResourceManager::IsCategoryAvailableToUse(rms_msg_request *req, int *is_available) +{ + assert(req); + assert(is_available); + + CRequester *requester = new CRequester(req); + std::vector requests; + MakeRequests(requester, req, &requests); + + *is_available = 1; + + std::for_each(requests.begin(), requests.end(), categoryAvailableToUse); + std::for_each(requests.begin(), requests.end(), + [is_available](CRequest *request) { if (request->GetResult() != RMS_OK) *is_available = 0; }); + + std::for_each(requests.begin(), requests.end(), [](CRequest *request) { delete request; }); + delete requester; + + return RMS_OK; +} + +int CResourceManager::SetAppId(int consumer_id, const char *app_id) +{ + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + + if (!consumer) { + SERVER_ERR("Failed to set app_id : not existing consumer (%d)", consumer_id); + return RMS_ERROR; + } + + consumer->SetAppID(app_id); + + return RMS_OK; +} + +int CResourceManager::RegisterConsumer(int consumer_id, int process_id, const char *app_id, int main_priority, int sub_priority) +{ + CConsumer *consumer = m_consumers->findConsumer(consumer_id); + + if (consumer) { + SERVER_ERR("already registered consumer(%d)", consumer_id); + return RMS_ERROR; + } + + rms_consumer_s consumer_info; + consumer_info.consumer_id = consumer_id; + consumer_info.app_pid = 0; + consumer_info.priority.main = main_priority; + consumer_info.priority.sub = sub_priority; + consumer_info.process_id = process_id; + + snprintf(consumer_info.app_id, RMS_APPID_LENGTH, "%s", (app_id == NULL) ? "" : app_id); + + consumer = new CConsumer(&consumer_info); + + return (m_consumers->AddConsumer(consumer_id, consumer)) ? RMS_OK : RMS_ERROR; +} + +int CResourceManager::GetResourceState(int device_id) +{ + CResource *rsc = m_db->FindResource(device_id); + + if (!rsc) { + SERVER_ERR("device not found(%d)", device_id); + return -1; + } + + return (int) rsc->GetState(); +} + +int CResourceManager::FindDeviceId(int virtual_id) +{ + return m_db->FindRealDeviceId(virtual_id); +} + +int CResourceManager::SwapResources(int device_id_a, int device_id_b) +{ + CResource *rsc_a = m_db->FindResource(device_id_a); + CResource *rsc_b = m_db->FindResource(device_id_b); + + if (!rsc_a || !rsc_b) { + SERVER_ERR("resource not found (%d:%d)", device_id_a, device_id_b); + return -1; + } + + if (!rsc_a->IsScaler() || !rsc_b->IsScaler()) { + SERVER_ERR("swap not supported for (%d:%d)", device_id_a, device_id_b); + return -1; + } + + int result = m_db->SwapScaler(rsc_a->GetVirtualDeviceId(), rsc_b->GetVirtualDeviceId()); + if (result == 0) + m_db->UpdateVirtualScalerIds(); + + return result; +} + +int CResourceManager::RestoreResources(int category_id) +{ + int scaler_ids[4] = {RMS_DEVICE_SCALER, RMS_DEVICE_SCALER_SUB, RMS_DEVICE_SCALER_SUB2, RMS_DEVICE_SCALER_SUB3}; + bool swapped = false; + + if (category_id != RMS_CATEGORY_SCALER && category_id != RMS_CATEGORY_SCALER_MULTIVIEW) { + SERVER_ERR("restore not supported (%d)", category_id); + return -1; + } + + for (int i = 0; i < 4; i++) { + CResource *scaler = m_db->FindResource(scaler_ids[i]); + if (!scaler) { + SERVER_ERR("not existing scaler(%d)", scaler_ids[i]); + continue; + } + + SERVER_INFO("(%d) vid(%d)/dedicated(%d)", scaler_ids[i], scaler->GetVirtualDeviceId(), scaler->GetDedicatedVirtualDeviceId()); + if (scaler->GetVirtualDeviceId() != scaler->GetDedicatedVirtualDeviceId()) { + if (m_db->SwapScaler(scaler->GetDedicatedVirtualDeviceId(), scaler->GetVirtualDeviceId()) == 0) + swapped = true; + } + } + + if (swapped) + m_db->UpdateVirtualScalerIds(); + + return 0; +} + +int CResourceManager::GetResourceList(int category_id, GVariantBuilder *builder) +{ + CResourceCategory *category = m_db->FindResourceCategory((rms_rsc_category_e) category_id); + + if (!category) { + SERVER_ERR("not existing category (%d)", category_id); + return -1; + } + + std::map resource_map; + category->GetResources(&resource_map); + + SERVER_INFO("category(%d), n_rsc(%zu)", category_id, resource_map.size()); + + for (auto &it : resource_map) { + CResource *rsc = it.second; + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(rsc->GetFirstConsumer()); + g_variant_builder_add(builder, "(iissi)", rsc->GetDeviceID(), rsc->GetState(), rsc->GetDevicePath(), consumer? consumer->GetAppID().c_str() : "", consumer ? consumer->GetId() : 0); + } + + return 0; +} + +int CResourceManager::GetScalerState(int category_id, GVariantBuilder *builder) +{ + CResourceCategory *category = m_db->FindResourceCategory((rms_rsc_category_e) category_id); + if (!category) { + SERVER_ERR("not existing category (%d)", category_id); + return -1; + } + + int cid = -1; + std::string app_id; + CConsumer *consumer; + std::map resource_map; + category->GetResources(&resource_map); + + for (auto &it : resource_map) { + CResource *rsc = it.second; + cid = rsc->GetFirstConsumer(); + + consumer = CConsumerContainer::getInstance()->findConsumer(cid); + if (consumer) + app_id = (consumer->GetAppID().empty()) ? consumer->GetCmdName():consumer->GetAppID(); + + SERVER_INFO("(%d:%d:%d:%d:%d:%d:%s)", category_id, rsc->GetCurCategory(), rsc->GetDeviceID(), rsc->GetState(), cid, rsc->GetZoneId(), (app_id.empty() ? "" : app_id.c_str())); + + g_variant_builder_add(builder, "(iiiiis)", category_id, rsc->GetDeviceID(), rsc->GetState(), cid, rsc->GetZoneId(), (app_id.empty() ? "" : app_id.c_str())); + + app_id.erase(); + } + + return 0; +} + +int CResourceManager::GetScalerState(GVariantBuilder *builder) +{ + GetScalerState(RMS_CATEGORY_SCALER, builder); + GetScalerState(RMS_CATEGORY_SCALER_SUB, builder); + GetScalerState(RMS_CATEGORY_SCALER_SUB2, builder); + GetScalerState(RMS_CATEGORY_SCALER_SUB3, builder); + return 0; +} + +int CResourceManager::GetResourceCollectionState(int collection, GVariantBuilder *builder) +{ + CConsumer *consumer; + int cid = -1; + std::string app_id(""); + std::map resource_map; + + if (collection == RMS_RSC_COLLECTION_ACTIVE_VIDEO_DECODER) + m_db->FindActiveVideoDecoders(&resource_map); + else + m_db->FindMainResources(&resource_map); + + //SERVER_INFO("collection(%d), n_rsc(%d)", collection, resource_map.size()); + + for (auto &it : resource_map) { + CResource *rsc = it.second; + cid = rsc->GetFirstConsumer(); + consumer = CConsumerContainer::getInstance()->findConsumer(cid); + + if (consumer) + app_id = (consumer->GetAppID().empty()) ? consumer->GetCmdName() : consumer->GetAppID(); + + g_variant_builder_add(builder, "(isiiis)", rsc->GetDeviceID(), rsc->GetDevicePath(), rsc->GetState(), rsc->GetCurCategory(), cid, app_id.c_str()); + + app_id.clear(); + } + + return 0; +} + +int CResourceManager::GetActiveDecoderNum(void) +{ + return CResourceDB::getInstance()->GetActiveDecoderNum(); +} + +int CResourceManager::GetActiveAudioOut(int consumer_id) +{ + int result = RMS_AUDIO_OUT_NONE; + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id); + if (!consumer) { + SERVER_INFO("not existing consumer (%d)", consumer_id); + return RMS_AUDIO_OUT_NONE; + } + + std::set rscs = consumer->GetResources(); + for (auto &it : rscs) { + if (it == RMS_DEVICE_AUDIO_MAIN_OUT) + result = (result | RMS_AUDIO_OUT_MAIN); + if (it == RMS_DEVICE_AUDIO_SUB_OUT) + result = (result | RMS_AUDIO_OUT_SUB); + } + + return result; +} + +int CResourceManager::GetScalerHWId(int zone_id) +{ + CResource *rsc; + CResourceDB *db = CResourceDB::getInstance(); + std::map scalers; + db->GetScalerList(&scalers); + + for (auto &it: scalers) { + rsc = it.second; + + if (rsc->GetZoneId() == zone_id) + return db->ToScalerId(rsc->GetDeviceID()); + } + + SERVER_ERR("scaler not found at zone(%d)", zone_id); + return -1; +} + +int CResourceManager::GetZoneId(int device_id) +{ + CResource *rsc = m_db->FindResource(device_id); + if (!rsc) { + SERVER_ERR("device not found(%d)", device_id); + return -1; + } + + return rsc->GetZoneId(); +} + +void CResourceManager::ResetZoneIds(void) +{ + CResourceDB::getInstance()->ResetZoneIds(); +} + +void CResourceManager::UpdateZoneIds(std::string app_id, int zone_id) +{ + std::map consumers = CConsumerContainer::getInstance()->FindConsumers(app_id); + if (consumers.empty()) { + SERVER_INFO("consumer(%s) not found", app_id.c_str()); + return; + } + + CConsumer *consumer; + CResource *rsc; + CResourceDB *db = CResourceDB::getInstance(); + std::set rscs; + + for (auto &it : consumers) { + consumer = it.second; + rscs = consumer->GetResources(); + //SERVER_INFO("update zone ids (%s:%d:%d)", app_id.c_str(), consumer->GetId(), zone_id); + if (rscs.empty()) + continue; + for (auto &it_rsc : rscs) { + rsc = db->FindResource(it_rsc); + if (!rsc) + continue; + rsc->SetZoneId(zone_id); + } + rscs.clear(); + } +} diff --git a/src/manager/CResourceState.cpp b/src/manager/CResourceState.cpp new file mode 100644 index 0000000..f08c8a3 --- /dev/null +++ b/src/manager/CResourceState.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CResourceState::CResourceState(int device_id, int category_type, int consumer_id, int state, std::string app_id) +{ + m_device_id = device_id; + m_category_type = category_type; + m_consumer_id = consumer_id; + m_state = state; + m_app_id = app_id; +} \ No newline at end of file diff --git a/src/manager/CVideoController.cpp b/src/manager/CVideoController.cpp new file mode 100644 index 0000000..db9bfc0 --- /dev/null +++ b/src/manager/CVideoController.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#define LWIPC_WM_READY "/tmp/.wm_ready" +#define LWIPC_TIMEOUT_MS 10000 +#define LWIPC_SWAP_DONE "/tmp/.scaler_swap_done" +#define LWIPC_SWAP_DONE_TIMEOUT_MS 3000 +#define LWIPC_SWAP_DONE_TIMEOUT_DBG_MS 4000 +#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) + +CVideoController *CVideoController::m_instance = nullptr; + +static void registry_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) +{ + void **tizen_video_rsc = (void**)data; + + if (strncmp(interface, "tizen_video_rsc", sizeof("tizen_video_rsc"))) + return; + + SERVER_INFO("%p : %s", tizen_video_rsc, interface); + //*tizen_video_rsc = wl_registry_bind(wl_registry, id, &tizen_video_rsc_interface, 1); +} + +static void registry_handle_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) +{ + +} + +void CVideoController::WaylandDisplayCreate(void) +{ + SERVER_INFO("Create Start"); + + SERVER_INFO("%s is created", LWIPC_WM_READY); + m_wl_display = wl_display_connect(nullptr); + + if (!m_wl_display) { + SERVER_ERR("Failed to connect to the wayland display"); + return; + } + + m_wl_registry = wl_display_get_registry(m_wl_display); + wl_registry_add_listener(m_wl_registry, &m_registry_listener, &m_tizen_video_rsc); + SERVER_INFO("Add listener : %p", &m_tizen_video_rsc); + + wl_display_roundtrip(m_wl_display); + + if (!m_tizen_video_rsc) + SERVER_ERR("Failed to get tizen_video_rsc"); + + SERVER_INFO("Create Done"); +} + +void CVideoController::WaylandDisplayDestroy(void) +{ + if (m_tizen_video_rsc) { + //tizen_video_rsc_destroy(m_tizen_video_rsc); + m_tizen_video_rsc = nullptr; + } + + if (m_wl_registry) { + wl_registry_destroy(m_wl_registry); + m_wl_registry = nullptr; + } + + SERVER_INFO("Display disconnect"); + + if (m_wl_display) { + wl_display_roundtrip(m_wl_display); + wl_display_disconnect(m_wl_display); + m_wl_display = nullptr; + } + + SERVER_INFO("Destroy Done"); +} + +CVideoController::CVideoController(void) : m_wl_display(nullptr), m_wl_registry(nullptr), m_tizen_video_rsc(nullptr), m_waiting_thread(nullptr) +{ + m_registry_listener.global = registry_handle_global; + m_registry_listener.global_remove = registry_handle_global_remove; + WaylandDisplayCreate(); + m_lock_ctr = CLockController::GetInstance(); + + SERVER_INFO("Initialize Done"); +} + +CVideoController::~CVideoController(void) +{ + WaylandDisplayDestroy(); + SERVER_INFO("Finalize Done"); +} + +CVideoController *CVideoController::GetInstance(void) +{ + if (m_instance == nullptr) + { + m_instance = new(std::nothrow) CVideoController(); + assert(m_instance); + } + + return m_instance; +} + +void CVideoController::UpdateVirtualScalerIds(std::map scaler_id_map) +{ + struct wl_array mapping_list; + scaler_id_pair_t *scaler_id_pair = NULL; + + wl_array_init(&mapping_list); + SERVER_ERR("Update virtual scaler ids"); + + for (auto it = scaler_id_map.begin(); it != scaler_id_map.end(); it++) { + scaler_id_pair = (scaler_id_pair_t*)wl_array_add(&mapping_list, sizeof(scaler_id_pair_t)); + scaler_id_pair->virtual_scaler_id = it->first; + scaler_id_pair->scaler_id = it->second; + SERVER_ERR("scaler(%d:%d)", it->first, it->second); + } + + //tizen_video_rsc_map_scaler_id(m_tizen_video_rsc, &mapping_list); + + wl_display_roundtrip(m_wl_display); + wl_array_release(&mapping_list); + + RunWaitingThread(); +} + +gpointer CVideoController::WaitingThread(gpointer data) +{ + assert(data); + CVideoController *ctr = (CVideoController*) data; + + ctr->m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); + ctr->m_waiting_thread = nullptr; + return 0; +} + +void CVideoController::RunWaitingThread(void) +{ + if (m_waiting_thread) + { + SERVER_ERR("already created"); + return; + } + + m_lock_ctr->Lock(ResourceType::VIDEO_SCALER); + + m_waiting_thread = g_thread_new("waiting_swap_done", WaitingThread, this); + if (m_waiting_thread == nullptr) { + m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); + SERVER_ERR("failed to create waiting_swap_done thread"); + return; + } + + SERVER_ERR("waiting_swap_done thread created"); +} diff --git a/src/manager/CVirtualResource.cpp b/src/manager/CVirtualResource.cpp new file mode 100644 index 0000000..c7b2aba --- /dev/null +++ b/src/manager/CVirtualResource.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CVirtualResource::CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set dependent, bool is_main_device, const char *audio_codec, int category_class) +:m_vir_rsc_id(virtual_device_id), m_category_type(category_type), m_vir_rsc_bw(bw), m_is_main_device(is_main_device), m_category_class(category_class) +{ + m_mem_clusters = dependent; + + if (audio_codec) + m_audio_codec.assign(audio_codec); +} + +void CVirtualResource::SetResource(CResource *resource) +{ + m_rsc = resource; +} diff --git a/src/manager/dependence/CAudioCodec.cpp b/src/manager/dependence/CAudioCodec.cpp new file mode 100644 index 0000000..15dd2b8 --- /dev/null +++ b/src/manager/dependence/CAudioCodec.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CAudioCodec::CAudioCodec(const char * name) +:m_ref_count(0), m_ref_count_max(0) +{ + m_name.assign(name); +} + +CAudioCodec::~CAudioCodec() +{ +} + +void CAudioCodec::increaseRef(int device_id, int consumer_id) +{ + if (m_ref_count_max == 0) + return; + + if (m_ref_count >= m_ref_count_max) { + SERVER_ERR("(%s) can't increase ref count (%d, %d) by %d", m_name.c_str(), m_ref_count, m_ref_count_max, consumer_id); + return; + } + + m_ref_count++; + + auto it = m_consumers.find(consumer_id); + + m_resources.insert(std::pair(device_id, consumer_id)); + + if (it == m_consumers.end()) { + m_consumers.insert(std::pair(consumer_id, 1)); + return; + } + + (*it).second = ++it->second ; +} + +void CAudioCodec::decreaseRef(int device_id, int consumer_id) +{ + if (m_ref_count_max == 0) + return; + + if (m_ref_count <= 0) { + SERVER_ERR("(%s) can't decrease ref count (%d, %d) by %d", m_name.c_str(), m_ref_count, m_ref_count_max, consumer_id); + return; + } + + auto it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) { + SERVER_ERR("not registered consumer(%d)", consumer_id); + return; + } + + m_resources.erase(device_id); + + m_ref_count--; + + if (it->second <= 1) { + m_consumers.erase(consumer_id); + return; + } + + (*it).second = --it->second; +} + +void CAudioCodec::increaseMaxRef(void) +{ + m_ref_count_max++; +} + +bool CAudioCodec::isAvailableToUse(void) +{ + if (isUnknownCodec()) + return true; + + SERVER_INFO("%s > cur(%d), max(%d)", m_name.c_str(), m_ref_count, m_ref_count_max); + + return (m_ref_count < m_ref_count_max); +} + +std::set CAudioCodec::getResourcesOfConsumer(int consumer_id) +{ + std::set resources; + + for (auto const &it : m_resources) { + if (it.second == consumer_id) + resources.insert(it.first); + } + + return resources; +} diff --git a/src/manager/dependence/CAudioCodecCollection.cpp b/src/manager/dependence/CAudioCodecCollection.cpp new file mode 100644 index 0000000..5d73640 --- /dev/null +++ b/src/manager/dependence/CAudioCodecCollection.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +CAudioCodecCollection *CAudioCodecCollection::m_instance = NULL; + +CAudioCodecCollection::CAudioCodecCollection() +{ + +} + +CAudioCodecCollection *CAudioCodecCollection::getInstance(void) +{ + if (!m_instance) + m_instance = new CAudioCodecCollection(); + + return m_instance; +} + +CAudioCodecCollection::~CAudioCodecCollection() +{ +} + +CAudioCodec *CAudioCodecCollection::findAudioCodec(std::string name) +{ + auto it = m_audio_codecs.find(name); + + return (it == m_audio_codecs.end()) ? NULL : it->second; +} + +void CAudioCodecCollection::registerAudioCodec(const char *name, int count) +{ + if (!name) + return; + + CAudioCodec *audio_codec = findAudioCodec(name); + + if (!audio_codec) { + audio_codec = new CAudioCodec(name); + m_audio_codecs.insert(std::pair(std::string(name), audio_codec)); + } + + if (count > 0) + audio_codec->increaseMaxRef(); +} diff --git a/src/manager/dependence/CBandwidth.cpp b/src/manager/dependence/CBandwidth.cpp new file mode 100644 index 0000000..c9535df --- /dev/null +++ b/src/manager/dependence/CBandwidth.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +CBandwidth *CBandwidth::m_instance = NULL; + +CBandwidth *CBandwidth::GetInstance(void) +{ + if (!m_instance) + { + m_instance = new CBandwidth(); + } + + return m_instance; +} + +void CBandwidth::AddConsumerNDec(int device_id, int consumer_id, int category_id) +{ + auto it = m_ndec_consumers.find(category_id); + if (it == m_ndec_consumers.end()) + { + std::map consumers; + consumers.insert(std::pair(device_id, consumer_id)); + m_ndec_consumers.insert(std::pair>(category_id, consumers)); + } + else + { + std::map *consumers = &it->second; + consumers->insert(std::pair(device_id, consumer_id)); + } +} + +void CBandwidth::RemoveConsumerNDec(int device_id, int category_id) +{ + auto it = m_ndec_consumers.find(category_id); + if (it == m_ndec_consumers.end()) + return; + + it->second.erase(device_id); +} + +void CBandwidth::GetConsumersNDec(int category_id, std::map *consumers) +{ + auto it = m_ndec_consumers.find(category_id); + if (it == m_ndec_consumers.end()) + return; + + consumers->insert(it->second.begin(), it->second.end()); +} + +void CBandwidth::AddConsumer(int device_id, int consumer_id, int category_id, int category_class) +{ + m_consumers.insert(std::pair(device_id, consumer_id)); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + AddConsumerNDec(device_id, consumer_id, category_id); +} + +void CBandwidth::RemoveConsumer(int device_id, int category_id, int category_class) +{ + auto it = m_consumers.find(device_id); + if (it == m_consumers.end()) + return; + + m_consumers.erase(device_id); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + RemoveConsumerNDec(device_id, category_id); +} + +int CBandwidth::GetNConsumersNDec(int category_id) +{ + auto it = m_ndec_consumers.find(category_id); + if (it == m_ndec_consumers.end()) + return 0; + + return it->second.size(); +} + +void CBandwidth::Increase(unsigned int bw, int category_id, int category_class, int device_id) +{ + if ((category_class == RMS_CATEGORY_CLASS_N_DECODING) && IncludeSameDeviceGroup(category_id, device_id)) + return; + + m_avail += bw; + m_avail = (m_avail > m_max) ? m_max : m_avail; +} + +void CBandwidth::Decrease(unsigned int bw, int category_id, int category_class, int device_id) +{ + if (category_class == RMS_CATEGORY_CLASS_N_DECODING && IncludeSameDeviceGroup(category_id, device_id)) + return; + + m_avail -= bw; +} + +bool CBandwidth::IncludeSameDeviceGroup(int category_id, int device_id) +{ + if (GetNConsumersNDec(category_id) == 0) + return false; + + CResource *c_rsc; + CVirtualResource *c_vrsc; + std::set c_mc; + + CResourceDB *db = CResourceDB::getInstance(); + CResource *u_rsc = db->FindResource(device_id); + CVirtualResource *u_vrsc = db->FindVirtualResource(u_rsc->GetVirtualResourceID()); + + std::set u_mc = u_vrsc->GetMemClusters(); + + std::map consumers; // device_id, consumer_id + GetConsumersNDec(category_id, &consumers); + + for (auto const &it : consumers) + { + c_rsc = db->FindResource(it.first); + c_vrsc = db->FindVirtualResource(c_rsc->GetVirtualResourceID()); + c_mc = c_vrsc->GetMemClusters(); + + if (c_rsc->GetDeviceID() == u_rsc->GetDeviceID()) + continue; + + if (IsSameMemClusters(c_mc, u_mc)) + { + SERVER_INFO("same mc (%d = %d) found", device_id, it.first); + return true; + } + } + + return false; +} + +bool CBandwidth::IsSameMemClusters(std::set c_mc, std::set u_mc) +{ + if (c_mc.size() != u_mc.size()) + return false; + + for (auto const &it : u_mc) + { + if (c_mc.find(it) == c_mc.end()) + return false; + } + return true; +} diff --git a/src/manager/dependence/CDependencyController.cpp b/src/manager/dependence/CDependencyController.cpp new file mode 100644 index 0000000..43354b0 --- /dev/null +++ b/src/manager/dependence/CDependencyController.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +static rms_mixing_mode_e supported_mixing_modes[] = +{ + RMS_MIXING_MODE_DEFAULT, + RMS_MIXING_MODE_MULTIVIEW, + RMS_MIXING_MODE_INTERACTION_SOUND +}; + +CDependencyController *CDependencyController::m_instance = NULL; + +CDependencyController::CDependencyController() +{ + registerMixingModes(); + m_cur_mixing_mode = NULL; +} + +CDependencyController *CDependencyController::getInstance(void) +{ + if (!m_instance) + m_instance = new CDependencyController(); + + return m_instance; +} + +CDependencyController::~CDependencyController() +{ +} + +void CDependencyController::registerMixingModes(void) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(supported_mixing_modes); i++) { + CMixingMode *mixing_mode = new CMixingMode(supported_mixing_modes[i]); + m_mixing_modes.insert(std::pair(supported_mixing_modes[i], mixing_mode)); + } +} + +bool CDependencyController::IsRegisteredMemCluster(unsigned int id) +{ + auto it = m_mem_clusters.find(id); + return (it != m_mem_clusters.end()); +} + +CMemCluster *CDependencyController::findMemCluster(unsigned int id) +{ + auto it = m_mem_clusters.find(id); + + if (it == m_mem_clusters.end()) + { + SERVER_ERR("not existing mem cluster(%d)", id); + return NULL; + } + + return it->second; +} + +void CDependencyController::RegisterMemCluster(unsigned int id) +{ + if (IsRegisteredMemCluster(id)) + return; + + CMemCluster *mc = new CMemCluster(id); + SERVER_INFO("register mem cluster (%d)", id); + m_mem_clusters.insert(std::pair(id, mc)); +} + +bool CDependencyController::isAvailableMemClusters(std::set mc_ids) +{ + CMemCluster *mc = NULL; + + for (auto it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + if (mc->IsUsed()) { + SERVER_INFO("mem cluster (%d) is being used", mc->GetId()); + return false; + } + } + + return true; +} + +bool CDependencyController::isAvailableMemClusters(std::set mc_ids, std::string app_id) +{ + CMemCluster *mc = NULL; + + for (auto it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + if (mc->IsUsed() && !mc->IsUsedBy(app_id)) { + SERVER_INFO("mem cluster (%d) is being used", mc->GetId()); + return false; + } + } + + return true; +} + +bool CDependencyController::isAvailableMemClusters(std::set mc_ids, int category_class, int category_id) +{ + CMemCluster *mc = NULL; + + for (auto it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + if (!mc->IsUsed()) + continue; + + if (mc->GetCategoryClass() != category_class) { + SERVER_INFO("mem cluster (%d) is in use, mc_class(%d)/category(%d)", mc->GetId(), mc->GetCategoryClass(), category_class); + return false; + } + + if (mc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING && (mc->GetCategoryId() != category_id)) { + SERVER_INFO("mem cluster (%d) is in use, mc_category(%d)/category(%d)", mc->GetId(), mc->GetCategoryId(), category_id); + return false; + } + } + + return true; +} + +bool CDependencyController::isSharableMemClusters(std::set mc_ids, int device_id) +{ + CMemCluster *mc = NULL; + + for (auto it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + if (!mc->IsSharable(device_id)) { + SERVER_INFO("mem cluster (%d) is not sharable", mc->GetId()); + return false; + } + } + + return true; +} + + +bool CDependencyController::canReclaimMemClusters(std::set mc_ids, int consumer_id) +{ + CMemCluster *mc = NULL; + + for (auto const &it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + std::set consumers = mc->GetConsumers(); + + for (auto const &it_consumer : consumers) { + if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) { + SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer); + return false; + } + } + } + + return true; +} + +bool CDependencyController::canReclaimMemClusters(std::set mc_ids, int consumer_id, std::string app_id) +{ + CMemCluster *mc = NULL; + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *consumer = NULL; + + for (auto const &it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return false; + } + + std::set consumers = mc->GetConsumers(); + + for (auto const &it_consumer : consumers) { + consumer = c_container->findConsumer(it_consumer); + if (consumer) { + if (!consumer->GetAppID().compare(app_id)) { + SERVER_INFO("skip to check priority against same app (%s:%s)", consumer->GetAppID().c_str(), app_id.c_str()); + continue; + } + } + + if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) { + SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer); + return false; + } + } + } + + return true; +} + +int CDependencyController::getReclaimableMemClusterConsumers(std::set mc_ids, int consumer_id, std::multimap* reclaimables) +{ + CMemCluster *mc = NULL; + + for (auto const &it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return RMS_ERROR; + } + + std::set consumers = mc->GetConsumers(); + + for (auto const &it_consumer : consumers) { + if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) { + SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer); + return RMS_ERROR; + } + + std::set device_ids = mc->GetAssignedDeviceId(it_consumer); + for (auto const &it_dev_id : device_ids) { + SERVER_INFO("[mc:%d] add (%d:%d)", mc->GetId(), it_dev_id, it_consumer); + reclaimables->insert(std::pair(it_dev_id, it_consumer)); + } + } + } + + return RMS_OK; +} + +int CDependencyController::getReclaimableMemClusterConsumers(std::set mc_ids, int consumer_id, std::multimap* reclaimables, std::string app_id) +{ + CMemCluster *mc = NULL; + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *consumer = NULL; + + for (auto const &it : mc_ids) { + mc = findMemCluster(it); + if (!mc) { + SERVER_INFO("mem cluster NULL"); + return RMS_ERROR; + } + + std::set consumers = mc->GetConsumers(); + + for (auto const &it_consumer : consumers) { + consumer = c_container->findConsumer(it_consumer); + if (!consumer->GetAppID().compare(app_id)) { + SERVER_INFO("skip to check priority against same app (%s:%s)", consumer->GetAppID().c_str(), app_id.c_str()); + continue; + } + + if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) { + SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer); + return RMS_ERROR; + } + + std::set device_ids = mc->GetAssignedDeviceId(it_consumer); + for (auto const &it_dev_id : device_ids) { + SERVER_INFO("[mc:%d] add (%d:%d)", mc->GetId(), it_dev_id, it_consumer); + reclaimables->insert(std::pair(it_dev_id, it_consumer)); + } + } + } + + return RMS_OK; +} + +void CDependencyController::SwapConsumers(int device_id_a, std::set consumers_a, int device_id_b, std::set consumers_b) +{ + ClearMemClusterConsumer(device_id_a); + ClearMemClusterConsumer(device_id_b); + + for (auto const &it : consumers_a) + addMemClusterConsumer(device_id_b, it); + + for (auto const &it : consumers_b) + addMemClusterConsumer(device_id_a, it); +} + +void CDependencyController::addMemClusterConsumer(int device_id, int consumer_id) +{ + CMemCluster *mc = NULL; + CResource *rsc = CResourceDB::getInstance()->FindResource(device_id); + + if (!rsc) + return; + + if (rsc->GetCurCategory() == RMS_CATEGORY_VIDEO_ENCODER_EXCLUSIVE) + return; + + int category_class = rsc->GetCategoryClass(); + + std::set mc_mc_ids = rsc->GetMemClusters(); + for (auto const &it : mc_mc_ids) { + mc = findMemCluster(it); + if (!mc) + continue; + + mc->AddConsumer(consumer_id, device_id, category_class, rsc->GetCurCategory()); + SERVER_INFO("add consumer(%d) to mem_cluster(%d)/class(%d)", consumer_id, mc->GetId(), category_class); + } +} + +void CDependencyController::removeMemClusterConsumer(int device_id, int consumer_id) +{ + CMemCluster *mc = NULL; + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + + if (!resource) + return; + + std::set mc_mc_ids = resource->GetMemClusters(); + + for (auto const &it : mc_mc_ids) { + mc = findMemCluster(it); + if (!mc) + continue; + + mc->RemoveConsumer(consumer_id, device_id); + SERVER_INFO("remove consumer(%d) from mem_cluster(%d)", consumer_id, mc->GetId()); + } +} + +void CDependencyController::ClearMemClusterConsumer(int device_id) +{ + CMemCluster *mc = NULL; + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + if (!resource) + return; + + std::set mc_mc_ids = resource->GetMemClusters(); + + for (auto const &it : mc_mc_ids) { + mc = findMemCluster(it); + if (!mc) + continue; + + mc->ClearConsumers(); + SERVER_INFO("clear consumers from mem_cluster(%d)", mc->GetId()); + } +} + +void CDependencyController::Update(resource_update_type_e type, const int device_id, const int consumer_id) +{ + switch (type) { + case UPDATED_BY_ALLOC: + addMemClusterConsumer(device_id, consumer_id); + addAudioCodecConsumer(device_id, consumer_id); + setCurMixingMode(device_id, consumer_id); + break; + case UPDATED_BY_RELEASE: + removeMemClusterConsumer(device_id, consumer_id); + removeAudioCodecConsumer(device_id, consumer_id); + resetCurMixingMode(device_id, consumer_id); + break; + default: + SERVER_ERR("unexpected update type (%d)", type); + break; + } +} + +void CDependencyController::addAudioCodecConsumer(int device_id, int consumer_id) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + + if (!resource->IsAudioDevice()) + return; + + m_acodec_consumers.insert(std::pair (device_id, consumer_id)); + + std::string codec_name = resource->GetAudioCodec(); + CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name); + + codec->increaseRef(device_id, consumer_id); +} + +void CDependencyController::removeAudioCodecConsumer(int device_id, int consumer_id) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + + if (!resource->IsAudioDevice()) + return; + + m_acodec_consumers.erase(device_id); + + std::string codec_name = resource->GetAudioCodec(); + CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name); + + codec->decreaseRef(device_id, consumer_id); +} + +CMixingMode *CDependencyController::findMixingMode(rms_mixing_mode_e mode) +{ + auto it = m_mixing_modes.find(mode); + + return (it == m_mixing_modes.end()) ? NULL : it->second; +} + +void CDependencyController::setCurMixingMode(int device_id, int consumer_id) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + + if (!resource->IsAudioDevice()) + return; + + rms_mixing_mode_e mode_id = resource->GetMixingMode(); + CMixingMode *mode = findMixingMode(mode_id); + + if (!mode) { + SERVER_ERR("undefined mixing mode (%d)", mode_id); + return; + } + + mode->AddConsumer(device_id, consumer_id); + + m_cur_mixing_mode = mode; +} + +void CDependencyController::resetCurMixingMode(int device_id, int consumer_id) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + + if (!resource->IsAudioDevice()) + return; + + rms_mixing_mode_e mode_id = resource->GetMixingMode(); + CMixingMode *mode = findMixingMode(mode_id); + + if (!mode) { + SERVER_ERR("undefined mixing mode (%d)", mode_id); + return; + } + + if (mode->RemoveConsumer(device_id, consumer_id) > 0) + return; + + m_cur_mixing_mode = NULL; +} + +bool CDependencyController::isAvailableAudioCodec(std::string name) +{ + SERVER_DBG("cur(%zu)/max(%d)", m_acodec_consumers.size(), m_acodec_ref_count_max); + return (m_acodec_consumers.size() >= m_acodec_ref_count_max); //??? +} + +std::map> CDependencyController::getAudioCodecConsumers(void) +{ + std::map> consumers; + + for (auto const &it : m_acodec_consumers) { + CResource *rsc = CResourceDB::getInstance()->FindResource(it.first); + consumers.insert(std::pair>(rsc->GetAllocatedTime(), std::make_pair(it.first, it.second))); + } + + return consumers; +} diff --git a/src/manager/dependence/CMemCluster.cpp b/src/manager/dependence/CMemCluster.cpp new file mode 100644 index 0000000..0649621 --- /dev/null +++ b/src/manager/dependence/CMemCluster.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "CMemCluster.h" +#include "CConsumerContainer.h" +#include "CConsumer.h" + +CMemCluster::CMemCluster(unsigned int id) +{ + m_id = id; + m_category_class = 0; + m_category_id = 0; +} + +CMemCluster::~CMemCluster() +{ +} + +bool CMemCluster::IsUsed(void) +{ + return (m_consumers.size() > 0); +} + +bool CMemCluster::IsUsedBy(std::string app_id) +{ + CConsumerContainer *cc = CConsumerContainer::getInstance(); + CConsumer *c = NULL; + bool result = false; + + if (m_consumers.size() == 0) + return false; + + for (auto it : m_consumers) { + c = cc->findConsumer(it.first); + if (!c) + continue; + if (!c->GetAppID().compare(app_id)) { + SERVER_INFO("mc(%d) is used by (%s)", m_id, app_id.c_str()); + return true; + } + } + + return result; +} + +bool CMemCluster::IsSharable(int device_id) +{ + if (m_consumers.size() == 0) + return true; + + for (auto it : m_consumers) { + auto it_dev_id = it.second.find(device_id); + if (it_dev_id != it.second.end()) + return true; + } + return false; +} + +void CMemCluster::AddConsumer(int consumer_id, int device_id, int category_class, int category_id) +{ + auto it = m_consumers.find(consumer_id); + if (it == m_consumers.end()) { + std::set device_ids; + device_ids.insert(device_id); + m_consumers.insert(std::pair>(consumer_id, device_ids)); + m_category_class = category_class; + m_category_id = category_id; + } else { + std::set &pdevice_ids = it->second; + pdevice_ids.insert(device_id); + } +} + +void CMemCluster::RemoveConsumer(int consumer_id, int device_id) +{ + auto it = m_consumers.find(consumer_id); + if (it == m_consumers.end()) + return; + + std::set &device_ids = it->second; + + auto id_it = device_ids.find(device_id); + if (id_it == device_ids.end()) + return; + + device_ids.erase(device_id); + if (device_ids.empty()) + m_consumers.erase(consumer_id); + + if (m_consumers.empty()) { + m_category_class = 0; + m_category_id = 0; + } +} + +std::set CMemCluster::GetConsumers(void) +{ + std::set consumers; + + for (auto it : m_consumers) + consumers.insert(it.first); + + return consumers; +} + +void CMemCluster::ClearConsumers(void) +{ + for (auto &it : m_consumers) { + std::set &id_it = it.second; + id_it.clear(); + } + m_consumers.clear(); +} + +std::set CMemCluster::GetAssignedDeviceId(int consumer_id) +{ + std::set device_ids; + auto it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) + return device_ids; + + device_ids.insert(it->second.begin(), it->second.end()); + + return device_ids; +} diff --git a/src/manager/dependence/CMixingMode.cpp b/src/manager/dependence/CMixingMode.cpp new file mode 100644 index 0000000..131bd5e --- /dev/null +++ b/src/manager/dependence/CMixingMode.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +int CMixingMode::AddConsumer(int device_id, int consumer_id) +{ + auto it = m_consumers.find(device_id); + + if (it != m_consumers.end()) { + SERVER_ERR("already registered device(%d) by (%d)", device_id, it->second); + return m_consumers.size(); + } + + SERVER_INFO("add consumer(%d:%d) to mode(%d)", consumer_id, device_id, m_mode); + m_consumers.insert(std::pair(device_id, consumer_id)); + + return m_consumers.size(); +} + +int CMixingMode::RemoveConsumer(int device_id, int consumer_id) +{ + auto it = m_consumers.find(device_id); + + if (it == m_consumers.end()) + return m_consumers.size(); + + SERVER_INFO("remove consumer(%d:%d) from mode(%d)", consumer_id, device_id, m_mode); + + m_consumers.erase(device_id); + + return m_consumers.size(); +} + diff --git a/src/manager/strategy/CAllocateModeStrategyProvider.cpp b/src/manager/strategy/CAllocateModeStrategyProvider.cpp new file mode 100644 index 0000000..9a715a3 --- /dev/null +++ b/src/manager/strategy/CAllocateModeStrategyProvider.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +enum { + INIT_MODE = -1, + NORMAL_MODE, + PREFERENCE_MODE, + INVALID_MODE +}; + +CAllocateModeStrategyProvider *CAllocateModeStrategyProvider::m_instance = NULL; + +CAllocateModeStrategyProvider::CAllocateModeStrategyProvider() +{ +} + +CAllocateModeStrategyProvider::~CAllocateModeStrategyProvider() +{ +} + + +CAllocateModeStrategyProvider *CAllocateModeStrategyProvider::getInstance() +{ + if (!m_instance) + m_instance = new CAllocateModeStrategyProvider(); + + return m_instance; +} + +int CAllocateModeStrategyProvider::getAllocateMode(rms_msg_request *req) +{ + int mode = INIT_MODE; + + for (int i = 0; i < req->request_num; i++) { + if (req->state[i] == RMS_STATE_EXCLUSIVE_PREFERENCE) { + if (mode == INIT_MODE) { + mode = PREFERENCE_MODE; + } else if (mode == NORMAL_MODE) { + mode = INVALID_MODE; + break; + } + } else { + if (mode == INIT_MODE) { + mode = NORMAL_MODE; + } else if (mode == PREFERENCE_MODE) { + mode = INVALID_MODE; + break; + } + } + } + + return mode; +} + +CAllocateModeStrategy *CAllocateModeStrategyProvider::GetStrategy(rms_msg_request *req) +{ + CAllocateModeStrategy *strategy = NULL; + + switch (getAllocateMode(req)) { + case NORMAL_MODE: + strategy = new CNormalModeStrategy(); + break; + case PREFERENCE_MODE: + strategy = new CPreferenceModeStrategy(); + break; + default: + strategy = new CInvalidModeStrategy(); + break; + } + + return strategy; +} diff --git a/src/manager/strategy/CAllocateStrategy.cpp b/src/manager/strategy/CAllocateStrategy.cpp new file mode 100644 index 0000000..621605b --- /dev/null +++ b/src/manager/strategy/CAllocateStrategy.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void CAllocateStrategy::ExcludeResources(std::map vresources, std::map* filtered_resources, CRequest *req) +{ + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (req->IsMainDeviceRequest() && !vresource->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && vresource->IsMainDevice()) + continue; + if (req->IsAIDeviceRequest() && !vresource->IsAIDevice()) + continue; + if (req->IsRequestByDevice() && resource->GetDeviceID() != req->GetDevice()) + continue; + if (req->GetState() == RMS_STATE_SHARABLE && !resource->IsSharableDevice()) + continue; + if (req->GetState() != RMS_STATE_SHARABLE && resource->IsSharableDevice()) + continue; + + filtered_resources->insert(std::pair(it.first, it.second)); + } +} + +void CAllocateStrategy::ExcludeResources(std::multimap vresources, std::multimap* filtered_resources, CRequest *req) +{ + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + + if (req->IsMainDeviceRequest() && !vresource->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && vresource->IsMainDevice()) + continue; + if (req->IsAIDeviceRequest() && !vresource->IsAIDevice()) + continue; + + filtered_resources->insert(std::pair(it.first, it.second)); + } +} + +void CAllocateStrategy::updateReasonByResourceState(int device_id, CRequest *req) +{ + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + bool low_priority_consumer_using = (CPriority::compareCurConsumers(device_id, req->getRequester()->getHandle()) == HIGH_PRIORITY); + + if (low_priority_consumer_using) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + SERVER_INFO("RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER"); + } else { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + SERVER_INFO("RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS"); + } +} + +void CAllocateStrategy::updateReasonBySharableCount(int device_id, CRequest *req) +{ + if (req->GetState() != RMS_STATE_SHARABLE) + return; + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + bool low_priority_consumer_using = (CPriority::compareCurConsumers(device_id, req->getRequester()->getHandle()) == HIGH_PRIORITY); + + if (low_priority_consumer_using) + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + else + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +int CAllocateStrategy::GetReclaimedBW(std::multimap *retirables) +{ + CResourceDB *db = CResourceDB::getInstance(); + std::set rsc_ids; + int bw = 0; + + ExcludeDuplicatedNDecoders(retirables, &rsc_ids); + + for (auto const &it : rsc_ids) { + CResource *rsc = db->FindResource(it); + if (!rsc) + continue; + bw += rsc->GetBW(); + } + + //SERVER_INFO("reclaimed bw(%d) from (%d)", bw, retirables->size()); + return bw; +} + +void CAllocateStrategy::ExcludeDuplicatedNDecoders(std::multimap *retirables, std::set *excluded) +{ + assert(retirables); + assert(excluded); + std::map rscs_by_category; //category id, device_id + CResourceDB *db = CResourceDB::getInstance(); + + for (auto &it : *retirables) { + CResource *rsc = db->FindResource(it.first); + if (!rsc) + continue; + if (rsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) { + //SERVER_INFO("insert (%d:%d)", rsc->GetCurCategory(), it.first); + rscs_by_category.insert(std::pair(rsc->GetCurCategory(), it.first)); + } else { + //SERVER_INFO("insert (%d)", it.first); + excluded->insert(it.first); + } + } + + for (auto &itn : rscs_by_category) { + //SERVER_INFO("insert (%d)", itn.second); + excluded->insert(itn.second); + } +} diff --git a/src/manager/strategy/CAllocateStrategyProvider.cpp b/src/manager/strategy/CAllocateStrategyProvider.cpp new file mode 100644 index 0000000..840a8a2 --- /dev/null +++ b/src/manager/strategy/CAllocateStrategyProvider.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +CAllocateStrategyProvider *CAllocateStrategyProvider::m_instance = NULL; + +CAllocateStrategyProvider::CAllocateStrategyProvider() +{ +} + +bool CAllocateStrategyProvider::IsAudioDecoderCategory(rms_rsc_category_e category) +{ + bool result = false; + + switch (category) { + case RMS_CATEGORY_AUDIO_DECODER: + case RMS_CATEGORY_AUDIO_DECODER_SUB: + case RMS_CATEGORY_AUDIO_DECODER_PRIMARY: + case RMS_CATEGORY_AUDIO_DECODER_ANY: + result = true; + break; + default: + result = false; + break; + } + + if (category > RMS_CATEGORY_AUDIO_DECODER_OPTION && category < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX) + result = true; + + return result; +} + +bool CAllocateStrategyProvider::IsVideoDecoderCategory(rms_rsc_category_e category) +{ + bool result = false; + + switch (category) { + case RMS_CATEGORY_VIDEO_DECODER: + case RMS_CATEGORY_VIDEO_DECODER_SUB: + case RMS_CATEGORY_JPEG_DECODER: + case RMS_CATEGORY_MJPEG_DECODER: + case RMS_CATEGORY_JPEG_DECODER_FHD: + case RMS_CATEGORY_JPEG_DECODER_UHD: + case RMS_CATEGORY_JPEG_DECODER_8K: + case RMS_CATEGORY_MJPEG_DECODER_FHD: + case RMS_CATEGORY_MJPEG_DECODER_UHD: + case RMS_CATEGORY_MJPEG_DECODER_8K: + case RMS_CATEGORY_HEIC_DECODER: + result = true; + break; + default: + result = false; + break; + } + + if (category > RMS_CATEGORY_VIDEO_DECODER_OPTION && category < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX) + result = true; + + return result; +} + +bool CAllocateStrategyProvider::IsNDecordingVideoDecoderCategory(int category_class) +{ + return (category_class == RMS_CATEGORY_CLASS_N_DECODING); +} + +bool CAllocateStrategyProvider::IsBGScalerCategory(rms_rsc_category_e category) +{ + return (category == RMS_CATEGORY_SCALER_BG); +} + +bool CAllocateStrategyProvider::IsMultiviewScalerCategory(rms_rsc_category_e category) +{ + return (category == RMS_CATEGORY_SCALER_MULTIVIEW || category == RMS_CATEGORY_SCALER_INTERLACED); +} + +bool CAllocateStrategyProvider::IsSubScalerCategory(rms_rsc_category_e category) +{ + bool result = false; + + switch (category) { + case RMS_CATEGORY_SCALER_SUB: + case RMS_CATEGORY_SCALER_SUB2: + case RMS_CATEGORY_SCALER_SUB3: + result = true; + break; + default: + result = false; + break; + } + + return result; +} + +CAllocateStrategyProvider *CAllocateStrategyProvider::getInstance() +{ + if (!m_instance) + m_instance = new CAllocateStrategyProvider(); + + return m_instance; +} + +CAllocateStrategyProvider::~CAllocateStrategyProvider() +{ +} + +CAllocateStrategy *CAllocateStrategyProvider::GetStrategy(rms_rsc_category_e category, int category_class) +{ + CAllocateStrategy *strategy = NULL; + + if (IsVideoDecoderCategory(category)) { + if (IsNDecordingVideoDecoderCategory(category_class)) + strategy = new CNDecodingVideoDecoderStrategy(); + else + strategy = new CVideoDecoderStrategy(); + } else if (IsAudioDecoderCategory(category)) { + strategy = new CAudioDecoderStrategy(); + } else if (IsBGScalerCategory(category) || IsSubScalerCategory(category)) { + strategy = new CExclusiveStrategy(); + } else if (IsMultiviewScalerCategory(category)) { + strategy = new CScalerStrategy(); + } else if (category == RMS_CATEGORY_VIDEO_ENCODER_EXCLUSIVE) { + strategy = new CVideoEncoderExclusiveStrategy(); + } else { + strategy = new CNormalStrategy(); + } + + return strategy; +} diff --git a/src/manager/strategy/CAudioDecoderStrategy.cpp b/src/manager/strategy/CAudioDecoderStrategy.cpp new file mode 100644 index 0000000..984ad8e --- /dev/null +++ b/src/manager/strategy/CAudioDecoderStrategy.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CVirtualResource *CAudioDecoderStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + CRequester *requester = req->getRequester(); + CMixingStrategy *strategy = CMixingStrategy::getInstance(); + bool mixing_supported = CSysInfo::GetInstance()->IsAudioMixingSupported(); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + int device_id = resource->GetDeviceID(); + + SERVER_INFO("vresource id(%d), codec(%s)", vresource->GetVResourceID(), vresource->GetAudioCodec().c_str()); + + rms_error_type_e reason = RMS_ERR_TYPE_NONE; + + if (mixing_supported) { + if (!strategy->isAvailableMixingMode(req->GetMixingMode())) { + strategy->updateReasonByMixingMode(vresource, req, reason); + continue; + } + + if (!strategy->isAvailableAudioCodec(vresource->GetAudioCodec(), requester->getHandle(), &reason)) { + strategy->updateReasonByAudioCodec(vresource, req, reason); + continue; + } + } + + if (resource->IsReserved()) + continue; + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(device_id, req); + continue; + } + + return vresource; + } + + return NULL; +} + +int CAudioDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateAudioCodec(vrsc->GetAudioCodec()); + rsc->updateMixingMode(req->GetMixingMode()); + + return RMS_OK; +} + +int CAudioDecoderStrategy::GetRetirableConsumers(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CResource *resource = vresource->GetResource(); + CRequester *requester = req->getRequester(); + int cid = requester->getHandle(); + rms_error_type_e err; + + SERVER_INFO("vresource id(%d), codec(%s)", vresource->GetVResourceID(), vresource->GetAudioCodec().c_str()); + + if (CSysInfo::GetInstance()->IsAudioMixingSupported()) { + CMixingStrategy *strategy = CMixingStrategy::getInstance(); + + if (!strategy->isAvailableAudioCodec(vresource->GetAudioCodec(), requester->getHandle(), &err)) { + if (strategy->getReclaimableAudioCodecConsumers(vresource->GetAudioCodec(), cid, req, retirables, err_type) != RMS_OK) + goto error; + } + + if (!strategy->isAvailableMixingMode(req->GetMixingMode())) { + if (strategy->getReclaimableMixingModeConsumers(req->GetMixingMode(), cid, retirables, err_type) != RMS_OK) + goto error; + } + } + + if (!resource->IsFreeState()) { + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), cid, retirables, err_type) != RMS_OK) + goto error; + } + + return RMS_OK; + +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + + +void CAudioDecoderStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::map consumer_list; + std::multimap filtered_vresources; + + ExcludeResources(vresources, &filtered_vresources, req); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + + if (GetRetirableConsumers(vresource, req, retirables, err_type) == RMS_OK) + break; + } + + for (auto const &it : consumer_list) { + retirables->insert(std::pair(it.first, it.second)); + } +} diff --git a/src/manager/strategy/CExclusiveStrategy.cpp b/src/manager/strategy/CExclusiveStrategy.cpp new file mode 100644 index 0000000..04f9f97 --- /dev/null +++ b/src/manager/strategy/CExclusiveStrategy.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +void CExclusiveStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +bool CExclusiveStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req) +{ + CResource *resource = vresource->GetResource(); + + if (resource->IsReserved()) { + SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID()); + return false; + } + + if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) { + updateReasonByMemCluster(vresource, req); + return false; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(resource->GetDeviceID(), req); + return false; + } + + return true; +} + +bool CExclusiveStrategy::isSharableResource(CVirtualResource *vresource, CRequest *req) +{ + CResource *resource = vresource->GetResource(); + + if (resource->IsReserved()) { + SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID()); + return false; + } + + if (resource->getSharableCount() <= 0) { + SERVER_INFO("device id(%d) is not sharable state", resource->GetDeviceID()); + updateReasonBySharableCount(resource->GetDeviceID(), req); + return false; + } + + if (!CDependencyController::getInstance()->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID())) { + updateReasonByMemCluster(vresource, req); + return false; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(resource->GetDeviceID(), req); + return false; + } + + return true; +} + +CVirtualResource *CExclusiveStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + bool isReservable = (req->GetState() == RMS_STATE_SHARABLE) ? isSharableResource(vresource, req) : isAllocatableResource(vresource, req); + + SERVER_INFO("is Reservable ? %d", isReservable); + + if (!isReservable) + continue; + + return vresource; + } + + return NULL; +} + +int CExclusiveStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID()); + + return RMS_OK; +} + +bool CExclusiveStrategy::ContainAvailableResource(std::multimap vresources) +{ + CDependencyController *dc = CDependencyController::getInstance(); + + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) + continue; + + if (!resource->IsFreeState()) + continue; + + return true; + } + + return false; +} + +bool CExclusiveStrategy::ContainSharableResource(std::multimap vresources) +{ + CDependencyController *dc = CDependencyController::getInstance(); + + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (!dc->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID())) + continue; + + if (!resource->IsSharableState()) + continue; + + return true; + } + + return false; +} + +int CExclusiveStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CResource *resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables) != RMS_OK) + goto error; + } + + if (!resource->IsFreeState()) { + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK) + goto error; + } + + return RMS_OK; + +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + +int CExclusiveStrategy::getRetirableConsumersShare(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CResource *resource = vresource->GetResource(); + + if (!dc->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID())) { + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables) != RMS_OK) + goto error; + } + + if (!resource->IsSharableState()) { + if (CPriority::getReclaimableConsumersShare(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK) + goto error; + } + + return RMS_OK; + +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + + +void CExclusiveStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + + ExcludeResources(vresources, &filtered_vresources, req); + + bool isShareMode = (req->GetState() == RMS_STATE_SHARABLE); + bool hasAllocatableResource = (isShareMode) ? ContainSharableResource(filtered_vresources) : ContainAvailableResource(filtered_vresources); + + if (hasAllocatableResource) + return; + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + + int result = (isShareMode) ? getRetirableConsumersShare(vresource, req, &consumer_list, err_type) : getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type); + + if (result == RMS_OK) + break; + } + + for (auto const &it : consumer_list) { + retirables->insert(std::pair(it.first, it.second)); + } +} diff --git a/src/manager/strategy/CInvalidModeStrategy.cpp b/src/manager/strategy/CInvalidModeStrategy.cpp new file mode 100644 index 0000000..f314e48 --- /dev/null +++ b/src/manager/strategy/CInvalidModeStrategy.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include + +CInvalidModeStrategy::CInvalidModeStrategy() +{ +} + +CInvalidModeStrategy::~CInvalidModeStrategy() +{ +} + +bool CInvalidModeStrategy::CanAllocateResources(std::vector requests, rms_allocate_result_s *result) +{ + result->result = RMS_ERROR; + result->reason = RMS_ERR_TYPE_INVALID_REQUEST; + + SERVER_ERR("Invalid request set"); + std::for_each(requests.begin(), requests.end(), [](CRequest *req) { SERVER_ERR("req state(%d)", req->GetState()); }); + + return false; +} + +void CInvalidModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices) +{ + assert(allocated_devices); + + allocated_devices->result = RMS_ERROR; + allocated_devices->error_type = RMS_ERR_TYPE_INVALID_REQUEST; + allocated_devices->resources_num = 0; +} diff --git a/src/manager/strategy/CMixingStrategy.cpp b/src/manager/strategy/CMixingStrategy.cpp new file mode 100644 index 0000000..db58961 --- /dev/null +++ b/src/manager/strategy/CMixingStrategy.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CMixingStrategy *CMixingStrategy::m_instance = NULL; + +CMixingStrategy *CMixingStrategy::getInstance(void) +{ + if (!m_instance) + m_instance = new CMixingStrategy(); + + return m_instance; +} + +bool CMixingStrategy::isAvailableAudioCodec(std::string name, int consumer_id, rms_error_type_e *reason) +{ + CAudioCodec *audio_codec = CAudioCodecCollection::getInstance()->findAudioCodec(name.c_str()); + CDependencyController *dc = CDependencyController::getInstance(); + + if (!audio_codec) { + SERVER_ERR("not existing audio codec (%s)", name.c_str()); + *reason = RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST; + return false; + } + + if (!audio_codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) { + SERVER_ERR("mixing not supported (%s)", name.c_str()); + return false; + } + + if (!dc->isAvailableAudioCodec(name)) { + SERVER_ERR("not available audio codec (%s)", name.c_str()); + return false; + } + + return true; +} + +int CMixingStrategy::getReclaimableAudioCodecConsumers(std::string codec_name, int consumer_id, CRequest *req, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name); + + if (!codec) + return RMS_ERROR; + + std::map> acodec_consumers = dc->getAudioCodecConsumers(); + + if (!codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) { + for (auto const &it : acodec_consumers) { + if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, err_type)) + return RMS_ERROR; + + reclaimables->insert(std::pair(it.second.first, it.second.second)); + } + + return RMS_OK; + } + + if (!dc->isAvailableAudioCodec(codec_name)) { + for (auto const &it : acodec_consumers) { + CResource *rsc = CResourceDB::getInstance()->FindResource(it.second.first); + if (req->IsMainDeviceRequest() && !rsc->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && rsc->IsMainDevice()) + continue; + if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, err_type)) + continue; + + reclaimables->insert(std::pair(it.second.first, it.second.second)); + return RMS_OK; + } + } + + return RMS_ERROR; + +} + +bool CMixingStrategy::isAvailableMixingMode(rms_mixing_mode_e mode) +{ + CMixingMode *cur_mode = CDependencyController::getInstance()->getCurMixingMode(); + + if (!cur_mode) + return true; + + SERVER_INFO("cur_mode(%d)/requested(%d)", cur_mode->getMode(), mode); + + return (mode == cur_mode->getMode()); +} + +int CMixingStrategy::getReclaimableMixingModeConsumers(rms_mixing_mode_e mode, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CMixingMode *cur_mode = CDependencyController::getInstance()->getCurMixingMode(); + + if (!cur_mode) { + SERVER_ERR("there is no mixing mode to reclaim"); + return RMS_ERROR; + } + + SERVER_INFO("cur mixing mode (%d), requested codec (%d)", cur_mode->getMode(), mode); + + std::map consumers = cur_mode->GetConsumers(); + + if (consumers.size() == 0) { + SERVER_ERR("no consumer to reclaim in mixing mode(%d)", cur_mode->getMode()); + return RMS_ERROR; + } + + for (auto const &it_consumer : consumers) { + if (!CPriority::isReclaimableConsumer(it_consumer.second, consumer_id, err_type)) + return RMS_ERROR; + + reclaimables->insert(std::pair(it_consumer.first, it_consumer.second)); + } + + return RMS_OK; +} + +bool CMixingStrategy::canReclaimMixingMode(rms_mixing_mode_e mode, CMixingMode *cur_mode, int consumer_id) +{ + std::map consumers = cur_mode->GetConsumers(); + + if (consumers.size() == 0) { + SERVER_ERR("no consumer to reclaim in mixing mode(%d)", cur_mode->getMode()); + return false; + } + + for (auto const &it_consumer : consumers) { + if (!CPriority::isReclaimableConsumer(it_consumer.second, consumer_id, NULL)) + return false; + } + + return true; +} + +bool CMixingStrategy::canReclaimMixingMode(rms_mixing_mode_e mode, int consumer_id) +{ + CMixingMode *mixing_mode = CDependencyController::getInstance()->getCurMixingMode(); + + return (mixing_mode != NULL) ? canReclaimMixingMode(mode, mixing_mode, consumer_id) : false; +} + +void CMixingStrategy::updateReasonByMixingMode(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (!needReclaimCheck(cur_reason)) { + req->SetReason(cur_reason); + return; + } + + if (canReclaimMixingMode(req->GetMixingMode(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + +} + +void CMixingStrategy::updateReasonByAudioCodec(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (!needReclaimCheck(cur_reason)) { + req->SetReason(cur_reason); + return; + } + + if (canReclaimAudioCodec(vresource->GetAudioCodec(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +bool CMixingStrategy::needReclaimCheck(rms_error_type_e reason) +{ + bool result = false; + + switch (reason) { + case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST: + SERVER_ERR("erro case : %d", reason); + result = false; + break; + default: + result = true; + break; + } + + return result; +} + +bool CMixingStrategy::canReclaimAudioCodec(std::string codec_name, int consumer_id) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name); + + if (!codec) + return false; + + std::map> acodec_consumers = dc->getAudioCodecConsumers(); + rms_error_type_e err_type; + + if (!codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) { + for (auto const &it : acodec_consumers) + { + if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, &err_type)) + return false; + } + + return true; + } + + if (!dc->isAvailableAudioCodec(codec_name)) { + for (auto const &it : acodec_consumers) { + if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, &err_type)) + continue; + + return true; + } + } + + return false; + +} diff --git a/src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp b/src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp new file mode 100644 index 0000000..6291dc6 --- /dev/null +++ b/src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void CNDecodingVideoDecoderStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +void CNDecodingVideoDecoderStrategy::updateReasonByBW(CVirtualResource *vresource, CRequest *req) +{ + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + rms_error_type_e reason = canReclaimRequiredBW(req, vresource->GetBW()) ? + RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + req->SetReason(reason); +} + +void CNDecodingVideoDecoderStrategy::updateReasonByTripleDecoding(CRequest *req) +{ + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + rms_error_type_e reason = canReclaimActiveVideoDecoders(req) ? + RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + req->SetReason(reason); +} + +bool CNDecodingVideoDecoderStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req) +{ + int category_class = vresource->GetCategoryClass(); + CResource *resource = vresource->GetResource(); + + if (resource->IsReserved()) { + SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID()); + return false; + } + + if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType())) { + updateReasonByMemCluster(vresource, req); + return false; + } + + CBandwidth *bandwidth = CBandwidth::GetInstance(); + if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && (vresource->GetBW() > bandwidth->GetAvail())) { + SERVER_INFO("insufficient BW required(%d)/avail(%d)", vresource->GetBW(), bandwidth->GetAvail()); + updateReasonByBW(vresource, req); + return false; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(resource->GetDeviceID(), req); + return false; + } + + if (!CResourceDB::getInstance()->HasAvailableDecoderNDecoding()) { + updateReasonByTripleDecoding(req); + return false; + } + + return true; +} + +CVirtualResource *CNDecodingVideoDecoderStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + if (!isAllocatableResource(vresource, req)) + continue; + + return vresource; + } + + return NULL; +} + +int CNDecodingVideoDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID()); + + return RMS_OK; +} + +bool CNDecodingVideoDecoderStrategy::ContainAvailableResource(std::multimap vresources) +{ + + CDependencyController *dc = CDependencyController::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + int category_class = vresource->GetCategoryClass(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType())) + continue; + + if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && (bandwidth->GetAvail() < vresource->GetBW())) + continue; + + if (!resource->IsFreeState()) + continue; + + if (!CResourceDB::getInstance()->HasAvailableDecoderNDecoding()) + continue; + + return true; + } + + return false; +} + +int CNDecodingVideoDecoderStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CResourceDB *resource_db = CResourceDB::getInstance(); + CResource *resource = vresource->GetResource(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + int requester_id = req->getRequester()->getHandle(); + int category_class = vresource->GetCategoryClass(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType())) { + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), requester_id, retirables) != RMS_OK) + goto error; + } + + if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && ((bandwidth->GetAvail() + GetReclaimedBW(retirables)) < vresource->GetBW())) { + if (GetConsumerUsingBW(req, vresource->GetBW(), retirables) != RMS_OK) + goto error; + } + + if (!resource->IsFreeState()) { + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), requester_id, retirables, err_type) != RMS_OK) + goto error; + } + + if (!resource_db->HasAvailableDecoderNDecoding(*retirables)) { + if (GetReclaimableVideoDecoderConsumers(requester_id, retirables, req, err_type) != RMS_OK) + goto error; + } + + return RMS_OK; +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + +void CNDecodingVideoDecoderStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + bool included = false; + + ExcludeResources(vresources, &filtered_vresources, req); + + if (ContainAvailableResource(filtered_vresources)) + return; + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + included = false; + CResource *rsc = vresource->GetResource(); + SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), rsc->GetDeviceID()); + if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK) { + for (auto const &it_c : consumer_list) { + auto it_r = retirables->find(it_c.first); + if (it_r != retirables->end()) { + included = true; + SERVER_INFO("(%d:%d) is already in the list", it_c.first, it_c.second); + break; + } + } + if (included) + continue; + + break; + } + } + + retirables->insert(consumer_list.begin(), consumer_list.end()); +} + +bool CNDecodingVideoDecoderStrategy::canReclaimRequiredBW(CRequest *req, unsigned int bw) +{ + CRequester *requester = req->getRequester(); + CResourceDB *resource_db = CResourceDB::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + unsigned int check_available = bandwidth->GetAvail(); + std::map bw_consumers = bandwidth->GetConsumers(); + + for (std::map::iterator it = bw_consumers.begin(); it != bw_consumers.end(); it++) { + int device_id = (*it).first; + int consumer_id = (*it).second; + + CResource *pRsc = resource_db->FindResource(device_id); + + if (!pRsc) { + SERVER_ERR("cannot find resource using device id"); + continue; + } + + if (requester->getHandle() == consumer_id) { + SERVER_INFO("CID[%d] is using BW (%d)", requester->getHandle(), pRsc->GetBW()); + continue; + } + + if (CPriority::compare(consumer_id, requester->getHandle()) != HIGH_PRIORITY) + continue; + + check_available += pRsc->GetBW(); + + if (bw <= check_available) + break; + + SERVER_INFO("DevID[%d]/ need more resource to be released!!! required BW(%d)-resource BW(%d)-check(%d)", pRsc->GetDeviceID(), bw, pRsc->GetBW(), check_available); + + } + + SERVER_INFO("required BW(%d) - available (%d)", bw, check_available); + + return (bw <= check_available); +} + +void CNDecodingVideoDecoderStrategy::SelectDevicesByMainSub(CRequest *req, std::map *src, std::map *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + + for (auto const &it : *src) { + CResource *rsc = db->FindResource(it.first); + if (!rsc) + continue; + if (req->IsMainDeviceRequest() && !rsc->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && rsc->IsMainDevice()) + continue; + + result->insert(std::pair(it.first, it.second)); + } +} + +int CNDecodingVideoDecoderStrategy::GetConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap* return_ids) +{ + std::map candidates; + std::map cur_consumers = CBandwidth::GetInstance()->GetConsumers(); //device id, consumer id + + SelectDevicesByMainSub(req, &cur_consumers, &candidates); + + std::multimap reclaimed_by_ms; + unsigned int avail_bw = GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, candidates, &reclaimed_by_ms); + + if (avail_bw >= bw) { + return_ids->insert(reclaimed_by_ms.begin(), reclaimed_by_ms.end()); + return RMS_OK; + } + + std::multimap reclaimed_by_t; + GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, cur_consumers, &reclaimed_by_t); + return_ids->insert(reclaimed_by_t.begin(), reclaimed_by_t.end()); + + return RMS_OK; +} + +int CNDecodingVideoDecoderStrategy::GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map bw_consumers, std::multimap* reclaimed_consumers) +{ + assert(reclaimed_consumers); + + CResourceDB *resource_db = CResourceDB::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + SERVER_INFO("candidates using BW : %zu", bw_consumers.size()); + unsigned int reclaimed_bw = bandwidth->GetAvail(); + + std::map consumers_by_t; + for (auto const &itc : bw_consumers) { + CResource *rsc = resource_db->FindResource(itc.first); + if (!rsc) + continue; + + consumers_by_t.insert(std::pair(rsc->GetAllocatedTime(), itc.first)); + } + + for (auto const &it : consumers_by_t) { + int device_id = it.second; + CResource *pRsc = resource_db->FindResource(device_id); + if (!pRsc) + continue; + + int consumer_id = pRsc->GetFirstConsumer(); + SERVER_INFO("consumer (%d) is using bw for device (%d)", consumer_id, device_id); + + if (requester_id == consumer_id) { + SERVER_INFO("CID[%d] is using BW (%d)", requester_id, pRsc->GetBW()); + continue; + } + + if (CPriority::compare(consumer_id, requester_id) != HIGH_PRIORITY) + continue; + + auto ret = reclaimed_consumers->find(device_id); + if (ret != reclaimed_consumers->end()) { + SERVER_INFO("(%d:%d) already inserted", device_id, consumer_id); + continue; + } + + reclaimed_consumers->insert(std::pair(device_id, consumer_id)); + + if (pRsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) { + std::map siblings; + bandwidth->GetConsumersNDec(pRsc->GetCurCategory(), &siblings); + if (siblings.size() > 0) { + SERVER_INFO("insert n-dec siblings(%zu)", siblings.size()); + reclaimed_consumers->insert(siblings.begin(), siblings.end()); + } + } + + reclaimed_bw += pRsc->GetBW(); + + if (required_bw <= reclaimed_bw) + break; + SERVER_INFO("DevID[%d]/ need more BW! required:(%d)-resource(%d)-reclaimed(%d)", pRsc->GetDeviceID(), required_bw, pRsc->GetBW(), reclaimed_bw); + } + + return reclaimed_bw; +} + +bool CNDecodingVideoDecoderStrategy::canReclaimActiveVideoDecoders(CRequest *req) +{ + CRequester *requester = req->getRequester(); + CResourceDB *resource_db = CResourceDB::getInstance(); + std::map active_vdecs = resource_db->GetActiveVideoDecoders(); + + for (auto const &it : active_vdecs) { + int dev_id = it.first; + int cid = it.second; + + CResource *rsc = resource_db->FindResource(dev_id); + + if (!rsc) { + SERVER_ERR("can't find resource (%d)", dev_id); + continue; + } + + if (requester->getHandle() == cid) { + SERVER_INFO("CID[%d] is using device (%d)", cid, dev_id); + continue; + } + + if (CPriority::compare(cid, requester->getHandle()) == HIGH_PRIORITY) + return true; + } + + return false; + +} + +int CNDecodingVideoDecoderStrategy::GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap* reclaimables, CRequest *req, rms_error_type_e *err_type) +{ + std::map rscs; + CResource *rsc = NULL; + CResourceDB *resource_db = CResourceDB::getInstance(); + std::map active_vdecs = resource_db->GetActiveVideoDecoders(); + bool has_main_vdec = false; + bool has_sub_vdec = false; + + for (auto const &it_vdec : active_vdecs) { + rsc = resource_db->FindResource(it_vdec.first); + rscs.insert(std::pair(rsc->GetAllocatedTime(), rsc)); + + if (rsc->IsMainDevice()) + has_main_vdec = true; + else + has_sub_vdec = true; + } + + for (auto const &it : rscs) + { + rsc = it.second; + + if (req->IsMainDeviceRequest() && has_main_vdec && !rsc->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && has_sub_vdec && rsc->IsMainDevice()) + continue; + + if (CPriority::getReclaimableConsumers(rsc->GetDeviceID(), consumer_id, reclaimables, err_type) == RMS_OK) + return RMS_OK; + } + + return RMS_ERROR; +} diff --git a/src/manager/strategy/CNormalModeStrategy.cpp b/src/manager/strategy/CNormalModeStrategy.cpp new file mode 100644 index 0000000..9295d02 --- /dev/null +++ b/src/manager/strategy/CNormalModeStrategy.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include + +void ReserveCandidate(CRequest *req) +{ + CResourceCategory *resource_category = CResourceDB::getInstance()->FindResourceCategory(req->GetCategory()); + + req->SetResult(RMS_ERROR); + + if (!resource_category) { + if (req->GetCategory() == RMS_CATEGORY_NOT_PERMITTED) + req->SetReason(RMS_ERR_TYPE_NOT_PERMITTED); + else + req->SetReason(RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST); + + SERVER_ERR("not existing category(%d)! can't allocate a candidate", req->GetCategory()); + return; + } + + CResource *resource = resource_category->ReserveCandidate(req, true); + + if (!resource) + return; + + req->SetResult(RMS_OK); + req->SetCandidateDevice(resource->GetDeviceID()); +} + +void ReleaseReservedResources(CRequest *req) +{ + if (req->GetResult() != RMS_OK) + return; + + CResource *resource = CResourceDB::getInstance()->FindResource(req->GetCandidateDevice()); + + resource->CancelReservation((rms_requests_resource_state_e) req->GetState()); +} + +rms_return_code_e ToAllocReturnCode(rms_error_type_e error_type) +{ + rms_return_code_e result = RMS_OK; + + switch (error_type) { + case RMS_ERR_TYPE_NONE: + result = RMS_OK; + break; + case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + result = RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER; + break; + default: + result = RMS_ERROR; + break; + } + + return result; +} + + +CNormalModeStrategy::CNormalModeStrategy() +{ +} + +CNormalModeStrategy::~CNormalModeStrategy() +{ +} + +rms_error_type_e CNormalModeStrategy::GetCandidateFindResult(std::vector requests) +{ + rms_error_type_e result = RMS_ERR_TYPE_NONE; + + for (auto& it : requests) { + CRequest *request = it; + + if (request->GetResult() == RMS_OK) + continue; + + if (request->GetReason() != RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return request->GetReason(); + + result = RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER; + } + + return result; +} + +bool CNormalModeStrategy::CanAllocateResources(std::vector requests, rms_allocate_result_s *result) +{ + std::for_each(requests.begin(), requests.end(), ReserveCandidate); + + result->reason = GetCandidateFindResult(requests); + result->result = ToAllocReturnCode(result->reason); + + std::for_each(requests.begin(), requests.end(), ReleaseReservedResources); + + return (result->result == RMS_OK); +} + +void CNormalModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices) +{ + assert(allocated_devices); + + allocated_devices->result = alloc_result->result; + allocated_devices->error_type = alloc_result->reason; + + if (alloc_result->result != RMS_OK) { + allocated_devices->resources_num = 0; + return; + } + + allocated_devices->resources_num = requests.size(); + allocated_devices->device_ids = (int*) calloc(requests.size(), sizeof(int)); + assert(allocated_devices->device_ids); + allocated_devices->devices = (rms_return_device_info_s*) calloc(requests.size(), sizeof(rms_return_device_info_s)); + + int i = 0; + + for (auto const &it : requests) { + allocated_devices->device_ids[i] = it->GetAllocatedVirtualDevice(); + allocated_devices->devices[i].device_id = it->GetAllocatedVirtualDevice(); + CResource *resource = CResourceDB::getInstance()->FindResource(it->GetAllocatedDevice()); + assert(resource); + + const char *path = resource->GetDevicePath(); + allocated_devices->devices[i].device_path = strndup(path, strlen(path)); + resource->SetAllocatedTime(); + i++; + } +} diff --git a/src/manager/strategy/CNormalStrategy.cpp b/src/manager/strategy/CNormalStrategy.cpp new file mode 100644 index 0000000..49846b1 --- /dev/null +++ b/src/manager/strategy/CNormalStrategy.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include + +CNormalStrategy::CNormalStrategy() +{ +} + +CNormalStrategy::~CNormalStrategy() +{ +} + +CVirtualResource *CNormalStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + int device_id = resource->GetDeviceID(); + + if (resource->IsReserved()) + continue; + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(device_id, req); + continue; + } + + return vresource; + } + + return NULL; +} + +int CNormalStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + return RMS_OK; +} + +bool CNormalStrategy::ContainFreeResource(std::multimap vresources) +{ + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsFreeState()) + return true; + } + + return false; +} + +void CNormalStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + + ExcludeResources(vresources, &filtered_vresources, req); + + if (ContainFreeResource(filtered_vresources)) + return; + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), &consumer_list, err_type) == RMS_OK) + break; + } + + for (auto const &it : consumer_list) { + retirables->insert(std::pair(it.first, it.second)); + } +} diff --git a/src/manager/strategy/CPreferenceModeStrategy.cpp b/src/manager/strategy/CPreferenceModeStrategy.cpp new file mode 100644 index 0000000..9bebbe6 --- /dev/null +++ b/src/manager/strategy/CPreferenceModeStrategy.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +CPreferenceModeStrategy::CPreferenceModeStrategy() +{ +} + +CPreferenceModeStrategy::~CPreferenceModeStrategy() +{ +} + +bool CPreferenceModeStrategy::CanAllocateResources(std::vector requests, rms_allocate_result_s *result) +{ + result->result = RMS_ERROR; + result->reason = RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE; + + for (auto const &it : requests) { + CRequest *req = it; + CResourceCategory *resource_category = CResourceDB::getInstance()->FindResourceCategory(req->GetCategory()); + + if (!resource_category) { + SERVER_ERR("not existing category(%d)! can't allocate a candidate", req->GetCategory()); + continue; + } + + CResource *resource = resource_category->ReserveCandidate(req, false); + + if (!resource) + continue; + + req->SetResult(RMS_OK); + req->SetCandidateDevice(resource->GetDeviceID()); + result->result = RMS_OK; + break; + } + + std::for_each(requests.begin(), requests.end(), [](CRequest *req) { if (req->GetResult()!= RMS_OK) return; + CResource *resource = CResourceDB::getInstance()->FindResource(req->GetCandidateDevice()); + resource->CancelReservation((rms_requests_resource_state_e) req->GetState()); }); + + return (result->result == RMS_OK); +} + +void CPreferenceModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector requests, rms_return_device_s *allocated_devices) +{ + assert(allocated_devices); + + allocated_devices->result = alloc_result->result; + allocated_devices->error_type = alloc_result->reason; + + if (alloc_result->result != RMS_OK) { + allocated_devices->resources_num = 0; + return; + } + + allocated_devices->resources_num = requests.size(); + allocated_devices->device_ids = (int*) calloc(requests.size(), sizeof(int)); + allocated_devices->devices = (rms_return_device_info_s*) calloc(requests.size(), sizeof(rms_return_device_info_s)); + + int i = 0; + + for (auto const &it : requests) { + bool is_allocated = (it->GetResult() == RMS_OK); + int allocated_device_id = (is_allocated) ? it->GetAllocatedVirtualDevice() : RMS_DEVICE_NONE; + + allocated_devices->device_ids[i] = allocated_device_id; + allocated_devices->devices[i].device_id = allocated_device_id; + + if (!is_allocated) { + i++; + continue; + } + + CResource *resource = CResourceDB::getInstance()->FindResource(it->GetAllocatedDevice()); + assert(resource); + + const char *path = resource->GetDevicePath(); + allocated_devices->devices[i].device_path = strndup(path, strlen(path)); + resource->SetAllocatedTime(); + i++; + } +} + diff --git a/src/manager/strategy/CScalerStrategy.cpp b/src/manager/strategy/CScalerStrategy.cpp new file mode 100644 index 0000000..5cca781 --- /dev/null +++ b/src/manager/strategy/CScalerStrategy.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +CScalerStrategy::CScalerStrategy() +{ +} + +CScalerStrategy::~CScalerStrategy() +{ +} + +void CScalerStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req) +{ + CRequester *requester = req->getRequester(); + + if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +CVirtualResource *CScalerStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + int device_id = resource->GetDeviceID(); + + if (resource->IsReserved()) + continue; + + if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) { + updateReasonByMemCluster(vresource, req); + continue; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(device_id, req); + continue; + } + + return vresource; + } + + return NULL; +} + +int CScalerStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID()); + return RMS_OK; +} + +bool CScalerStrategy::ContainFreeResource(std::multimap vresources) +{ + for (auto const &it : vresources) + { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsFreeState()) + return true; + } + + return false; +} + +void CScalerStrategy::SelectConsumersByAllocationTime(std::map> *candidates, std::multimap *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + std::map candidates_by_alloc_t; // allocation time, virtual resource id + + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + candidates_by_alloc_t.insert(std::pair(rsc->GetAllocatedTime(), it.first)); + SERVER_INFO("vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second); + } + } + + auto itf = candidates_by_alloc_t.begin(); + if (itf == candidates_by_alloc_t.end()) { + SERVER_ERR("no candidate"); + return; + } + + auto const &ite = candidates->find(itf->second); + std::multimap *elected = &ite->second; + + result->insert(elected->begin(), elected->end()); +} + +void CScalerStrategy::SelectConsumersByZoneId(int zone_id, std::map> *candidates, std::multimap *result) +{ + if (zone_id <= 0) { + SERVER_ERR("invalid zone id(%d)", zone_id); + return; + } + + CResourceDB *db = CResourceDB::getInstance(); + + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + if (rsc->GetZoneId() == zone_id) { + SERVER_INFO("[%d] select (%d) > (%d:%d)", it.first, zone_id, itc.first, itc.second); + result->insert(candidate.begin(), candidate.end()); + break; + } + } + } +} + +bool CScalerStrategy::ContainInterlacedNotSupportedApp(std::map> *candidates) +{ + CResourceDB *db = CResourceDB::getInstance(); + + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + if (rsc->GetCurCategory() != RMS_CATEGORY_SCALER_INTERLACED) + return true; + } + } + return false; +} + +int CScalerStrategy::FindScalerInSameZone(int zone_id) +{ + std::map scalers; + CResourceDB::getInstance()->GetScalerList(&scalers); + + for (auto const &it : scalers) { + CResource *rsc = it.second; + if (rsc->GetZoneId() == zone_id) { + SERVER_INFO("scaler in same zone(%d:%d:%d) found", zone_id, rsc->GetDeviceID(), rsc->GetVirtualDeviceId()); + return rsc->GetDeviceID(); + } + } + SERVER_INFO("scaler in same zone not found"); + return -1; +} + +int CScalerStrategy::FindScalerUsedByAppInterlacedNotSupported(std::map> *candidates) +{ + CResourceDB *db = CResourceDB::getInstance(); + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + if (rsc->GetCurCategory() == RMS_CATEGORY_SCALER_INTERLACED) + continue; + SERVER_INFO("scaler(%d:%d:%d) used by the app interlaced not supported found", rsc->GetCurCategory(), rsc->GetDeviceID(), rsc->GetVirtualDeviceId()); + return rsc->GetDeviceID(); + } + } + SERVER_INFO("scaler used by the app interlaced not supported not found"); + return -1; +} + +void CScalerStrategy::SelectConsumersBySwap(int zone_id, std::map> *candidates, std::multimap *result) +{ + if (!ContainInterlacedNotSupportedApp(candidates)) { + SERVER_INFO("all scalers are being used by apps supporting interlaced"); + return; + } + + int scaler_id_sz = FindScalerInSameZone(zone_id); + if (scaler_id_sz < 0) + return; + + int scaler_id_ins = FindScalerUsedByAppInterlacedNotSupported(candidates); + if (scaler_id_ins < 0) + return; + + CResourceDB *db = CResourceDB::getInstance(); + CResource *rsc_sz = db->FindResource(scaler_id_sz); + CResource *rsc_ins = db->FindResource(scaler_id_ins); + + if (db->SwapScaler(rsc_sz->GetVirtualDeviceId(), rsc_ins->GetVirtualDeviceId()) < 0) + return; + + db->UpdateVirtualScalerIds(); + + std::set consumers = rsc_ins->GetConsumers(); + for (auto const &it : consumers) { + SERVER_INFO("insert (%d:%d)", scaler_id_ins, it); + result->insert(std::pair(scaler_id_ins, it)); + } +} + +void CScalerStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + std::map> candidates; // > + + ExcludeResources(vresources, &filtered_vresources, req); + + CDependencyController *dc = CDependencyController::getInstance(); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID()); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), &consumer_list) != RMS_OK) { + SERVER_ERR("failed to find reclaimable consumer vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID()); + }; + } + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), &consumer_list, err_type) == RMS_OK) { + candidates.insert(std::pair>(vresource->GetVResourceID(), consumer_list)); + consumer_list.clear(); + } + } + SERVER_INFO("zone id : %d, candidates(%zu)", req->GetMultiviewZoneId(), candidates.size()); + if (req->GetMultiviewZoneId() > 0) + SelectConsumersByZoneId(req->GetMultiviewZoneId(), &candidates, &consumer_list); + + if (consumer_list.empty() && (req->GetCategory() == RMS_CATEGORY_SCALER_INTERLACED)) + SelectConsumersBySwap(req->GetMultiviewZoneId(), &candidates, &consumer_list); + + if (consumer_list.empty()) + SelectConsumersByAllocationTime(&candidates, &consumer_list); + + for (auto const &it : consumer_list) + retirables->insert(std::pair(it.first, it.second)); +} diff --git a/src/manager/strategy/CVideoDecoderStrategy.cpp b/src/manager/strategy/CVideoDecoderStrategy.cpp new file mode 100644 index 0000000..c02f504 --- /dev/null +++ b/src/manager/strategy/CVideoDecoderStrategy.cpp @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CVideoDecoderStrategy::CVideoDecoderStrategy() +{ + m_reclaim_policy_by_zone_id = ri_get_zone_id_based_reclaim_policy(); +} + +void CVideoDecoderStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) { + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) + return; + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +void CVideoDecoderStrategy::updateReasonByBW(CVirtualResource *vresource, CRequest *req) +{ + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + rms_error_type_e reason = canReclaimRequiredBW(req, vresource->GetBW()) ? + RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER:RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + req->SetReason(reason); +} + +void CVideoDecoderStrategy::updateReasonByTripleDecoding(CRequest *req) +{ + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + rms_error_type_e reason = canReclaimActiveVideoDecoders(req) ? + RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + req->SetReason(reason); +} + +bool CVideoDecoderStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req) +{ + CResource *resource = vresource->GetResource(); + //int cat_id = vresource->GetCategoryType(); + //int vid = vresource->GetVResourceID(); + int device_id = resource->GetDeviceID(); + + //SERVER_INFO("> cat(%d)/vid(%d) device id(%d)", cat_id, vid, device_id); + + if (resource->IsReserved()) { + SERVER_INFO("device id(%d) is reserved state", device_id); + return false; + } + + if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) { + updateReasonByMemCluster(vresource, req); + return false; + } + + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + if (vresource->GetBW() > bandwidth->GetAvail()) { + SERVER_INFO("insufficient BW required(%d)/avail(%d)", vresource->GetBW(), bandwidth->GetAvail()); + updateReasonByBW(vresource, req); + return false; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + updateReasonByResourceState(device_id, req); + return false; + } + + if (!CResourceDB::getInstance()->HasAvailableDecoder()) { + updateReasonByTripleDecoding(req); + return false; + } + + //SERVER_INFO("> cat(%d)/vid(%d) device id(%d) allocatable", cat_id, vid, device_id); + + return true; +} + +CVirtualResource *CVideoDecoderStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + + if (!isAllocatableResource(vresource, req)) + continue; + + return vresource; + } + + return NULL; +} + +int CVideoDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID()); + return RMS_OK; +} + +bool CVideoDecoderStrategy::ContainAvailableResource(std::multimap vresources) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) + continue; + + if (bandwidth->GetAvail() < vresource->GetBW()) + continue; + + if (!resource->IsFreeState()) + continue; + + if (!CResourceDB::getInstance()->HasAvailableDecoder()) + continue; + + return true; + } + + return false; +} + +int CVideoDecoderStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CResourceDB *resource_db = CResourceDB::getInstance(); + CResource *resource = vresource->GetResource(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + int requester_id = req->getRequester()->getHandle(); + + SERVER_INFO(":: Get retirable consumers (%d:%d)", vresource->GetVResourceID(), resource->GetDeviceID()); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { + SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID()); + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), requester_id, retirables) != RMS_OK) + goto error; + } + + if ((bandwidth->GetAvail() + GetReclaimedBW(retirables)) < vresource->GetBW()) { + if (getConsumerUsingBW(req, vresource->GetBW(), retirables) != RMS_OK) + goto error; + } + + if (!resource->IsFreeState()) { + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), requester_id, retirables, err_type) != RMS_OK) + goto error; + } + + if (!resource_db->HasAvailableDecoder(*retirables)) { + if (GetReclaimableVideoDecoderConsumers(requester_id, retirables, req, err_type) != RMS_OK) + goto error; + } + + SERVER_WARN("RMS_OK"); + return RMS_OK; + +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + +void CVideoDecoderStrategy::SelectInSameCategoryAndZone(int zone_id, std::map> *candidates, std::multimap *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + if ((rsc->GetVirtualResourceID() == it.first) && (rsc->GetZoneId() == zone_id)) { + SERVER_INFO("[%d] select (%d) > (%d:%d)", it.first, zone_id, itc.first, itc.second); + result->insert(candidate.begin(), candidate.end()); + return; + } + } + } +} + +int CVideoDecoderStrategy::GetConflictScore(int n_conflicts) +{ + return (10000 - n_conflicts); +} + +void CVideoDecoderStrategy::SelectInSameZone(int zone_id, std::map> candidates, std::multimap *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + std::map candidates_by_score; + + for (auto const &it : candidates) { + std::multimap candidate = it.second; + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + if (rsc->GetZoneId() != zone_id) + continue; + + int score = GetConflictScore(candidate.size()); + SERVER_INFO("insert (%d:%d) : score(%d) by (%d)", it.first, zone_id, score, itc.first); + candidates_by_score.insert(std::pair(score, it.first)); + } + } + + if (candidates_by_score.empty()) + return; + + auto const top = candidates_by_score.rbegin(); + auto const it = candidates.find(top->second); + if (it == candidates.end()) + return; + + std::multimap selected = it->second; + SERVER_INFO("select (%d:%d)", top->second, zone_id); + result->insert(selected.begin(), selected.end()); +} + +void CVideoDecoderStrategy::SelectConsumersByZoneId(int zone_id, std::map> *candidates, std::multimap *result) +{ + if (zone_id <= 0) { + SERVER_ERR("invalid zone id(%d)", zone_id); + return; + } + + SelectInSameCategoryAndZone(zone_id, candidates, result); + + if (!result->empty()) + return; + + SelectInSameZone(zone_id, *candidates, result); +} + +void CVideoDecoderStrategy::SelectConsumersByAllocationTime(std::map> *candidates, std::multimap *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + std::map candidates_by_alloc_t; // allocation time, virtual resource id + + std::map conflicts; //virtual resource id, n conflicts + int n_conflicts = 0; + for (auto const &itn : *candidates) { + std::multimap candidate = itn.second; + n_conflicts = candidate.size(); + if (n_conflicts > 0) { + SERVER_INFO("vrsc(%d)/conflicts(%d)", itn.first, n_conflicts); + conflicts.insert(std::pair(itn.first, n_conflicts)); + } + } + + bool inserted = false; + + for (auto const &it : *candidates) { + std::multimap candidate = it.second; + n_conflicts = candidate.size(); + for (auto const &itc : candidate) { + CResource *rsc = db->FindResource(itc.first); + unsigned long alloc_t = rsc->GetAllocatedTime(); + SERVER_INFO("insert vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second); + inserted = candidates_by_alloc_t.insert(std::pair(alloc_t, it.first)).second; + if (!inserted) { + SERVER_INFO("t:%ld already in it", alloc_t); + auto const &cur = candidates_by_alloc_t.find(alloc_t); + if (cur == candidates_by_alloc_t.end()) + continue; + + auto const &n = conflicts.find(cur->second); + if (n == conflicts.end()) + continue; + + int cur_conflicts = n->second; + SERVER_INFO("cur_conflicts(%d)/n_conflicts(%d)", cur_conflicts, n_conflicts); + if (cur_conflicts > n_conflicts) { + candidates_by_alloc_t.erase(rsc->GetAllocatedTime()); + SERVER_INFO("insert vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second); + candidates_by_alloc_t.insert(std::pair(rsc->GetAllocatedTime(), it.first)); + } + } + + } + } + + auto itf = candidates_by_alloc_t.begin(); + if (itf == candidates_by_alloc_t.end()) { + SERVER_ERR("no candidate"); + return; + } + + auto const &ite = candidates->find(itf->second); + std::multimap *elected = &ite->second; + + result->insert(elected->begin(), elected->end()); +} + +void CVideoDecoderStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + std::map> candidates; + + ExcludeResources(vresources, &filtered_vresources, req); + + if (ContainAvailableResource(filtered_vresources)) + return; + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + + if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK) { + candidates.insert(std::pair>(vresource->GetVResourceID(), consumer_list)); + consumer_list.clear(); + } + } + + if (m_reclaim_policy_by_zone_id && req->GetMultiviewZoneId() > 0) + SelectConsumersByZoneId(req->GetMultiviewZoneId(), &candidates, &consumer_list); + + if (consumer_list.empty()) + SelectConsumersByAllocationTime(&candidates, &consumer_list); + + for (auto const &it : consumer_list) + retirables->insert(std::pair(it.first, it.second)); +} + +bool CVideoDecoderStrategy::canReclaimRequiredBW(CRequest *req, unsigned int bw) +{ + CRequester *requester = req->getRequester(); + CResourceDB *resource_db = CResourceDB::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + unsigned int reclaimed_bw = bandwidth->GetAvail(); + std::map bw_consumers = bandwidth->GetConsumers(); + + for (std::map::iterator it = bw_consumers.begin(); it != bw_consumers.end(); it++) { + int device_id = (*it).first; + int consumer_id = (*it).second; + + CResource *pRsc = resource_db->FindResource(device_id); + + if (!pRsc) { + SERVER_ERR("cannot find resource using device id"); + continue; + } + + if (requester->getHandle() == consumer_id) { + SERVER_INFO("CID[%d] is using BW (%d)", requester->getHandle(), pRsc->GetBW()); + continue; + } + + if (CPriority::compare(consumer_id, requester->getHandle()) != HIGH_PRIORITY) + continue; + + reclaimed_bw += pRsc->GetBW(); + + if (bw <= reclaimed_bw) + break; + + SERVER_INFO("DevID[%d] / need more resource to be released!!! required BW(%d)-resource BW(%d)-check(%d)", pRsc->GetDeviceID(), bw, pRsc->GetBW(), reclaimed_bw); + } + + SERVER_INFO("required BW(%d) - available (%d)", bw, reclaimed_bw); + + return (bw <= reclaimed_bw); + +} + +void CVideoDecoderStrategy::SelectDevicesByMainSub(CRequest *req, std::map *src, std::map *result) +{ + CResourceDB *db = CResourceDB::getInstance(); + + for (auto const &it : *src) { + CResource *rsc = db->FindResource(it.first); + if (!rsc) + continue; + if (req->IsMainDeviceRequest() && !rsc->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && rsc->IsMainDevice()) + continue; + + result->insert(std::pair(it.first, it.second)); + } +} + +int CVideoDecoderStrategy::getConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap *return_ids) +{ + std::map candidates; + std::map cur_consumers = CBandwidth::GetInstance()->GetConsumers(); //device id, consumer id + + SelectDevicesByMainSub(req, &cur_consumers, &candidates); + + std::multimap reclaimed_by_ms; + unsigned int avail_bw = GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, candidates, &reclaimed_by_ms); + + if (avail_bw >= bw) { + return_ids->insert(reclaimed_by_ms.begin(), reclaimed_by_ms.end()); + return RMS_OK; + } + + std::multimap reclaimed_by_t; + GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, cur_consumers, &reclaimed_by_t); + return_ids->insert(reclaimed_by_t.begin(), reclaimed_by_t.end()); + + return RMS_OK; +} + +int CVideoDecoderStrategy::GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map bw_consumers, std::multimap *reclaimed_consumers) +{ + assert(reclaimed_consumers); + + CResourceDB *resource_db = CResourceDB::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + SERVER_INFO("candidates using BW : %zu", bw_consumers.size()); + unsigned int reclaimed_bw = bandwidth->GetAvail(); + + std::map consumers_by_t; + for (auto const &itc : bw_consumers) { + CResource *rsc = resource_db->FindResource(itc.first); + if (!rsc) + continue; + + consumers_by_t.insert(std::pair(rsc->GetAllocatedTime(), itc.first)); + } + + for (auto const &it : consumers_by_t) { + int device_id = it.second; + CResource *pRsc = resource_db->FindResource(device_id); + if (!pRsc) + continue; + + int consumer_id = pRsc->GetFirstConsumer(); + SERVER_INFO("consumer (%d) is using bw for device (%d)", consumer_id, device_id); + + if (requester_id == consumer_id) { + SERVER_INFO("CID[%d] is using BW (%d)", requester_id, pRsc->GetBW()); + continue; + } + + if (CPriority::compare(consumer_id, requester_id) != HIGH_PRIORITY) + continue; + + auto ret = reclaimed_consumers->find(device_id); + if (ret != reclaimed_consumers->end()) { + SERVER_INFO("(%d:%d) already inserted", device_id, consumer_id); + continue; + } + + reclaimed_consumers->insert(std::pair(device_id, consumer_id)); + + if (pRsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) { + std::map siblings; + bandwidth->GetConsumersNDec(pRsc->GetCurCategory(), &siblings); + if (siblings.size() > 0) { + SERVER_INFO("insert n-dec siblings(%zu)", siblings.size()); + reclaimed_consumers->insert(siblings.begin(), siblings.end()); + } + } + + reclaimed_bw += pRsc->GetBW(); + + if (required_bw <= reclaimed_bw) + break; + SERVER_INFO("DevID[%d]/ need more BW! required:(%d)-resource(%d)-reclaimed(%d)", pRsc->GetDeviceID(), required_bw, pRsc->GetBW(), reclaimed_bw); + } + + return reclaimed_bw; +} + +bool CVideoDecoderStrategy::canReclaimActiveVideoDecoders(CRequest *req) +{ + CRequester *requester = req->getRequester(); + CResourceDB *resource_db = CResourceDB::getInstance(); + std::map active_vdecs = resource_db->GetActiveVideoDecoders(); + + for (auto const &it : active_vdecs) { + int dev_id = it.first; + int cid = it.second; + + CResource *rsc = resource_db->FindResource(dev_id); + + if (!rsc) { + SERVER_ERR("can't find resource (%d)", dev_id); + continue; + } + + if (requester->getHandle() == cid) { + SERVER_INFO("CID[%d] is using device (%d)", cid, dev_id); + continue; + } + + if (CPriority::compare(cid, requester->getHandle()) == HIGH_PRIORITY) + return true; + } + + return false; + +} + +int CVideoDecoderStrategy::GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap* reclaimables, CRequest *req, rms_error_type_e *err_type) +{ + std::map rscs; + CResource *rsc = NULL; + CResourceDB *db = CResourceDB::getInstance(); + std::map active_vdecs = db->GetActiveVideoDecoders(); + bool has_main_vdec = false; + bool has_sub_vdec = false; + + for (auto const &it_vdec : active_vdecs) { + rsc = db->FindResource(it_vdec.first); + rscs.insert(std::pair(rsc->GetAllocatedTime(), rsc)); + + if (rsc->IsMainDevice()) + has_main_vdec = true; + else + has_sub_vdec = true; + } + + for (auto const &it : rscs) { + rsc = it.second; + + if (req->IsMainDeviceRequest() && has_main_vdec && !rsc->IsMainDevice()) + continue; + if (req->IsSubDeviceRequest() && has_sub_vdec && rsc->IsMainDevice()) + continue; + + if (CPriority::getReclaimableConsumers(rsc->GetDeviceID(), consumer_id, reclaimables, err_type) == RMS_OK) { + if (rsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) { + std::map active_ndecs = db->GetActiveNVideoDecoders(); + reclaimables->insert(active_ndecs.begin(), active_ndecs.end()); + } + return RMS_OK; + } + } + + return RMS_ERROR; +} diff --git a/src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp b/src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp new file mode 100644 index 0000000..3e06691 --- /dev/null +++ b/src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +void CVideoEncoderExclusiveStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req) +{ + CRequester *requester = req->getRequester(); + + if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) { + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); + return; + } + + if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle(), requester->getAppId())) { + SERVER_ERR("canReclaimMemClusters is failed"); + req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER); + return; + } + + if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) { + SERVER_ERR("RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER"); + return; + } + + req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS); +} + +bool CVideoEncoderExclusiveStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req) +{ + CResource *resource = vresource->GetResource(); + CRequester *requester = req->getRequester(); + + if (resource->IsReserved()) { + SERVER_ERR("device id(%d) is reserved state", resource->GetDeviceID()); + return false; + } + + if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId())) { + SERVER_ERR("isAvailableMemClusters is failed"); + updateReasonByMemCluster(vresource, req); + return false; + } + + if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) { + SERVER_ERR("IsAllocatableState is failed"); + updateReasonByResourceState(resource->GetDeviceID(), req); + return false; + } + + return true; +} + +CVirtualResource *CVideoEncoderExclusiveStrategy::findCandidate(std::map vresources, CRequest *req) +{ + std::map filtered_vresources; + ExcludeResources(vresources, &filtered_vresources, req); + + req->SetResult(RMS_ERROR); + req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE); + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + if (!isAllocatableResource(vresource, req)) + continue; + + return vresource; + } + + return NULL; +} + +int CVideoEncoderExclusiveStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req) +{ + CResource *rsc = vrsc->GetResource(); + + if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK) + return RMS_ERROR; + + rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID()); + + return RMS_OK; +} + +bool CVideoEncoderExclusiveStrategy::ContainAvailableResource(std::multimap vresources, CRequest *req) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CRequester *requester = req->getRequester(); + + for (auto const &it : vresources) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId())) + continue; + + if (!resource->IsFreeState()) + continue; + + return true; + } + + return false; +} + +int CVideoEncoderExclusiveStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap *retirables, rms_error_type_e *err_type) +{ + CDependencyController *dc = CDependencyController::getInstance(); + CResource *resource = vresource->GetResource(); + CRequester *requester = req->getRequester(); + + if (!requester) { + SERVER_ERR("can't find requester"); + goto error; + } + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId())) { + if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables, requester->getAppId()) != RMS_OK) + goto error; + } + + if (!resource->IsFreeState()) { + if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK) + goto error; + } + + return RMS_OK; + +error: + if (!retirables->empty()) + retirables->clear(); + + return RMS_ERROR; +} + +void CVideoEncoderExclusiveStrategy::GetRetirableConsumers(std::multimap vresources, CRequest *req, std::multimap* retirables, rms_error_type_e *err_type) +{ + std::multimap consumer_list; + std::multimap filtered_vresources; + + ExcludeResources(vresources, &filtered_vresources, req); + + bool hasAllocatableResource = ContainAvailableResource(filtered_vresources, req); + if (hasAllocatableResource) + return; + + for (auto const &it : filtered_vresources) { + CVirtualResource *vresource = it.second; + if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK) + break; + } + + for (auto const &it : consumer_list) { + retirables->insert(std::pair(it.first, it.second)); + } +} diff --git a/src/rms_service.cpp b/src/rms_service.cpp new file mode 100644 index 0000000..2f73275 --- /dev/null +++ b/src/rms_service.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include + +int main(void) +{ + SERVER_INFO("RscMgr server main loop\n"); + trace_begin("[RSC_MGR] main start"); + trace_end(); + + GMainLoop *main_loop; + main_loop = g_main_loop_new(NULL, FALSE); + + if (!main_loop) { + SERVER_ERR("failed to create a main loop\n"); + return 0; + } + + CResourceService *service = new(std::nothrow) CResourceService; + service->Init(main_loop); + + g_main_loop_ref(main_loop); + g_main_loop_run(main_loop); + + return 0; +}