Initial Release 22/312622/18
authorYoungHun Kim <yh8004.kim@samsung.com>
Wed, 12 Jun 2024 10:19:09 +0000 (19:19 +0900)
committerYoungHun Kim <yh8004.kim@samsung.com>
Tue, 30 Jul 2024 22:06:06 +0000 (07:06 +0900)
Change-Id: I6539ef377a33ff79fde7ca709507e8f6e6adec62

106 files changed:
CMakeLists.txt [new file with mode: 0644]
LICENSE.APLv2 [new file with mode: 0644]
include_internal/CAsyncQueue.h [new file with mode: 0644]
include_internal/CCallback.h [new file with mode: 0644]
include_internal/CDbusHandler.h [new file with mode: 0644]
include_internal/CHandle.h [new file with mode: 0644]
include_internal/CHandleManager.h [new file with mode: 0644]
include_internal/CMessage.h [new file with mode: 0644]
include_internal/CMessageHandler.h [new file with mode: 0644]
include_internal/CMessageQueue.h [new file with mode: 0644]
include_internal/CQueryHandler.h [new file with mode: 0644]
include_internal/CRequest.h [new file with mode: 0644]
include_internal/CRequester.h [new file with mode: 0644]
include_internal/CResourceService.h [new file with mode: 0644]
include_internal/CSysInfo.h [new file with mode: 0644]
include_internal/manager/CCache.h [new file with mode: 0644]
include_internal/manager/CConsumer.h [new file with mode: 0644]
include_internal/manager/CConsumerContainer.h [new file with mode: 0644]
include_internal/manager/CDebugUtils.h [new file with mode: 0644]
include_internal/manager/CLockController.h [new file with mode: 0644]
include_internal/manager/CPriority.h [new file with mode: 0644]
include_internal/manager/CResource.h [new file with mode: 0644]
include_internal/manager/CResourceCategory.h [new file with mode: 0644]
include_internal/manager/CResourceDB.h [new file with mode: 0644]
include_internal/manager/CResourceManager.h [new file with mode: 0644]
include_internal/manager/CResourceObserver.h [new file with mode: 0644]
include_internal/manager/CResourceState.h [new file with mode: 0644]
include_internal/manager/CResourceSubject.h [new file with mode: 0644]
include_internal/manager/CVideoController.h [new file with mode: 0644]
include_internal/manager/CVirtualResource.h [new file with mode: 0644]
include_internal/manager/dependence/CAudioCodec.h [new file with mode: 0644]
include_internal/manager/dependence/CAudioCodecCollection.h [new file with mode: 0644]
include_internal/manager/dependence/CBandwidth.h [new file with mode: 0644]
include_internal/manager/dependence/CDependencyController.h [new file with mode: 0644]
include_internal/manager/dependence/CMemCluster.h [new file with mode: 0644]
include_internal/manager/dependence/CMixingMode.h [new file with mode: 0644]
include_internal/manager/strategy/CAllocateModeStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CAllocateModeStrategyProvider.h [new file with mode: 0644]
include_internal/manager/strategy/CAllocateStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CAllocateStrategyProvider.h [new file with mode: 0644]
include_internal/manager/strategy/CAudioDecoderStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CExclusiveStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CInvalidModeStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CMixingStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CNormalModeStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CNormalStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CPreferenceModeStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CScalerStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CVideoDecoderStrategy.h [new file with mode: 0644]
include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h [new file with mode: 0644]
include_internal/rms-dbus-interface.xml [new file with mode: 0644]
include_internal/rms_debug.h [new file with mode: 0644]
include_internal/rms_log.h [new file with mode: 0644]
include_internal/rms_type.h [new file with mode: 0644]
packaging/rscmgr-service.service [new file with mode: 0644]
packaging/rscmgr-service.spec [new file with mode: 0644]
rscmgr-service.manifest [new file with mode: 0644]
src/CAsyncQueue.cpp [new file with mode: 0644]
src/CCallback.cpp [new file with mode: 0644]
src/CDbusHandler.cpp [new file with mode: 0644]
src/CHandle.cpp [new file with mode: 0644]
src/CHandleManager.cpp [new file with mode: 0644]
src/CMessage.cpp [new file with mode: 0644]
src/CMessageHandler.cpp [new file with mode: 0644]
src/CMessageQueue.cpp [new file with mode: 0644]
src/CQueryHandler.cpp [new file with mode: 0644]
src/CRequest.cpp [new file with mode: 0644]
src/CRequester.cpp [new file with mode: 0644]
src/CResourceService.cpp [new file with mode: 0644]
src/CSysInfo.cpp [new file with mode: 0644]
src/gen_rm_msgq.cpp [new file with mode: 0644]
src/manager/CCache.cpp [new file with mode: 0644]
src/manager/CConsumer.cpp [new file with mode: 0644]
src/manager/CConsumerContainer.cpp [new file with mode: 0644]
src/manager/CDebugUtils.cpp [new file with mode: 0644]
src/manager/CLockController.cpp [new file with mode: 0644]
src/manager/CPriority.cpp [new file with mode: 0644]
src/manager/CResource.cpp [new file with mode: 0644]
src/manager/CResourceCategory.cpp [new file with mode: 0644]
src/manager/CResourceDB.cpp [new file with mode: 0644]
src/manager/CResourceManager.cpp [new file with mode: 0644]
src/manager/CResourceState.cpp [new file with mode: 0644]
src/manager/CVideoController.cpp [new file with mode: 0644]
src/manager/CVirtualResource.cpp [new file with mode: 0644]
src/manager/dependence/CAudioCodec.cpp [new file with mode: 0644]
src/manager/dependence/CAudioCodecCollection.cpp [new file with mode: 0644]
src/manager/dependence/CBandwidth.cpp [new file with mode: 0644]
src/manager/dependence/CDependencyController.cpp [new file with mode: 0644]
src/manager/dependence/CMemCluster.cpp [new file with mode: 0644]
src/manager/dependence/CMixingMode.cpp [new file with mode: 0644]
src/manager/strategy/CAllocateModeStrategyProvider.cpp [new file with mode: 0644]
src/manager/strategy/CAllocateStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CAllocateStrategyProvider.cpp [new file with mode: 0644]
src/manager/strategy/CAudioDecoderStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CExclusiveStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CInvalidModeStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CMixingStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CNormalModeStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CNormalStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CPreferenceModeStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CScalerStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CVideoDecoderStrategy.cpp [new file with mode: 0644]
src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp [new file with mode: 0644]
src/rms_service.cpp [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8162b6a
--- /dev/null
@@ -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 (file)
index 0000000..bbe9d02
--- /dev/null
@@ -0,0 +1,206 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+\r
+                                 Apache License\r
+                           Version 2.0, January 2004\r
+                        http://www.apache.org/licenses/\r
+\r
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+   1. Definitions.\r
+\r
+      "License" shall mean the terms and conditions for use, reproduction,\r
+      and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+      "Licensor" shall mean the copyright owner or entity authorized by\r
+      the copyright owner that is granting the License.\r
+\r
+      "Legal Entity" shall mean the union of the acting entity and all\r
+      other entities that control, are controlled by, or are under common\r
+      control with that entity. For the purposes of this definition,\r
+      "control" means (i) the power, direct or indirect, to cause the\r
+      direction or management of such entity, whether by contract or\r
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+      outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+      "You" (or "Your") shall mean an individual or Legal Entity\r
+      exercising permissions granted by this License.\r
+\r
+      "Source" form shall mean the preferred form for making modifications,\r
+      including but not limited to software source code, documentation\r
+      source, and configuration files.\r
+\r
+      "Object" form shall mean any form resulting from mechanical\r
+      transformation or translation of a Source form, including but\r
+      not limited to compiled object code, generated documentation,\r
+      and conversions to other media types.\r
+\r
+      "Work" shall mean the work of authorship, whether in Source or\r
+      Object form, made available under the License, as indicated by a\r
+      copyright notice that is included in or attached to the work\r
+      (an example is provided in the Appendix below).\r
+\r
+      "Derivative Works" shall mean any work, whether in Source or Object\r
+      form, that is based on (or derived from) the Work and for which the\r
+      editorial revisions, annotations, elaborations, or other modifications\r
+      represent, as a whole, an original work of authorship. For the purposes\r
+      of this License, Derivative Works shall not include works that remain\r
+      separable from, or merely link (or bind by name) to the interfaces of,\r
+      the Work and Derivative Works thereof.\r
+\r
+      "Contribution" shall mean any work of authorship, including\r
+      the original version of the Work and any modifications or additions\r
+      to that Work or Derivative Works thereof, that is intentionally\r
+      submitted to Licensor for inclusion in the Work by the copyright owner\r
+      or by an individual or Legal Entity authorized to submit on behalf of\r
+      the copyright owner. For the purposes of this definition, "submitted"\r
+      means any form of electronic, verbal, or written communication sent\r
+      to the Licensor or its representatives, including but not limited to\r
+      communication on electronic mailing lists, source code control systems,\r
+      and issue tracking systems that are managed by, or on behalf of, the\r
+      Licensor for the purpose of discussing and improving the Work, but\r
+      excluding communication that is conspicuously marked or otherwise\r
+      designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+      "Contributor" shall mean Licensor and any individual or Legal Entity\r
+      on behalf of whom a Contribution has been received by Licensor and\r
+      subsequently incorporated within the Work.\r
+\r
+   2. Grant of Copyright License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      copyright license to reproduce, prepare Derivative Works of,\r
+      publicly display, publicly perform, sublicense, and distribute the\r
+      Work and such Derivative Works in Source or Object form.\r
+\r
+   3. Grant of Patent License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      (except as stated in this section) patent license to make, have made,\r
+      use, offer to sell, sell, import, and otherwise transfer the Work,\r
+      where such license applies only to those patent claims licensable\r
+      by such Contributor that are necessarily infringed by their\r
+      Contribution(s) alone or by combination of their Contribution(s)\r
+      with the Work to which such Contribution(s) was submitted. If You\r
+      institute patent litigation against any entity (including a\r
+      cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+      or a Contribution incorporated within the Work constitutes direct\r
+      or contributory patent infringement, then any patent licenses\r
+      granted to You under this License for that Work shall terminate\r
+      as of the date such litigation is filed.\r
+\r
+   4. Redistribution. You may reproduce and distribute copies of the\r
+      Work or Derivative Works thereof in any medium, with or without\r
+      modifications, and in Source or Object form, provided that You\r
+      meet the following conditions:\r
+\r
+      (a) You must give any other recipients of the Work or\r
+          Derivative Works a copy of this License; and\r
+\r
+      (b) You must cause any modified files to carry prominent notices\r
+          stating that You changed the files; and\r
+\r
+      (c) You must retain, in the Source form of any Derivative Works\r
+          that You distribute, all copyright, patent, trademark, and\r
+          attribution notices from the Source form of the Work,\r
+          excluding those notices that do not pertain to any part of\r
+          the Derivative Works; and\r
+\r
+      (d) If the Work includes a "NOTICE" text file as part of its\r
+          distribution, then any Derivative Works that You distribute must\r
+          include a readable copy of the attribution notices contained\r
+          within such NOTICE file, excluding those notices that do not\r
+          pertain to any part of the Derivative Works, in at least one\r
+          of the following places: within a NOTICE text file distributed\r
+          as part of the Derivative Works; within the Source form or\r
+          documentation, if provided along with the Derivative Works; or,\r
+          within a display generated by the Derivative Works, if and\r
+          wherever such third-party notices normally appear. The contents\r
+          of the NOTICE file are for informational purposes only and\r
+          do not modify the License. You may add Your own attribution\r
+          notices within Derivative Works that You distribute, alongside\r
+          or as an addendum to the NOTICE text from the Work, provided\r
+          that such additional attribution notices cannot be construed\r
+          as modifying the License.\r
+\r
+      You may add Your own copyright statement to Your modifications and\r
+      may provide additional or different license terms and conditions\r
+      for use, reproduction, or distribution of Your modifications, or\r
+      for any such Derivative Works as a whole, provided Your use,\r
+      reproduction, and distribution of the Work otherwise complies with\r
+      the conditions stated in this License.\r
+\r
+   5. Submission of Contributions. Unless You explicitly state otherwise,\r
+      any Contribution intentionally submitted for inclusion in the Work\r
+      by You to the Licensor shall be under the terms and conditions of\r
+      this License, without any additional terms or conditions.\r
+      Notwithstanding the above, nothing herein shall supersede or modify\r
+      the terms of any separate license agreement you may have executed\r
+      with Licensor regarding such Contributions.\r
+\r
+   6. Trademarks. This License does not grant permission to use the trade\r
+      names, trademarks, service marks, or product names of the Licensor,\r
+      except as required for reasonable and customary use in describing the\r
+      origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+   7. Disclaimer of Warranty. Unless required by applicable law or\r
+      agreed to in writing, Licensor provides the Work (and each\r
+      Contributor provides its Contributions) on an "AS IS" BASIS,\r
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+      implied, including, without limitation, any warranties or conditions\r
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+      PARTICULAR PURPOSE. You are solely responsible for determining the\r
+      appropriateness of using or redistributing the Work and assume any\r
+      risks associated with Your exercise of permissions under this License.\r
+\r
+   8. Limitation of Liability. In no event and under no legal theory,\r
+      whether in tort (including negligence), contract, or otherwise,\r
+      unless required by applicable law (such as deliberate and grossly\r
+      negligent acts) or agreed to in writing, shall any Contributor be\r
+      liable to You for damages, including any direct, indirect, special,\r
+      incidental, or consequential damages of any character arising as a\r
+      result of this License or out of the use or inability to use the\r
+      Work (including but not limited to damages for loss of goodwill,\r
+      work stoppage, computer failure or malfunction, or any and all\r
+      other commercial damages or losses), even if such Contributor\r
+      has been advised of the possibility of such damages.\r
+\r
+   9. Accepting Warranty or Additional Liability. While redistributing\r
+      the Work or Derivative Works thereof, You may choose to offer,\r
+      and charge a fee for, acceptance of support, warranty, indemnity,\r
+      or other liability obligations and/or rights consistent with this\r
+      License. However, in accepting such obligations, You may act only\r
+      on Your own behalf and on Your sole responsibility, not on behalf\r
+      of any other Contributor, and only if You agree to indemnify,\r
+      defend, and hold each Contributor harmless for any liability\r
+      incurred by, or claims asserted against, such Contributor by reason\r
+      of your accepting any such warranty or additional liability.\r
+\r
+   END OF TERMS AND CONDITIONS\r
+\r
+   APPENDIX: How to apply the Apache License to your work.\r
+\r
+      To apply the Apache License to your work, attach the following\r
+      boilerplate notice, with the fields enclosed by brackets "[]"\r
+      replaced with your own identifying information. (Don't include\r
+      the brackets!)  The text should be enclosed in the appropriate\r
+      comment syntax for the file format. We also recommend that a\r
+      file or class name and description of purpose be included on the\r
+      same "printed page" as the copyright notice for easier\r
+      identification within third-party archives.\r
+\r
+   Copyright [yyyy] [name of copyright owner]\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+\r
+\r
diff --git a/include_internal/CAsyncQueue.h b/include_internal/CAsyncQueue.h
new file mode 100644 (file)
index 0000000..619ae3a
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __C_ASYNC_QUEUE_H__\r
+#define __C_ASYNC_QUEUE_H__\r
+\r
+#include <glib.h>\r
+\r
+typedef void (*destoryNotify)(void *data);\r
+\r
+class CAsyncQueue{\r
+public:\r
+       CAsyncQueue();\r
+       CAsyncQueue(destoryNotify destory_cb);\r
+       ~CAsyncQueue();\r
+\r
+       void push(void *data);\r
+       void push(CAsyncQueue *src_queue);\r
+       void push_front(void *data);\r
+       void push_front(CAsyncQueue *src_queue);\r
+\r
+       void *pop(void);\r
+       void *pop(unsigned int timeout_ms);\r
+\r
+       int length(void);\r
+\r
+private:\r
+       GAsyncQueue *queue;\r
+};\r
+\r
+#endif // __C_ASYNC_QUEUE_H__\r
diff --git a/include_internal/CCallback.h b/include_internal/CCallback.h
new file mode 100644 (file)
index 0000000..aee85c8
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_CCALLBACK_H__\r
+#define __RMS_CCALLBACK_H__\r
+\r
+class CCallback\r
+{\r
+public:\r
+       CCallback() {}\r
+       ~CCallback() {}\r
+\r
+       static void InitCallback(void);\r
+       static int SendCallbackMessage(int cid, int pid, void *callback_data, int size, int *err);\r
+       static int RemoveFIFOServerToClient(int pid, int cid);\r
+       static int ConvertCallbackType(int rm_return_type);\r
+       static unsigned int GetTimeout(void);\r
+};\r
+\r
+#endif //__RMS_CCALLBACK_H__\r
diff --git a/include_internal/CDbusHandler.h b/include_internal/CDbusHandler.h
new file mode 100644 (file)
index 0000000..711c1e6
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CDBUS_HANDLER_H__\r
+#define __CDBUS_HANDLER_H__\r
+\r
+#include <glib.h>\r
+#include <gio/gio.h>\r
+\r
+#include <CAsyncQueue.h>\r
+\r
+class CDbusHandler\r
+{\r
+public:\r
+       CDbusHandler(CAsyncQueue *queue);\r
+       ~CDbusHandler() = default;\r
+\r
+       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);\r
+       static void OnBusAcquired(GDBusConnection *conn, const gchar *bus_name, gpointer data);\r
+       static void OnNameLost(GDBusConnection *conn, const gchar *bus_name, gpointer data);\r
+\r
+private:\r
+\r
+       static const std::string m_methods;\r
+       static const GDBusInterfaceVTable m_vtable;\r
+\r
+       GDBusConnection *m_conn;\r
+       unsigned int m_reg_id;\r
+       unsigned int m_own_id;\r
+\r
+       CAsyncQueue *m_async_queue;\r
+\r
+       bool MakeDbusConnection(void);\r
+       void RegisterObjects(void);\r
+       void GenerateReadyEvent(void);\r
+};\r
+\r
+#endif // __CDBUS_HANDLER_H__\r
diff --git a/include_internal/CHandle.h b/include_internal/CHandle.h
new file mode 100644 (file)
index 0000000..2bc26ba
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_CHANDLE_H__\r
+#define __RMS_CHANDLE_H__\r
+#include <rms_type.h>\r
+class CHandle\r
+{\r
+public:\r
+       CHandle() {}\r
+       CHandle(int handle, int is_used, int pid);\r
+       ~CHandle() {}\r
+\r
+       int handle;\r
+       int is_used;\r
+       int pid;\r
+       int main_priority;\r
+       int sub_priority;\r
+       int app_pid;\r
+       char *app_id;\r
+       char process_name[RMS_NAME_BUF_SIZE];\r
+};\r
+\r
+#endif //__RMS_CHANDLE_H__\r
diff --git a/include_internal/CHandleManager.h b/include_internal/CHandleManager.h
new file mode 100644 (file)
index 0000000..2280b45
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_CHANDLE_MANAGER_H__\r
+#define __RMS_CHANDLE_MANAGER_H__\r
+\r
+#include <map>\r
+#include <CResourceManager.h>\r
+#include <CHandle.h>\r
+\r
+class CHandleManager\r
+{\r
+public:\r
+       CHandleManager(CResourceManager *rsc_mgr);\r
+       ~CHandleManager() {}\r
+\r
+       int GetNewHandle(int pid, int main_priority, int sub_priority, int app_pid, char *app_id);\r
+       int RemoveHandle(int handle, int pid);\r
+       int SetPriority(int handle, int main_priority, int sub_priority);\r
+       int GetPriority(int handle, int *main_priority, int *sub_priority);\r
+       int SetAppID(int handle, char *app_id);\r
+       char *GetAppID(int handle);\r
+       void ReclaimAllInvalidCustomer(int request_pid);\r
+\r
+private:\r
+       int m_RemoveHandle(int handle, int pid);\r
+       int m_IsValidHandle(int handle);\r
+       int m_ReclaimHandle(void);\r
+       int m_AddNewHandle(int handle, int pid, int main_priority, int sub_priority, int app_pid, char *app_id);\r
+       int m_PrintHandleInfo(int handle, int pid);\r
+       void m_PrintHandleList(void);\r
+       CHandle *findHandle(int id);\r
+\r
+       CResourceManager *m_rsc_mgr;\r
+       int m_next_handle;\r
+       std::map<int, CHandle*> m_handles;\r
+};\r
+\r
+#endif //__RMS_CHANDLE_MANAGER_H__\r
diff --git a/include_internal/CMessage.h b/include_internal/CMessage.h
new file mode 100644 (file)
index 0000000..fb7e3aa
--- /dev/null
@@ -0,0 +1,63 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CMESSAGE_H__\r
+#define __CMESSAGE_H__\r
+\r
+#include <iostream>\r
+#include <gio/gio.h>\r
+#include <rms_type.h>\r
+\r
+typedef enum {\r
+       MSG_SENDER_MSGQ,\r
+       MSG_SENDER_DBUS,\r
+       MSG_SENDER_INTERNAL\r
+} msg_sender_e;\r
+\r
+class CMessage\r
+{\r
+public:\r
+       CMessage(std::string name);\r
+       CMessage(rms_msg_request *msgq_req);\r
+       CMessage(GDBusMethodInvocation *invoc);\r
+       ~CMessage();\r
+\r
+       int GetReqType(void);\r
+       std::string GetName(void) { return m_name; }\r
+       msg_sender_e GetSender(void) { return m_sender; }\r
+       rms_msg_request *GetRequest(void) { return m_msgq_req; }\r
+       GDBusMethodInvocation *GetMethodInvocation(void) { return m_invoc; }\r
+\r
+       bool IsUnlockMsg(void);\r
+       bool IsMsgFor(ResourceType rsc_type);\r
+       void PrintInfo(void);\r
+\r
+private:\r
+       rms_msg_request *m_msgq_req;\r
+       GDBusMethodInvocation *m_invoc;\r
+       msg_sender_e m_sender;\r
+       std::string m_name;\r
+\r
+       void PrintDbus(void);\r
+       void PrintInternal(void);\r
+       void PrintMsgQ(void);\r
+\r
+       bool IsMsgForScaler(void);\r
+       bool IsMsgForScalerDbus(void);\r
+       bool IsMsgForScalerMsgQ(void);\r
+};\r
+\r
+#endif //__CMESSAGE_H__\r
diff --git a/include_internal/CMessageHandler.h b/include_internal/CMessageHandler.h
new file mode 100644 (file)
index 0000000..61caafd
--- /dev/null
@@ -0,0 +1,124 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_CMESSAGE_HANDLER_H__\r
+#define __RMS_CMESSAGE_HANDLER_H__\r
+\r
+#include <rms_type.h>\r
+#include <gio/gio.h>\r
+#include <glib.h>\r
+#include <map>\r
+\r
+#include <CMessage.h>\r
+#include <CQueryHandler.h>\r
+#include <CResourceManager.h>\r
+#include <CHandleManager.h>\r
+#include <CDbusHandler.h>\r
+#include <CLockController.h>\r
+#include <CMessageQueue.h>\r
+#include <CAsyncQueue.h>\r
+\r
+class CMessageHandler\r
+{\r
+public:\r
+       typedef GVariant *(CMessageHandler::*MsgHandler)(GVariant *params);\r
+\r
+       CMessageHandler(CResourceManager *rsc_mgr);\r
+       ~CMessageHandler(void);\r
+\r
+       int Run(void);\r
+       void NotifyWatchdog(void);\r
+\r
+private:\r
+       void InitDbusHandlers(void);\r
+       void InitInternalMsgHandlers(void);\r
+\r
+       static gpointer msgThread(gpointer data);\r
+       static gpointer msgQThread(gpointer data);\r
+\r
+       int ProcessMessage(void);\r
+       int ProcessCallbackMessage(rms_consumer_tobe_returned_s *consumer_info, int requester_cid);\r
+       void ProcessMessage(CAsyncQueue *queue, CMessage *msg, int cid_requester, int cid_releaser);\r
+       void ProcessMsgQMessage(CMessage *msg);\r
+       void ProcessDbusMessage(CMessage *msg);\r
+       void ProcessInternalMessage(CMessage *msg);\r
+\r
+       void EmptyPendingQueue(void);\r
+       void InsertPendingQueue(CMessage *msg);\r
+\r
+       int SendResponse(rms_msg_response *response);\r
+       int PushMessage(CAsyncQueue *queue, CMessage *msg);\r
+\r
+       bool IsRegisteredHandle(int handle);\r
+       bool IsValidProcess(int pid);\r
+       bool IsValidRequest(int req_type);\r
+       bool IsAllResourcesReclaimed(rms_consumer_tobe_returned_s *consumer_info);\r
+\r
+       int ReleaseInvalidProcessResources(int pid, int handle);\r
+       int ReclaimResources(int reason, int requester_cid, int requester_zone_id, consumer_reclaim_s *conflict_info, bool *need_response);\r
+\r
+       void SetRequesterInfo(rms_msg_request *request);\r
+\r
+       void m_ConstructResponse(rms_msg_response *response, int data_type, rms_response_type_e msg_type, int handle, int pid);\r
+       void m_ConstructRequestedDevice(rms_msg_request *request, rms_requests_device_s *requested_resource);\r
+       void m_FreeAllocatedDevice(rms_return_device_s *allocated_device);\r
+       int *m_SerializeCallbackData(const rms_consumer_tobe_returned_s *consumer_info, int reason, int *data_size);\r
+       void m_Free(consumer_reclaim_s *consumer_info);\r
+\r
+       void m_RegisterConsumer(rms_msg_request *request, rms_msg_response *response);\r
+       void m_UnregisterConsumer(rms_msg_request *request, rms_msg_response *response);\r
+       void m_AllocateResources(rms_msg_request *request, rms_msg_response *response);\r
+       void m_ReleaseResources(rms_msg_request *request, rms_msg_response *response);\r
+       void m_Query(rms_msg_request *request, rms_msg_response *response);\r
+       void m_SetConsumerPriority(rms_msg_request *request, rms_msg_response *response);\r
+       void m_SetAppID(rms_msg_request *request, rms_msg_response *response);\r
+\r
+       GVariant *RegisterResource(GVariant *params);\r
+       GVariant *GetResourceState(GVariant *params);\r
+       GVariant *GetResourceList(GVariant *params);\r
+       GVariant *GetResourceCollectionState(GVariant *params);\r
+       GVariant *FindDeviceId(GVariant *params);\r
+       GVariant *SwapResources(GVariant *params);\r
+       GVariant *GetScalerState(GVariant *params);\r
+       GVariant *GetAppId(GVariant *params);\r
+       GVariant *GetActiveAudioOut(GVariant *params);\r
+       GVariant *GetScalerHWID(GVariant *params);\r
+       GVariant *RestoreResources(GVariant *params);\r
+       GVariant *NotifyResourcePolicy(GVariant *params);\r
+       GVariant *NotifyAppZoneInfo(GVariant *params);\r
+       GVariant *NotifyWatchdog(GVariant *params);\r
+\r
+       void NotifyConflict(consumer_reclaim_s *conflict_info, int zone_id);\r
+\r
+       unsigned long m_req_timeout = 5;\r
+\r
+       CMessageQueue *msgq_rx;\r
+       CMessageQueue *msgq_tx;\r
+       CAsyncQueue *async_queue;\r
+       CAsyncQueue *async_pending_queue;\r
+       CLockController *m_lock_ctr;\r
+       CResourceManager *m_rsc_mgr;\r
+       CHandleManager *m_handle_mgr;\r
+       CQueryHandler *m_query_h;\r
+       CDbusHandler *m_dbus_h;\r
+\r
+       typedef void (CMessageHandler::*msg_handler)(rms_msg_request *request, rms_msg_response *response);\r
+       static msg_handler handlers[RMS_REQUEST_MAX];\r
+       std::map<std::string, MsgHandler> m_dbus_handlers;\r
+       std::map<std::string, MsgHandler> m_internal_msg_handlers;\r
+};\r
+\r
+#endif //__RMS_CMESSAGE_HANDLER_H__\r
diff --git a/include_internal/CMessageQueue.h b/include_internal/CMessageQueue.h
new file mode 100644 (file)
index 0000000..7630413
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CMESSAGE_QUEUE_H__\r
+#define __CMESSAGE_QUEUE_H__\r
+\r
+#include <rms_type.h>\r
+#include <CAsyncQueue.h>\r
+\r
+typedef enum {\r
+       MSG_QUEUE_RX = 0,\r
+       MSG_QUEUE_TX\r
+} msgq_type_e;\r
+\r
+class CMessageQueue{\r
+public:\r
+       CMessageQueue(msgq_type_e type);\r
+       ~CMessageQueue();\r
+\r
+       int receive(rms_msg_request *req, int msg_type);\r
+       int send(rms_msg_response *response);\r
+\r
+private:\r
+       int init(void);\r
+       int recover(void);\r
+       static int getKey(msgq_type_e type);\r
+\r
+       msgq_type_e msgq_type;\r
+       int msgq_id;\r
+\r
+       static const long msgq_size = 131072; // 128KB\r
+       static const int key_rx = 8211;\r
+       static const int key_tx = 8212;\r
+};\r
+\r
+#endif //__CMESSAGE_QUEUE_H__\r
diff --git a/include_internal/CQueryHandler.h b/include_internal/CQueryHandler.h
new file mode 100644 (file)
index 0000000..2a1bcaa
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CQUERY_HANDLER_H__\r
+#define __CQUERY_HANDLER_H__\r
+\r
+#include <rms_type.h>\r
+#include <CResourceManager.h>\r
+\r
+class CQueryHandler\r
+{\r
+public:\r
+       CQueryHandler(CResourceManager *rsc_mgr);\r
+       ~CQueryHandler();\r
+\r
+       int GetAnswer(rms_msg_request *request, int *answer_out);\r
+private:\r
+       CResourceManager *m_rsc_mgr;\r
+};\r
+\r
+#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 (file)
index 0000000..e98279b
--- /dev/null
@@ -0,0 +1,94 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CREQUEST_H__\r
+#define __CREQUEST_H__\r
+\r
+#include "rms_type.h"\r
+\r
+class CRequester;\r
+class CRequest\r
+{\r
+public:\r
+       CRequest(CRequester *requester);\r
+       ~CRequest();\r
+\r
+       CRequester *getRequester(void);\r
+\r
+       void SetCategory(int category_id, int category_option);\r
+       void SetState(int req_state);\r
+\r
+       void SetResult(rms_return_code_e req_result);\r
+       void SetReason(rms_error_type_e reason) { m_reason = reason; }\r
+       void ResetResult(void) { m_result = RMS_ERROR; }\r
+       void SetCandidateDevice(int device_id) { m_candidate_device = device_id; }\r
+       void SetAllocatedDevice(int device_id) { m_allocated_device = device_id; }\r
+       void SetAllocatedVirtualDevice(int virtual_id) { m_virtual_device = virtual_id; }\r
+\r
+       bool IsRequestByDevice(void) { return (m_device_id > 0); }\r
+       bool IsMainDeviceRequest(void);\r
+       bool IsSubDeviceRequest(void);\r
+       bool IsAIDeviceRequest(void);\r
+\r
+       rms_rsc_category_e GetCategory(void);\r
+       int GetDevice(void) { return m_device_id; }\r
+       rms_requests_resource_state_e GetState(void) { return m_state; }\r
+       rms_error_type_e GetReason(void) { return m_reason; }\r
+\r
+       rms_return_code_e GetResult(void);\r
+       int GetCandidateDevice(void) { return m_candidate_device; }\r
+       int GetAllocatedDevice(void) { return m_allocated_device; }\r
+       int GetAllocatedVirtualDevice(void) { return m_virtual_device; }\r
+       rms_mixing_mode_e GetMixingMode(void) { return m_mixing_mode; }\r
+\r
+       int GetMultiviewZoneId(void) { return m_mv_zone_id; }\r
+       void PrintResult(void);\r
+\r
+private:\r
+       rms_rsc_category_e ToVideoDecoderCategory(int category, int category_option, bool force_main, bool force_sub);\r
+       rms_rsc_category_e ToJpegDecoderCategory(int category, int category_option);\r
+       rms_rsc_category_e ToMJpegDecoderCategory(int category, int category_option);\r
+       rms_rsc_category_e ToAudioDecoderCategory(int category, int category_option, bool force_main, bool force_sub);\r
+       rms_rsc_category_e ToScalerCategory(int category, int category_option, bool force_main, bool force_sub);\r
+       rms_rsc_category_e ToAudioOutCategory(int category, int category_option, bool force_main, bool force_sub);\r
+       rms_rsc_category_e ToResourceCategory(int category, int category_option);\r
+       rms_rsc_category_e ToImageDecoderCategory(int category, int category_option);\r
+       rms_mixing_mode_e ToMixingMode(int category, int category_option);\r
+       int ToMultiviewZoneId(int category_option);\r
+       bool IsSupportedCategory(int category_option);\r
+       int UnmaskMainSubOptions(int category_option);\r
+       int UnmaskMixingOptions(int category_option);\r
+       int UnmaskMVZoneInfo(int category_option);\r
+       int UnmaskForceOptions(int category_option);\r
+\r
+       CRequester *m_requester;\r
+\r
+       int m_category_id;\r
+       int m_category_option;\r
+       rms_rsc_category_e m_category;\r
+       rms_requests_resource_state_e m_state;\r
+       rms_mixing_mode_e m_mixing_mode;\r
+       int m_device_id;\r
+\r
+       rms_return_code_e m_result;\r
+       int m_candidate_device;\r
+       int m_allocated_device;\r
+       int m_virtual_device;\r
+       int m_mv_zone_id;\r
+       rms_error_type_e m_reason;\r
+};\r
+\r
+#endif //__CREQUEST_H__\r
diff --git a/include_internal/CRequester.h b/include_internal/CRequester.h
new file mode 100644 (file)
index 0000000..03a12a0
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CREQUESTER_H__\r
+#define __CREQUESTER_H__\r
+\r
+#include <string>\r
+\r
+#include "rms_type.h"\r
+\r
+class CRequester\r
+{\r
+public:\r
+       CRequester();\r
+       CRequester(rms_msg_request *req);\r
+       ~CRequester();\r
+\r
+       int getHandle(void);\r
+       int getPid(void);\r
+       int getMainPriority(void);\r
+       int getSubPriority(void);\r
+       std::string getAppId(void) { return m_app_id; }\r
+       void SetCmdName(int pid);\r
+       std::string GetCmdName(void) { return m_cmd_name; }\r
+\r
+private:\r
+       int m_handle;\r
+       int m_pid;\r
+       int m_main_priority;\r
+       int m_sub_priority;\r
+       std::string m_app_id;\r
+       std::string m_cmd_name;\r
+};\r
+\r
+#endif // __CREQUESTER_H__\r
diff --git a/include_internal/CResourceService.h b/include_internal/CResourceService.h
new file mode 100644 (file)
index 0000000..c91d54b
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_CRESOURCE_SERVICE_H__\r
+#define __RMS_CRESOURCE_SERVICE_H__\r
+\r
+#include <gio/gio.h>\r
+#include <CMessageHandler.h>\r
+\r
+class CResourceService\r
+{\r
+public:\r
+       CResourceService(void) {}\r
+       ~CResourceService(void) {}\r
+       int Init(GMainLoop *main_loop);\r
+\r
+private:\r
+\r
+       CMessageHandler *m_msg_h;\r
+\r
+       int IsFirstLaunch(void);\r
+       void RequestColdPowerOff(void);\r
+       void CreateWatchDogTimer(void);\r
+       void SetVIPProcess(void);\r
+       static gboolean WatchDogCallback(gpointer data);\r
+       static gboolean InvalidResourceTableMsgCallback(gpointer data);\r
+};\r
+\r
+#endif //__RMS_CRESOURCE_SERVICE_H__\r
diff --git a/include_internal/CSysInfo.h b/include_internal/CSysInfo.h
new file mode 100644 (file)
index 0000000..6347f53
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CSYS_INFO_H__\r
+#define __CSYS_INFO_H__\r
+\r
+class CSysInfo\r
+{\r
+public:\r
+       ~CSysInfo() = default;\r
+\r
+       static CSysInfo *GetInstance(void);\r
+       bool IsAudioMixingSupported(void);\r
+private:\r
+       CSysInfo() = default;\r
+\r
+       static CSysInfo *m_instance;\r
+       bool m_support_audio_mixing;\r
+};\r
+\r
+#endif //__CSYS_INFO_H__\r
diff --git a/include_internal/manager/CCache.h b/include_internal/manager/CCache.h
new file mode 100644 (file)
index 0000000..60a8d8a
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CCACHE_H__\r
+#define __CCACHE_H__\r
+\r
+#include <map>\r
+\r
+class CCache\r
+{\r
+public:\r
+       static CCache *getInstance(void);\r
+       ~CCache() = default;\r
+\r
+       void Drop(void);\r
+       int GetAppStatus(std::string app_id);\r
+       void SetAppStatus(std::string app_id, int status);\r
+\r
+private:\r
+       CCache() = default;\r
+\r
+       static CCache *m_instance;\r
+       std::map<std::string, int> m_visibility; // app id, app status\r
+};\r
+\r
+#endif //__CCACHE_H__\r
diff --git a/include_internal/manager/CConsumer.h b/include_internal/manager/CConsumer.h
new file mode 100644 (file)
index 0000000..d79039f
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_CONSUMER_H__\r
+#define __RSC_MGR_SERVER_CONSUMER_H__\r
+\r
+#include <string>\r
+#include <rms_type.h>\r
+#include <set>\r
+\r
+class CConsumer\r
+{\r
+public:\r
+       CConsumer(IN const rms_consumer_s *consumer);\r
+       virtual ~CConsumer() {}\r
+\r
+       long GetPid(void) { return m_pid; }\r
+       int GetId(void) { return m_consumerID; }\r
+       void SetAppID(IN const char *app_id);\r
+       std::string GetAppID(void) { return m_app_id; }\r
+       std::string GetCmdName(void) { return m_cmd_name; }\r
+\r
+       bool AddResource(IN int device_id);\r
+       int ReleaseResource(IN int device_id);\r
+       bool IsUsingResource(IN int device_id);\r
+       std::set<int> GetResources(void) { return m_resources; }\r
+       int GetResourceNum(void) { return m_resources.size(); }\r
+\r
+       void SetPriority(rms_priority_s priority) { m_priority = priority; }\r
+       rms_error_type_e ComparePriority(CConsumer *requester);\r
+\r
+private:\r
+       rms_priority_s GetPriority(void) { return m_priority; }\r
+       bool ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2);\r
+       bool CheckVisibility(IN std::string app_id_requester);\r
+       bool GetAppVisibility(IN std::string app_id, bool requester);\r
+       bool CheckWebAppState(IN std::string app_id_requesting);\r
+       bool IsVisibleStatus(int status);\r
+       bool NeedStatusUpdate(std::string app_id);\r
+       int UpdateAppStatus(std::string app_id);\r
+       void SetCmdName(long pid);\r
+       std::string GetAppId(int pid);\r
+\r
+       std::set<int> m_resources;\r
+\r
+       int m_consumerID;\r
+       rms_priority_s m_priority;\r
+       long m_pid;\r
+       std::string m_app_id;\r
+       std::string m_cmd_name;\r
+};\r
+\r
+\r
+#endif // __RSC_MGR_SERVER_CONSUMER_H__\r
diff --git a/include_internal/manager/CConsumerContainer.h b/include_internal/manager/CConsumerContainer.h
new file mode 100644 (file)
index 0000000..1a6c765
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CCONSUMER_CONTAINER_H__\r
+#define __CCONSUMER_CONTAINER_H__\r
+\r
+#include <map>\r
+\r
+class CConsumer;\r
+class CConsumerContainer\r
+{\r
+public:\r
+       static CConsumerContainer *getInstance(void);\r
+       ~CConsumerContainer() = default;\r
+\r
+       bool AddConsumer(int consumer_id, CConsumer *consumer);\r
+       void RemoveConsumer(int consumer_id);\r
+       CConsumer *findConsumer(int consumer_id);\r
+       std::map<int, CConsumer*> FindConsumers(std::string app_id);\r
+       std::map<int, CConsumer*> findConsumers(int pid);\r
+\r
+private:\r
+       CConsumerContainer() = default;\r
+\r
+       static CConsumerContainer *m_instance;\r
+       std::map<int, CConsumer*> m_consumers;\r
+};\r
+\r
+#endif // __CCONSUMER_CONTAINER_H__\r
diff --git a/include_internal/manager/CDebugUtils.h b/include_internal/manager/CDebugUtils.h
new file mode 100644 (file)
index 0000000..8ce5a50
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_DEBUGUTILS_H__\r
+#define __RSC_MGR_SERVER_DEBUGUTILS_H__\r
+\r
+#include <rms_type.h>\r
+#include <sys/types.h>\r
+#include <assert.h>\r
+\r
+#define RMS_CONSOLE_BUF_SIZE 256\r
+\r
+typedef enum {\r
+       RMS_ALARM_NO_CALLBACK_RESPONSE,\r
+       RMS_ALARM_NO_DEALLOCATION,\r
+} rms_alarm_reason_e;\r
+\r
+const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum);\r
+const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum);\r
+const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum);\r
+const char *rm_print_allocation_failure_reason(int ret_value);\r
+const char *rm_convert_device_enum_to_string(rms_device_e device_enum);\r
+\r
+int rms_get_cmd_name(pid_t pid, char *name_out, int size);\r
+void rms_print_log_console(char *buf);\r
+\r
+int rm_get_product_type(void);\r
+int rm_is_valid_pid(int pid);\r
+int rms_report_emergency(IN int cid, IN int pid, IN int requester);\r
+\r
+int is_symlink_file(const char *path);\r
+const char *rm_convert_error_type_to_string(rms_error_type_e error_type);\r
+\r
+void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info);\r
+void rms_display_resource_table_error_popup(void);\r
+void rms_print_model_info(void);\r
+\r
+bool process_htable_contains(const char *name);\r
+\r
+#endif //__RSC_MGR_SERVER_DEBUGUTILS_H__\r
diff --git a/include_internal/manager/CLockController.h b/include_internal/manager/CLockController.h
new file mode 100644 (file)
index 0000000..24a85ed
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CLOCK_CONTROLLER_H__\r
+#define __CLOCK_CONTROLLER_H__\r
+\r
+#include <map>\r
+#include <CAsyncQueue.h>\r
+#include <CMessage.h>\r
+\r
+class CLockController\r
+{\r
+public:\r
+       static CLockController *GetInstance(void);\r
+       void SetMsgQ(CAsyncQueue *queue) { m_msg_q = queue; }\r
+\r
+       void Lock(ResourceType rsc_type);\r
+       void Unlock(ResourceType rsc_type);\r
+       unsigned int GetLockCount(void);\r
+       bool IsLocked(CMessage *msg);\r
+\r
+private:\r
+       CLockController() = default;\r
+       ~CLockController() = default;\r
+       void NotifyUnlock(void);\r
+\r
+       static CLockController *m_instance;\r
+       std::map<ResourceType, unsigned int> m_locks;\r
+       CAsyncQueue *m_msg_q;\r
+};\r
+\r
+#endif //__CLOCK_CONTROLLER_H__S\r
diff --git a/include_internal/manager/CPriority.h b/include_internal/manager/CPriority.h
new file mode 100644 (file)
index 0000000..21cde0f
--- /dev/null
@@ -0,0 +1,42 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CPRIORITY_H__\r
+#define __CPRIORITY_H__\r
+\r
+#include <rms_type.h>\r
+\r
+enum {\r
+       LOW_PRIORITY = -1,\r
+       SAME_PRIORITY = 0,\r
+       HIGH_PRIORITY = 1\r
+};\r
+\r
+class CPriority\r
+{\r
+public:;\r
+       ~CPriority();\r
+\r
+       static bool isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type);\r
+       static int compareCurConsumers(int device_id, int consumer_id);\r
+       static int compare(int cur_consumer_id, int consumer_id);\r
+       static int getReclaimableConsumers(int device_id, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type);\r
+       static int getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type);\r
+private:\r
+       CPriority();\r
+};\r
+\r
+#endif //__CPRIORITY_H__\r
diff --git a/include_internal/manager/CResource.h b/include_internal/manager/CResource.h
new file mode 100644 (file)
index 0000000..f4d1da1
--- /dev/null
@@ -0,0 +1,140 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_RESOURCE_H__\r
+#define __RSC_MGR_SERVER_RESOURCE_H__\r
+\r
+#include <vector>\r
+#include <map>\r
+#include <set>\r
+\r
+#include <rms_type.h>\r
+#include <CResourceSubject.h>\r
+\r
+class CResource : public CResourceSubject\r
+{\r
+public:\r
+       CResource(IN const int device_id, IN const rms_rsc_category_e category_type, IN const char *name, IN const char *path, \r
+                    IN std::set<unsigned int> mem_cluster, IN int is_main_device, IN const char *audio_codec, IN int sharable_count);\r
+       ~CResource();\r
+\r
+       std::string GetName(void) { return std::string(m_device_name); }\r
+       int GetDeviceID(void) { return m_id; }\r
+       int GetVirtualResourceID(void) { return m_vrsc_id; }\r
+       const char *GetDevicePath(void) { return m_device_path; }\r
+       std::string GetAudioCodec(void) { return m_audio_codec; }\r
+       rms_mixing_mode_e GetMixingMode(void) { return m_mixing_mode; }\r
+       rms_rsc_category_e GetCategoryType(void) { return m_category_type; }\r
+       int GetCurCategory(void) { return m_cur_category; }\r
+       int getSharableCount(void) { return (m_sharable_count - m_shared_count - m_reserved_count); }\r
+       int GetCategoryClass(void) { return m_category_class; }\r
+\r
+       bool IsFreeState(void) { return m_state == RMS_INTERNAL_STATE_FREE; };\r
+       bool IsAllocatableState(IN rms_requests_resource_state_e requested_state);\r
+       bool IsSharableState(void) { return (m_state == RMS_INTERNAL_STATE_FREE || m_state == RMS_INTERNAL_STATE_SHARABLE); }\r
+       bool IsReserved(void) { return m_is_reserved; }\r
+       bool IsSharableDevice(void) { return (m_sharable_count >= 2); }\r
+       bool IsMainDevice(void) { return m_is_main_device; }\r
+       bool IsAudioDevice(void);\r
+       bool IsVideoDecoder(void);\r
+       bool IsScaler(void) { return m_is_scaler; }\r
+       bool IsJpegDecoder(void);\r
+\r
+       void AddConsumer(IN int consumer_id, IN rms_requests_resource_state_e state);\r
+       void ResetConsumer(std::set<int> new_consumers);\r
+       int RemoveConsumer(IN int consumer_id, IN bool force);\r
+       std::set<int> GetConsumers(void) { return m_consumer_ids; }\r
+       int GetFirstConsumer(void);\r
+\r
+       int Reserve(IN int consumer_id, rms_requests_resource_state_e state);\r
+       void CancelReservation(rms_requests_resource_state_e state);\r
+\r
+       void SetDefaultBW(unsigned int bw);\r
+       unsigned int GetBW(void) { return m_occupied_bw; }\r
+       int GetDefaultBW(void) { return m_default_bw; }\r
+       void ResetBW(void) { m_occupied_bw = m_default_bw; }\r
+       void SetAllocatedTime(void);\r
+       unsigned long GetAllocatedTime(void) { return m_allocated_time; }\r
+\r
+       void SetVirtualDeviceId(int id) { m_virtual_id = id; }\r
+       int GetVirtualDeviceId(void);\r
+       void SetDedicatedVirtualDeviceId(int id) { m_dedicated_virtual_id = id; }\r
+       int GetDedicatedVirtualDeviceId(void) { return m_dedicated_virtual_id; }\r
+\r
+       std::set<unsigned int> GetMemClusters(void) { return m_mem_clusters; }\r
+       void UpdateProperties(std::set<unsigned int> mem_clusters, int bw, int category, int category_class, int vrsc_id);\r
+       void UpdateAudioCodec(std::string codec_name);\r
+       void updateMixingMode(rms_mixing_mode_e mode) { m_mixing_mode = mode; }\r
+\r
+       void RegisterObserver(CResourceObserver *observer);\r
+       void UnregisterObserver(CResourceObserver *observer);\r
+\r
+       bool Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id);\r
+       int GetState(void) { return (int) m_state; }\r
+       int GetZoneId(void) { return m_mv_zone_id; }\r
+       void SetZoneId(int zone_id);\r
+\r
+       void ChangeState(rms_resource_internal_state_e next_state);\r
+\r
+private:\r
+       void m_SetSubScalerFlag(int next_state);\r
+       bool IsRegisteredConsumer(int consumer_id);\r
+       int IncreaseRefCount(int consumer_id);\r
+       int DecreaseRefCount(int consumer_id);\r
+       void NotifyObservers(resource_update_type_e type, int consumer_id);\r
+       bool ChangeStateByAllocation(IN rms_requests_resource_state_e state, const int consumer_id, int mv_zone_id);\r
+       bool ChangeStateByRelease(int consumer_id);\r
+       bool IsScaler(rms_rsc_category_e category);\r
+\r
+       int ReserveExclusive(int consumer_id);\r
+       int ReserveShared(int consumer_id);\r
+\r
+       std::map<int, int> m_consumers; // consumer id, cnt\r
+       std::set<int> m_shared_consumers;\r
+       std::set<int> m_consumer_ids;\r
+\r
+       int m_id;\r
+       int m_vrsc_id;\r
+       int m_virtual_id;\r
+       int m_dedicated_virtual_id;\r
+       rms_resource_internal_state_e m_state;\r
+       rms_rsc_category_e m_category_type;\r
+       const char *m_device_name;\r
+       const char *m_device_path;\r
+       int m_category_class;\r
+       int m_cur_category;\r
+\r
+       unsigned int m_occupied_bw;\r
+       unsigned int m_default_bw;\r
+       int m_is_main_device;\r
+       int m_sharable_count;\r
+\r
+       bool m_is_reserved;\r
+       bool m_is_scaler;\r
+       int m_reserved_consumer_id;\r
+       unsigned long m_allocated_time;\r
+\r
+       int m_shared_count;\r
+       int m_reserved_count;\r
+       int m_mv_zone_id;\r
+\r
+       std::string m_audio_codec;\r
+       std::vector<CResourceObserver*> m_observers;\r
+       std::set<unsigned int> m_mem_clusters;\r
+       rms_mixing_mode_e m_mixing_mode;\r
+};\r
+\r
+#endif // __RSC_MGR_SERVER_RESOURCE_H__\r
diff --git a/include_internal/manager/CResourceCategory.h b/include_internal/manager/CResourceCategory.h
new file mode 100644 (file)
index 0000000..6fdd6ac
--- /dev/null
@@ -0,0 +1,55 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_CATEGORY_H__\r
+#define __RSC_MGR_SERVER_CATEGORY_H__\r
+\r
+#include <rms_type.h>\r
+#include <CResource.h>\r
+#include <map>\r
+#include <vector>\r
+\r
+#include <CRequest.h>\r
+\r
+class CConsumer;\r
+class CVirtualResource;\r
+class CRequest;\r
+class CAllocateStrategy;\r
+class CResourceCategory\r
+{\r
+public:\r
+       CResourceCategory(rms_rsc_category_e resource_category_id, int category_class);\r
+       virtual ~CResourceCategory() {}\r
+\r
+       rms_rsc_category_e GetCategoryID(void) { return m_categoryID; }\r
+       void AddVirtualResource(IN int device_id, IN CVirtualResource *vresource);\r
+\r
+       CResource *ReserveCandidate(CRequest *req, bool apply_promotion);\r
+       void GetRetirableConsumers(CRequest *req, std::multimap<int, int>* return_ids_in_category, rms_error_type_e *err_type);\r
+       bool hasFreeStateResource(void);\r
+       bool IsAvailableToUse(rms_requests_resource_state_e request_state);\r
+       void GetResources(std::map<int, CResource*> *resource_map);\r
+       CResource *FindMainResource(void);\r
+private:\r
+       std::map<int, CVirtualResource *> m_device_id_to_vresource_map;\r
+\r
+       rms_rsc_category_e m_categoryID;\r
+       CAllocateStrategy *m_alloc_strategy;\r
+\r
+       void MakeResourceMapSortedByAllocTime(std::multimap<unsigned long, CVirtualResource *> *time_resource_map);\r
+};\r
+\r
+#endif // __RSC_MGR_SERVER_CATEGORY_H__\r
diff --git a/include_internal/manager/CResourceDB.h b/include_internal/manager/CResourceDB.h
new file mode 100644 (file)
index 0000000..99d6609
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_DB_H__\r
+#define __RSC_MGR_SERVER_DB_H__\r
+\r
+#include <map>\r
+#include <glib.h>\r
+#include <rms_type.h>\r
+#include <CResourceObserver.h>\r
+#include <CResourceCategory.h>\r
+\r
+class CResourceCategory;\r
+class CVirtualResource;\r
+class CResource;\r
+class CResourceDB : public CResourceObserver\r
+{\r
+public:\r
+       CResourceDB(void) = default;\r
+       virtual ~CResourceDB(void) {}\r
+       static CResourceDB *getInstance(void);\r
+\r
+       void AddVirtualResource(IN CVirtualResource *vrsc, IN rms_rsc_category_e resource_category_id, IN const char *name,\r
+                                      IN const char *path, IN std::set<unsigned int> mem_cluster_info,\r
+                                      IN unsigned int device_id_unique, IN int is_main_device, IN const char *audio_codec,\r
+                                      IN int sharable_count, IN int mixing_count, IN CResourceObserver *observer);\r
+\r
+       void AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category);\r
+\r
+       CResourceCategory *FindResourceCategory(IN rms_rsc_category_e category_id);\r
+       CResource *FindResource(IN const int device_id);\r
+       CVirtualResource *FindVirtualResource(const int vid);\r
+       int FindRealDeviceId(int virtual_id);\r
+       void FindMainResources(IN std::map<int, CResource*> *resource_map);\r
+       void FindActiveVideoDecoders(IN std::map<int, CResource*> *resource_map);\r
+\r
+       void SetMaxVideoDecoders(int n_decs) { m_max_vdecs = n_decs; }\r
+       std::map<int, int> GetActiveVideoDecoders(void) { return m_active_vdecs; }\r
+       std::map<int, int> GetActiveNVideoDecoders(void) { return m_active_nvdecs; }\r
+       int GetActiveDecoderNum(void);\r
+       bool HasAvailableDecoder(void);\r
+       bool HasAvailableDecoderNDecoding(void);\r
+       bool HasAvailableDecoder(std::multimap<int, int> retirables);\r
+       bool HasAvailableDecoderNDecoding(std::multimap<int, int> retirables);\r
+       void AddReclaimResources(consumer_reclaim_s *consumers);\r
+       void ClearReclaimResources(void);\r
+       void Update(resource_update_type_e type, const int device_id, const int consumer_id);\r
+\r
+       void InitScalerTable(void);\r
+       int SwapScaler(int id_a, int id_b);\r
+       void GetScalerList(std::map<int, CResource*> *scalers);\r
+       int ToScalerId(int device_id);\r
+       void UpdateVirtualScalerIds(void);\r
+       void ResetZoneIds(void);\r
+\r
+       static gboolean NotifyResourceStateUpdated(gpointer data);\r
+private:\r
+       CResource *FindResource(const char *device_name);\r
+       CResource *FindMainResource(rms_rsc_category_e category_id);\r
+\r
+       void AddDeviceID(IN int device_id, IN CResource *resource);\r
+       void AddDeviceName(IN const char *device_name, IN CResource *resource);\r
+       void AddVirtualDeviceID(IN CVirtualResource *vresource);\r
+\r
+       void UpdateBWbyRelease(CResource *resource);\r
+       void UpdateBWbyAllocation(const unsigned int bandwidth, CResource *resource);\r
+       void UpdateByRelease(CResource *resource, const int device_id, const int consumer_id);\r
+       void UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id);\r
+       void SetVirtualScalerId(CResource *resource);\r
+       int GetVirtualScalerId(CResource *resource);\r
+       int GetDedicatedVirtualScalerId(int device_id);\r
+       void PrintVirtualScalerMap(void);\r
+\r
+       void AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class);\r
+       void RemoveActiveVideoDecoder(const int device_id, const int category_class);\r
+       void AddActiveJpegDecoder(const int device_id, const int consumer_id);\r
+       void RemoveActiveJpegDecoder(const int device_id);\r
+       void PrintVideoDecoderConsumers(void);\r
+\r
+       void NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id);\r
+\r
+       CResource *FindScaler(int id);\r
+       void InsertVirtualScaler(int virtual_id, CResource *resource);\r
+       void SwapResource(std::set<int> consumers, int cur_device_id, int new_device_id);\r
+       void UpdateConsumerInfoOfResource(CResource *resource, std::set<int> new_consumers, int new_virtual_id);\r
+\r
+       int CountNDecoders(std::map<int, int> retirables);\r
+       void InsertResourceHasZoneId(CResource *resource);\r
+       void RemoveResourceHasZoneId(int device_id);\r
+       std::map<rms_rsc_category_e, CResourceCategory*> m_resourceCategoryMap; //category info\r
+       std::map<int, CVirtualResource *> m_v_deviceid_to_rsc;\r
+       std::map<int, CResource*> m_deviceid_to_rsc;\r
+       std::map<std::string, CResource*> m_devicename_to_rsc;\r
+       std::map<int, CResource*> m_scaler_map;\r
+       std::map<int, CResource*> m_rscs_has_zone_id;\r
+\r
+       static CResourceDB *m_instance;\r
+       unsigned int m_device_id; //for virtual resource\r
+       int m_max_vdecs;\r
+\r
+       std::set<int> m_reclaim_rscs; // resources reclaiming\r
+       std::map<int, int> m_active_vdecs; // device id, consumer id\r
+       std::map<int, int> m_active_jdecs; // device id, consumer id\r
+       std::map<int, int> m_active_nvdecs; // device id, consumer id\r
+};\r
+\r
+#endif // __RSC_MGR_SERVER_DB_H__\r
diff --git a/include_internal/manager/CResourceManager.h b/include_internal/manager/CResourceManager.h
new file mode 100644 (file)
index 0000000..f25b963
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RSC_MGR_SERVER_MANAGER_H__\r
+#define __RSC_MGR_SERVER_MANAGER_H__\r
+#include <glib.h>\r
+#include <CConsumer.h>\r
+#include <rms_type.h>\r
+#include <map>\r
+#include <CResourceDB.h>\r
+#include <CConsumerContainer.h>\r
+\r
+class CResourceManager\r
+{\r
+public:\r
+       CResourceManager();\r
+       ~CResourceManager() = default;\r
+\r
+       int AllocateResources(rms_msg_request *req, rms_return_device_s *allocated_devices);\r
+       int ReleaseResourcesOfPid(IN const int pid);\r
+       int ReleaseResources(IN int consumer_id, IN const rms_requests_device_s *req);\r
+       int RegisterResources(void);\r
+\r
+       int SetAppId(IN int consumer_id, IN const char *app_id);\r
+       int RegisterConsumer(int consumer_id, int process_id, const char *app_id, int main_priority, int sub_priority);\r
+       int UnregisterConsumer(IN int consumer_id);\r
+       int FindReclaimableConsumers(rms_msg_request *req, consumer_reclaim_s *return_consumer, int *zone_id);\r
+       int GetActiveDecoderNum(void);\r
+       int GetActiveAudioOut(int consumer_id);\r
+\r
+       int IsCategoryAvailableToUse(rms_msg_request *request, int *is_available);\r
+       bool IsReclaimed(IN const int device_id, IN const int consumer_id);\r
+\r
+       int GetResourceState(int device_id);\r
+       int FindDeviceId(int virtual_id);\r
+       int GetResourceList(int category_id, GVariantBuilder *builder);\r
+       int GetScalerState(GVariantBuilder *builder);\r
+       int GetResourceCollectionState(int collection, GVariantBuilder *builder);\r
+       int SwapResources(int device_id_a, int device_id_b);\r
+       int RestoreResources(int category_id);\r
+       int GetScalerHWId(int zone_id);\r
+       int GetZoneId(int device_id);\r
+       void ResetZoneIds(void);\r
+       void UpdateZoneIds(std::string app_id, int zone_id);\r
+\r
+private:\r
+       void MakeRequests(CRequester *requester, rms_msg_request *reqs, std::vector<CRequest*> *requests);\r
+       void AllocateCandidates(std::vector<CRequest *> requests);\r
+       void ReleaseResources(const int consumer_id);\r
+       int GetScalerState(int category_id, GVariantBuilder *builder);\r
+\r
+       void MakeResourceMapPerConsumer(std::multimap<int, int> *device_id_to_consumer_id_map, std::map<int, std::set<int> > *consumer_id_to_resource_set_map);\r
+       void MakeConsumerInfoToBeReturned(consumer_reclaim_s *return_consumer, std::map<int, std::set<int> > *consumer_id_to_resource_set_map);\r
+       void PrintConsumerInfoToBeReturned(consumer_reclaim_s *consumer_info);\r
+\r
+       CResourceDB *m_db;\r
+\r
+       int m_is_db_created;\r
+       rms_error_type_e m_error_type;\r
+       CConsumerContainer *m_consumers;\r
+\r
+};\r
+\r
+#endif // __RSC_MGR_SERVER_MANAGER_H__\r
diff --git a/include_internal/manager/CResourceObserver.h b/include_internal/manager/CResourceObserver.h
new file mode 100644 (file)
index 0000000..9c1f246
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CRESOURCE_OBSERVER_H__\r
+#define __CRESOURCE_OBSERVER_H__\r
+\r
+typedef enum _resource_update_type_e {\r
+       UPDATED_BY_ALLOC = 0,\r
+       UPDATED_BY_RELEASE\r
+} resource_update_type_e;\r
+\r
+class CResourceObserver\r
+{\r
+public:\r
+       virtual ~CResourceObserver() {}\r
+       virtual void Update(resource_update_type_e type, const int device_id, const int consumer_id) = 0;\r
+};\r
+\r
+#endif // __CRESOURCE_OBSERVER_H__\r
diff --git a/include_internal/manager/CResourceState.h b/include_internal/manager/CResourceState.h
new file mode 100644 (file)
index 0000000..5064e66
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+\r
+#ifndef __CRESOURCE_STATE_H__\r
+#include <iostream>\r
+\r
+class CResourceState\r
+{\r
+public:\r
+       CResourceState(int device_id, int category_type, int consumer_id, int state, std::string app_id);\r
+       ~CResourceState() = default;\r
+\r
+       int GetDeviceId(void) { return m_device_id; }\r
+       int GetConsumerId(void) { return m_consumer_id; }\r
+       int GetState(void) { return m_state; }\r
+       int GetCategoryType(void) { return m_category_type; }\r
+       std::string GetAppId(void) { return m_app_id; }\r
+\r
+private:\r
+       int m_device_id;\r
+       int m_consumer_id;\r
+       int m_state;\r
+       int m_category_type;\r
+       std::string m_app_id;\r
+};\r
+\r
+#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 (file)
index 0000000..d8c2aaf
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CRESOURCE_SUBJECT_H__\r
+#define __CRESOURCE_SUBJECT_H__\r
+\r
+#include <CResourceObserver.h>\r
+\r
+class CResourceObserver;\r
+class CResourceSubject\r
+{\r
+public:\r
+       virtual ~CResourceSubject() {}\r
+\r
+       virtual void RegisterObserver(CResourceObserver *observer) = 0;\r
+       virtual void UnregisterObserver(CResourceObserver *observer) = 0;\r
+       virtual void NotifyObservers(resource_update_type_e type, const int consumer_id) = 0;\r
+};\r
+\r
+#endif // __CRESOURCE_SUBJECT_H__\r
+\r
diff --git a/include_internal/manager/CVideoController.h b/include_internal/manager/CVideoController.h
new file mode 100644 (file)
index 0000000..d6ec594
--- /dev/null
@@ -0,0 +1,54 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __C_VIDEO_CONTROLLER_H__\r
+#define __C_VIDEO_CONTROLLER_H__\r
+\r
+#include <map>\r
+#include <glib.h>\r
+#include <wayland-client.h>\r
+#include <CLockController.h>\r
+\r
+class CVideoController\r
+{\r
+public:\r
+       ~CVideoController(void);\r
+       static CVideoController *GetInstance(void);\r
+       void UpdateVirtualScalerIds(std::map<int, int> scaler_id_map);\r
+\r
+private:\r
+       typedef struct _scaler_id_pair {\r
+               unsigned int virtual_scaler_id;\r
+               unsigned int scaler_id;\r
+       } scaler_id_pair_t;\r
+\r
+       CVideoController(void);\r
+       void WaylandDisplayCreate(void);\r
+       void WaylandDisplayDestroy(void);\r
+       void RunWaitingThread(void);\r
+       static gpointer WaitingThread(gpointer data);\r
+\r
+       static CVideoController *m_instance;\r
+       struct wl_display *m_wl_display;\r
+       struct wl_registry *m_wl_registry;\r
+       struct tizen_video_rsc *m_tizen_video_rsc;\r
+       struct wl_registry_listener m_registry_listener;\r
+\r
+       GThread *m_waiting_thread;\r
+       CLockController *m_lock_ctr;\r
+};\r
+\r
+#endif //__C_VIDEO_CONTROLLER_H__\r
diff --git a/include_internal/manager/CVirtualResource.h b/include_internal/manager/CVirtualResource.h
new file mode 100644 (file)
index 0000000..a5771b3
--- /dev/null
@@ -0,0 +1,56 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef _RM_VIRTUAL_RESOURCE_H_INCLUDED\r
+#define _RM_VIRTUAL_RESOURCE_H_INCLUDED\r
+\r
+#include <rms_type.h>\r
+#include <map>\r
+#include <set>\r
+\r
+class CResource;\r
+class CVirtualResource\r
+{\r
+public:\r
+       CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set<unsigned int> dependent, bool is_main_device, const char *audio_codec, int category_class);\r
+       virtual ~CVirtualResource(void) {}\r
+\r
+       CResource *GetResource(void) { return m_rsc; }\r
+       void SetResource(CResource *resource);\r
+\r
+       int GetVResourceID(void) { return m_vir_rsc_id; }\r
+       rms_rsc_category_e GetCategoryType(void) { return m_category_type; }\r
+       int GetCategoryClass(void) { return m_category_class; }\r
+       unsigned int GetBW(void) { return m_vir_rsc_bw; }\r
+       std::set<unsigned int> GetMemClusters(void) { return m_mem_clusters; }\r
+       std::string GetAudioCodec(void) { return m_audio_codec; }\r
+\r
+       bool IsMainDevice(void) { return m_is_main_device; }\r
+       bool IsAIDevice(void) { return m_is_ai_device; }\r
+private:\r
+       int m_vir_rsc_id;\r
+       rms_rsc_category_e m_category_type;\r
+       unsigned int m_vir_rsc_bw;\r
+       bool m_is_main_device;\r
+       bool m_is_ai_device;\r
+       int m_category_class;\r
+       std::set<unsigned int> m_mem_clusters;\r
+       std::string m_audio_codec;\r
+\r
+       CResource *m_rsc;\r
+};\r
+\r
+#endif // _RM_VIRTUAL_RESOURCE_H_INCLUDED\r
diff --git a/include_internal/manager/dependence/CAudioCodec.h b/include_internal/manager/dependence/CAudioCodec.h
new file mode 100644 (file)
index 0000000..1dcb59a
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CAUDIO_CODEC_H__\r
+#define __CAUDIO_CODEC_H__\r
+\r
+#include <map>\r
+#include <set>\r
+#include <string>\r
+\r
+class CAudioCodec{\r
+public:\r
+       CAudioCodec(const char *name);\r
+       ~CAudioCodec();\r
+\r
+       std::string getName(void) { return m_name; }\r
+       std::set<int> getResourcesOfConsumer(int consumer_id);\r
+\r
+       void increaseRef(int device_id, int consumer_id);\r
+       void decreaseRef(int device_id, int consumer_id);\r
+       void increaseMaxRef(void);\r
+\r
+       bool isAvailableToUse(void);\r
+       bool isMixingSupported(void) { return (m_ref_count_max >= 2 || m_name.length() == 0); }\r
+       bool canBeUsedByMultiApp(void) { return (m_name.length() == 0); }\r
+       std::map<int, int> GetConsumers(void) { return m_consumers; }\r
+\r
+private:\r
+       bool isUnknownCodec(void) { return (m_name.length() == 0); }\r
+       std::string m_name;\r
+       unsigned int m_ref_count;\r
+       unsigned int m_ref_count_max;\r
+       std::map<int, int> m_consumers; // consumer id, ref_count\r
+       std::map<int, int> m_resources; // device_id, consumer id\r
+};\r
+\r
+#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 (file)
index 0000000..15b6633
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CAUDIO_CODEC_COLLECTION_H__\r
+#define __CAUDIO_CODEC_COLLECTION_H__\r
+\r
+#include <map>\r
+#include <string>\r
+\r
+class CAudioCodec;\r
+class CAudioCodecCollection {\r
+public:\r
+       static CAudioCodecCollection *getInstance();\r
+       ~CAudioCodecCollection();\r
+\r
+       void registerAudioCodec(const char *name, int count);\r
+       CAudioCodec *findAudioCodec(std::string name);\r
+private:\r
+       CAudioCodecCollection();\r
+\r
+       static CAudioCodecCollection *m_instance;\r
+       std::map<std::string, CAudioCodec*> m_audio_codecs;\r
+};\r
+\r
+#endif //__CAUDIO_CODEC_COLLECTION_H__\r
diff --git a/include_internal/manager/dependence/CBandwidth.h b/include_internal/manager/dependence/CBandwidth.h
new file mode 100644 (file)
index 0000000..68bdfdc
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CBANDWIDTH_H__\r
+#define __CBANDWIDTH_H__\r
+\r
+#include <map>\r
+#include <set>\r
+\r
+class CBandwidth\r
+{\r
+public:\r
+       static CBandwidth *GetInstance();\r
+\r
+       void SetMax(unsigned int max) { m_max = m_avail = max; }\r
+       unsigned int GetMax(void) { return m_max; }\r
+       unsigned int GetAvail(void) { return m_avail; }\r
+       void AddConsumer(int device_id, int consumer_id, int category_id, int category_class);\r
+       void RemoveConsumer(int device_id, int category_id, int category_class);\r
+       void Decrease(unsigned int bw, int category_id, int category_class, int device_id);\r
+       void Increase(unsigned int bw, int category_id, int category_class, int device_id);\r
+       int GetNConsumersNDec(int category_id);\r
+       void GetConsumersNDec(int category_id, std::map<int, int> *consumers);\r
+       std::map<int, int> GetConsumers(void) { return m_consumers; }\r
+\r
+private:\r
+       static CBandwidth *m_instance;\r
+\r
+       void AddConsumerNDec(int device_id, int consumer_id, int category_id);\r
+       void RemoveConsumerNDec(int device_id, int category_id);\r
+       bool IncludeSameDeviceGroup(int category_id, int device_id);\r
+       bool IsSameMemClusters(std::set<unsigned int> c_mc, std::set<unsigned int> u_mc);\r
+\r
+       std::map<int, int> m_consumers; // device_id, consumer_id\r
+       std::map<int, std::map<int, int>> m_ndec_consumers; // category id, <device_id, consumer_id>\r
+       unsigned int m_max;\r
+       unsigned int m_avail;\r
+};\r
+\r
+#endif //__CBANDWIDTH_H__\r
diff --git a/include_internal/manager/dependence/CDependencyController.h b/include_internal/manager/dependence/CDependencyController.h
new file mode 100644 (file)
index 0000000..d85fe4f
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CDEPENDENCY_CONTROLLER_H__\r
+#define __CDEPENDENCY_CONTROLLER_H__\r
+\r
+#include <map>\r
+#include <set>\r
+#include <CResourceObserver.h>\r
+\r
+class CMemCluster;\r
+class CMixingMode;\r
+class CAudioCodec;\r
+class CResourceObserver;\r
+class CDependencyController : public CResourceObserver\r
+{\r
+public:\r
+       static CDependencyController *getInstance(void);\r
+       ~CDependencyController();\r
+\r
+       void RegisterMemCluster(unsigned int id);\r
+       bool isAvailableMemClusters(std::set<unsigned int> mc_ids);\r
+       bool isAvailableMemClusters(std::set<unsigned int> mc_ids, int category_class, int category_id);\r
+       bool isAvailableMemClusters(std::set<unsigned int> mc_ids, std::string app_id);\r
+       bool isSharableMemClusters(std::set<unsigned int> mc_ids, int device_id);\r
+       bool canReclaimMemClusters(std::set<unsigned int> mc_ids, int consumer_id);\r
+       bool canReclaimMemClusters(std::set<unsigned int> mc_ids, int consumer_id, std::string app_id);\r
+       int getReclaimableMemClusterConsumers(std::set<unsigned int> mc_ids, int consumer_id, std::multimap<int, int>* reclaimables);\r
+       int getReclaimableMemClusterConsumers(std::set<unsigned int> mc_ids, int consumer_id, std::multimap<int, int>* reclaimables, std::string app_id);\r
+       void SwapConsumers(int device_id_a, std::set<int> consumers_a, int device_id_b, std::set<int> consumers_b);\r
+\r
+       bool isAvailableAudioCodec(std::string name);\r
+       bool isAudioCodecBeingUsed(void) { return (m_acodec_consumers.size() > 0); }\r
+       std::map<unsigned long, std::pair<int, int>> getAudioCodecConsumers(void);\r
+\r
+       CMixingMode *getCurMixingMode(void) { return m_cur_mixing_mode; }\r
+       CMixingMode *findMixingMode(rms_mixing_mode_e mode);\r
+       void Update(resource_update_type_e type, const int device_id, const int consumer_id);\r
+private:\r
+       CDependencyController();\r
+\r
+       void registerMixingModes(void);\r
+       bool IsRegisteredMemCluster(unsigned int id);\r
+       void addMemClusterConsumer(int device_id, int consumer_id);\r
+       void removeMemClusterConsumer(int device_id, int consumer_id);\r
+       void ClearMemClusterConsumer(int device_id);\r
+       CMemCluster *findMemCluster(unsigned int id);\r
+\r
+       static CDependencyController *m_instance;\r
+       std::map<unsigned int, CMemCluster*> m_mem_clusters;\r
+\r
+       void addAudioCodecConsumer(int device_id, int consumer_id);\r
+       void removeAudioCodecConsumer(int device_id, int consumer_id);\r
+       void setCurMixingMode(int device_id, int consumer_id);\r
+       void resetCurMixingMode(int device_id, int consumer_id);\r
+\r
+       std::map<int, int> m_acodec_consumers; // device id, consumer id\r
+       unsigned int m_acodec_ref_count_max = 2;\r
+\r
+       std::map<rms_mixing_mode_e, CMixingMode*> m_mixing_modes;\r
+       CMixingMode *m_cur_mixing_mode;\r
+};\r
+\r
+#endif // __CDEPENDENCY_CONTROLLER_H__\r
diff --git a/include_internal/manager/dependence/CMemCluster.h b/include_internal/manager/dependence/CMemCluster.h
new file mode 100644 (file)
index 0000000..12aa539
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CMEM_CLUSTER_H__\r
+#define __CMEM_CLUSTER_H__\r
+\r
+#include <set>\r
+#include <map>\r
+\r
+class CMemCluster{\r
+public:\r
+       CMemCluster(unsigned int m_id);\r
+       ~CMemCluster();\r
+\r
+       bool IsUsed(void);\r
+       bool IsUsedBy(std::string app_id);\r
+       bool IsSharable(int device_id);\r
+\r
+       unsigned int GetId(void) { return m_id; }\r
+       std::set<int> GetAssignedDeviceId(int consumer_id);\r
+       int GetCategoryClass(void) { return m_category_class; }\r
+       int GetCategoryId(void) { return m_category_id; }\r
+\r
+       void AddConsumer(int consumer_id, int device_id, int category_class, int category_id);\r
+       void RemoveConsumer(int consumer_id, int device_id);\r
+       void ClearConsumers(void);\r
+       std::set<int> GetConsumers(void);\r
+private:\r
+       unsigned int m_id;\r
+       std::map<int, std::set<int>> m_consumers; // consumer, device ids\r
+       int m_category_class;\r
+       int m_category_id;\r
+};\r
+\r
+#endif //__CMEM_CLUSTER_H__\r
diff --git a/include_internal/manager/dependence/CMixingMode.h b/include_internal/manager/dependence/CMixingMode.h
new file mode 100644 (file)
index 0000000..002ca7e
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CMIXING_MODE_H__\r
+#define __CMIXING_MODE_H__\r
+\r
+#include <map>\r
+#include <string>\r
+#include <rms_type.h>\r
+\r
+class CAudioCodec;\r
+class CMixingMode{\r
+public:\r
+       CMixingMode(rms_mixing_mode_e mode) { m_mode = mode; }\r
+       ~CMixingMode() = default;\r
+\r
+       int AddConsumer(int device_id, int consumer_id);\r
+       int RemoveConsumer(int device_id, int consumer_id);\r
+       rms_mixing_mode_e getMode(void) { return m_mode; }\r
+       std::map<int, int> GetConsumers(void) { return m_consumers; }\r
+private:\r
+       rms_mixing_mode_e m_mode;\r
+       std::map<std::string, CAudioCodec*> m_audio_codecs;\r
+       std::map<int, int> m_consumers; // device id, consumer id\r
+};\r
+\r
+#endif //__CAUDIO_MIXING_MODE_H__\r
diff --git a/include_internal/manager/strategy/CAllocateModeStrategy.h b/include_internal/manager/strategy/CAllocateModeStrategy.h
new file mode 100644 (file)
index 0000000..95f584d
--- /dev/null
@@ -0,0 +1,34 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CALLOCATE_MODE_STRATEGY_H__\r
+#define __CALLOCATE_MODE_STRATEGY_H__\r
+\r
+#include <rms_type.h>\r
+#include <vector>\r
+\r
+class CRequest;\r
+class CAllocateModeStrategy\r
+{\r
+public:\r
+       virtual ~CAllocateModeStrategy() {}\r
+\r
+       virtual bool CanAllocateResources(std::vector<CRequest *> requests, rms_allocate_result_s *result) = 0;\r
+       virtual void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices) = 0;\r
+};\r
+\r
+\r
+#endif //__CALLOCATE_MODE_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CAllocateModeStrategyProvider.h b/include_internal/manager/strategy/CAllocateModeStrategyProvider.h
new file mode 100644 (file)
index 0000000..356813f
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CALLOCATE_MODE_STRATEGY_PROVIDER_H__\r
+#define __CALLOCATE_MODE_STRATEGY_PROVIDER_H__\r
+\r
+#include <rms_type.h>\r
+\r
+class CAllocateModeStrategy;\r
+class CAllocateModeStrategyProvider\r
+{\r
+public:\r
+       static CAllocateModeStrategyProvider *getInstance();\r
+       ~CAllocateModeStrategyProvider();\r
+\r
+       CAllocateModeStrategy *GetStrategy(rms_msg_request *req);\r
+private:\r
+       CAllocateModeStrategyProvider();\r
+\r
+       int getAllocateMode(rms_msg_request *req);\r
+\r
+       static CAllocateModeStrategyProvider *m_instance;\r
+};\r
+\r
+#endif //__CALLOCATE_MODE_PROVIDER_H__\r
diff --git a/include_internal/manager/strategy/CAllocateStrategy.h b/include_internal/manager/strategy/CAllocateStrategy.h
new file mode 100644 (file)
index 0000000..2449c6f
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CALLOCATE_STRATEGY_H__\r
+#define __CALLOCATE_STRATEGY_H__\r
+\r
+#include <rms_type.h>\r
+#include <map>\r
+#include <set>\r
+\r
+class CVirtualResource;\r
+class CRequest;\r
+class CAllocateStrategy\r
+{\r
+public:\r
+       virtual ~CAllocateStrategy() {}\r
+       virtual CVirtualResource *findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req) = 0;\r
+       virtual int reserveResource(CVirtualResource *vrsc, CRequest *req) = 0;\r
+       virtual void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource*> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type) = 0;\r
+\r
+protected:\r
+       void ExcludeResources(std::map<int, CVirtualResource *> vresources, std::map<int, CVirtualResource *>* filtered_resources, CRequest *req);\r
+       void ExcludeResources(std::multimap<unsigned long, CVirtualResource *> vresources, std::multimap<unsigned long, CVirtualResource *>* filtered_resources, CRequest *req);\r
+       void ExcludeDuplicatedNDecoders(std::multimap<int, int> *retirables, std::set<int> *excluded);\r
+       void updateReasonByResourceState(int device_id, CRequest *req);\r
+       void updateReasonBySharableCount(int device_id, CRequest *req);\r
+       int GetReclaimedBW(std::multimap<int, int> *retirables);\r
+};\r
+\r
+#endif //__CALLOCATE_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CAllocateStrategyProvider.h b/include_internal/manager/strategy/CAllocateStrategyProvider.h
new file mode 100644 (file)
index 0000000..d93a831
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CALLOCATE_STRATEGY_PROVIDER_H__\r
+#define __CALLOCATE_STRATEGY_PROVIDER_H__\r
+\r
+#include <rms_type.h>\r
+\r
+class CAllocateStrategy;\r
+class CAllocateStrategyProvider\r
+{\r
+public:\r
+       static CAllocateStrategyProvider *getInstance();\r
+       ~CAllocateStrategyProvider();\r
+\r
+       CAllocateStrategy *GetStrategy(rms_rsc_category_e category, int category_class);\r
+\r
+private:\r
+       CAllocateStrategyProvider();\r
+\r
+       bool IsAudioDecoderCategory(rms_rsc_category_e category);\r
+       bool IsVideoDecoderCategory(rms_rsc_category_e category);\r
+       bool IsBGScalerCategory(rms_rsc_category_e category);\r
+       bool IsNDecordingVideoDecoderCategory(int category_class);\r
+       bool IsMultiviewScalerCategory(rms_rsc_category_e category);\r
+       bool IsSubScalerCategory(rms_rsc_category_e category);\r
+\r
+       static CAllocateStrategyProvider *m_instance;\r
+};\r
+\r
+#endif //__CALLOCATE_STRATEGY_PROVIDER_H__\r
diff --git a/include_internal/manager/strategy/CAudioDecoderStrategy.h b/include_internal/manager/strategy/CAudioDecoderStrategy.h
new file mode 100644 (file)
index 0000000..cacf8c6
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CAUDIO_DECODER_STRATEGY_H__\r
+#define __CAUDIO_DECODER_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CAllocateStrategy;\r
+class CAudioDecoderStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CAudioDecoderStrategy() = default;\r
+       ~CAudioDecoderStrategy() = default;\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource *vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+private:\r
+       int GetRetirableConsumers(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+};\r
+\r
+#endif //__CAUDIO_DECODER_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CExclusiveStrategy.h b/include_internal/manager/strategy/CExclusiveStrategy.h
new file mode 100644 (file)
index 0000000..1a54657
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CEXCLUSIVE_STRATEGY_H__\r
+#define __CEXCLUSIVE_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CAllocateStrategy;\r
+class CExclusiveStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CExclusiveStrategy() = default;\r
+       ~CExclusiveStrategy() = default;\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource * vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+\r
+private:\r
+       int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+       int getRetirableConsumersShare(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+       void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req);\r
+       bool isAllocatableResource(CVirtualResource *vresource, CRequest *req);\r
+       bool ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+       bool isSharableResource(CVirtualResource *vresource, CRequest *req);\r
+       bool ContainSharableResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+};\r
+\r
+#endif //__CEXCLUSIVE_STRATEGY_H__\r
+\r
diff --git a/include_internal/manager/strategy/CInvalidModeStrategy.h b/include_internal/manager/strategy/CInvalidModeStrategy.h
new file mode 100644 (file)
index 0000000..82e363e
--- /dev/null
@@ -0,0 +1,36 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CINVALID_MODE_STRATEGY_H__\r
+#define __CINVALID_MODE_STRATEGY_H__\r
+\r
+#include <rms_type.h>\r
+#include <vector>\r
+\r
+class CRequest;\r
+class CAllocateModeStrategy;\r
+class CInvalidModeStrategy: public CAllocateModeStrategy\r
+{\r
+public:\r
+       CInvalidModeStrategy();\r
+       ~CInvalidModeStrategy();\r
+\r
+       bool CanAllocateResources(std::vector<CRequest *> requests, rms_allocate_result_s *result);\r
+       void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices);\r
+};\r
+\r
+#endif// __CINVALID_MODE_STRATEGY_H__\r
+\r
diff --git a/include_internal/manager/strategy/CMixingStrategy.h b/include_internal/manager/strategy/CMixingStrategy.h
new file mode 100644 (file)
index 0000000..f27b8ff
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CMIXING_STRATEGY_H__\r
+#define __CMIXING_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+\r
+class CRequest;\r
+class CAudioCodec;\r
+class CVirtualResource;\r
+class CMixingMode;\r
+class CMixingStrategy\r
+{\r
+public:\r
+       static CMixingStrategy *getInstance();\r
+       ~CMixingStrategy() = default;\r
+\r
+       bool isAvailableAudioCodec(std::string name, int consumer_id, rms_error_type_e *reason);\r
+       int getReclaimableAudioCodecConsumers(std::string codec_name, int consumer_id, CRequest *req, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type);\r
+       void updateReasonByAudioCodec(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason);\r
+\r
+       int getReclaimableMixingModeConsumers(rms_mixing_mode_e mode, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type);\r
+       void updateReasonByMixingMode(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason);\r
+       bool isAvailableMixingMode(rms_mixing_mode_e mode);\r
+\r
+private:\r
+       CMixingStrategy() = default;\r
+\r
+       bool needReclaimCheck(rms_error_type_e reason);\r
+       bool canReclaimAudioCodec(std::string codec_name, int consumer_id);\r
+       bool canReclaimMixingMode(rms_mixing_mode_e mode, int consumer_id);\r
+       bool canReclaimMixingMode(rms_mixing_mode_e mode, CMixingMode *cur_mode, int consumer_id);\r
+\r
+       static CMixingStrategy *m_instance;\r
+};\r
+\r
+#endif //__CMIXING_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h b/include_internal/manager/strategy/CNDecodingVideoDecoderStrategy.h
new file mode 100644 (file)
index 0000000..e36812b
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+\r
+#ifndef __C_NDECODING_VIDEO_DECODER_STRATEGY_H__\r
+#define __C_NDECODING_VIDEO_DECODER_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CAllocateStrategy;\r
+class CNDecodingVideoDecoderStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CNDecodingVideoDecoderStrategy() = default;\r
+       ~CNDecodingVideoDecoderStrategy() = default;\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource *vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type);\r
+\r
+private:\r
+       int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+       void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req);\r
+       void updateReasonByBW(CVirtualResource *vresource, CRequest *req);\r
+       void updateReasonByTripleDecoding(CRequest *req);\r
+       bool isAllocatableResource(CVirtualResource *vresource, CRequest *req);\r
+       bool ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+       bool canReclaimRequiredBW(CRequest *req, unsigned int bw);\r
+       int GetConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap<int, int>* return_ids);\r
+       bool canReclaimActiveVideoDecoders(CRequest *req);\r
+       int GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap<int, int>* reclaimables, CRequest *req, rms_error_type_e *err_type);\r
+       void SelectDevicesByMainSub(CRequest *req, std::map<int, int> *src, std::map<int, int> *result);\r
+       int GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map<int, int> bw_consumers, std::multimap<int, int> *reclaimed_consumers);\r
+};\r
+\r
+#endif //__C_NDECODING_VIDEO_DECODER_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CNormalModeStrategy.h b/include_internal/manager/strategy/CNormalModeStrategy.h
new file mode 100644 (file)
index 0000000..92d9219
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CNORMAL_MODE_STRATEGY_H__\r
+#define __CNORMAL_MODE_STRATEGY_H__\r
+\r
+#include <vector>\r
+#include <rms_type.h>\r
+\r
+class CRequest;\r
+class CAllocateModeStrategy;\r
+class CNormalModeStrategy:public CAllocateModeStrategy\r
+{\r
+public:\r
+       CNormalModeStrategy();\r
+       ~CNormalModeStrategy();\r
+\r
+       bool CanAllocateResources(std::vector<CRequest *> requests, rms_allocate_result_s *result);\r
+       void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices);\r
+private:\r
+       rms_error_type_e GetCandidateFindResult(std::vector<CRequest *> requests);\r
+};\r
+\r
+#endif //__CNORMAL_MODE_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CNormalStrategy.h b/include_internal/manager/strategy/CNormalStrategy.h
new file mode 100644 (file)
index 0000000..d7bb414
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CNORMAL_STRATEGY_H__\r
+#define __CNORMAL_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CNormalStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CNormalStrategy();\r
+       ~CNormalStrategy();\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource *vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource*> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type);\r
+\r
+private:\r
+       bool ContainFreeResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+};\r
+\r
+#endif //__CALLOCATE_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CPreferenceModeStrategy.h b/include_internal/manager/strategy/CPreferenceModeStrategy.h
new file mode 100644 (file)
index 0000000..e1fcb29
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CPREFERENCE_MODE_STRATEGY_H__\r
+#define __CPREFERENCE_MODE_STRATEGY_H__\r
+\r
+#include <vector>\r
+#include <rms_type.h>\r
+\r
+class CRequest;\r
+class CAllocateModeStrategy;\r
+class CPreferenceModeStrategy: public CAllocateModeStrategy\r
+{\r
+public:\r
+       CPreferenceModeStrategy();\r
+       ~CPreferenceModeStrategy();\r
+\r
+       bool CanAllocateResources(std::vector<CRequest *> requests, rms_allocate_result_s *result);\r
+       void WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices);\r
+};\r
+\r
+#endif //__CPREFERENCE_MODE_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CScalerStrategy.h b/include_internal/manager/strategy/CScalerStrategy.h
new file mode 100644 (file)
index 0000000..5bbd14c
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CSCALER_STRATEGY_H__\r
+#define __CSCALER_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CScalerStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CScalerStrategy();\r
+       ~CScalerStrategy();\r
+\r
+       CVirtualResource * findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource * vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type);\r
+       void SelectConsumersByZoneId(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+       void SelectConsumersByAllocationTime(std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+\r
+private:\r
+       bool ContainFreeResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+       bool ContainInterlacedNotSupportedApp(std::map<int, std::multimap<int, int>> *candidates);\r
+       int FindScalerInSameZone(int zone_id);\r
+       int FindScalerUsedByAppInterlacedNotSupported(std::map<int, std::multimap<int, int>> *candidates);\r
+       void SelectConsumersBySwap(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+       void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req);\r
+};\r
+\r
+#endif //__CSCALER_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CVideoDecoderStrategy.h b/include_internal/manager/strategy/CVideoDecoderStrategy.h
new file mode 100644 (file)
index 0000000..9552d08
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CVIDEO_DECODER_STRATEGY_H__\r
+#define __CVIDEO_DECODER_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CAllocateStrategy;\r
+class CVideoDecoderStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CVideoDecoderStrategy();\r
+       ~CVideoDecoderStrategy() = default;\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource*> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource *vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource*> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type);\r
+\r
+private:\r
+       int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+       void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req);\r
+       void updateReasonByBW(CVirtualResource *vresource, CRequest *req);\r
+       void updateReasonByTripleDecoding(CRequest *req);\r
+       bool isAllocatableResource(CVirtualResource *vresource, CRequest *req);\r
+       bool ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources);\r
+       bool canReclaimRequiredBW(CRequest *req, unsigned int bw);\r
+       int getConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap<int, int>* return_ids);\r
+       int GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int bw, std::map<int, int> candidates, std::multimap<int, int>* return_ids);\r
+       bool canReclaimActiveVideoDecoders(CRequest *req);\r
+       int GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap<int, int>* reclaimables, CRequest *req, rms_error_type_e *err_type);\r
+       void SelectConsumersByAllocationTime(std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+       void SelectConsumersByZoneId(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+       void SelectInSameCategoryAndZone(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result);\r
+       void SelectInSameZone(int zone_id, std::map<int, std::multimap<int, int>> candidates, std::multimap<int, int> *result);\r
+       void SelectDevicesByMainSub(CRequest *req, std::map<int, int> *src, std::map<int, int> *result);\r
+       int GetConflictScore(int n_conflicts);\r
+\r
+       bool m_reclaim_policy_by_zone_id;\r
+};\r
+\r
+#endif //_CVIDEO_DECODER_STRATEGY_H__\r
diff --git a/include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h b/include_internal/manager/strategy/CVideoEncoderExclusiveStrategy.h
new file mode 100644 (file)
index 0000000..c982a24
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__\r
+#define __CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+class CRequest;\r
+class CVirtualResource;\r
+class CAllocateStrategy;\r
+class CVideoEncoderExclusiveStrategy: public CAllocateStrategy\r
+{\r
+public:\r
+       CVideoEncoderExclusiveStrategy() = default;\r
+       ~CVideoEncoderExclusiveStrategy() = default;\r
+\r
+       CVirtualResource *findCandidate(std::map<int, CVirtualResource*> vresources, CRequest *req);\r
+       int reserveResource(CVirtualResource *vrsc, CRequest *req);\r
+       void GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource*> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type);\r
+\r
+private:\r
+       int getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type);\r
+       void updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req);\r
+       bool isAllocatableResource(CVirtualResource *vresource, CRequest *req);\r
+       bool ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req);\r
+};\r
+\r
+#endif //__CVIDEO_ENCODER_EXCLUSIVE_STRATEGY_H__\r
diff --git a/include_internal/rms-dbus-interface.xml b/include_internal/rms-dbus-interface.xml
new file mode 100644 (file)
index 0000000..9a251e1
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<node>
+       <interface name="com.samsung.rmservice">
+       <annotation name= "com.Samsung.Exportable" value= "true"/>
+       <method name="TestCall">
+               <arg type="i" name="in_data" direction="in"/>
+               <arg type="i" name="out_data" direction="out"/>
+       </method>
+       <method name="NotifyAllocation">
+               <arg type="i" name="cid" direction="in"/>
+               <arg type="i" name="pid" direction="in"/>
+               <arg type="ai" name="alloc_list" direction="in"/>
+               <arg type="i" name="ret" direction="out"/>
+               <arg type="ai" name="ret_list" direction="out"/>
+       </method>
+       <method name="NotifyConsumerTobeReturned">
+               <arg type="i" name="cid" direction="in"/>
+               <arg type="i" name="pid" direction="in"/>
+               <arg type="ai" name="alloc_list" direction="in"/>
+               <arg type="i" name="ret" direction="out"/>
+               <arg type="ai" name="cid_list" direction="out"/>
+               <arg type="ai" name="pid_list" direction="out"/>
+               <arg type="ai" name="conflict_rsc_num_list" direction="out"/>
+               <arg type="ai" name="devices" direction="out"/>
+               <arg type="ai" name="num_of_rsc" direction="out"/>
+       </method>
+       <method name="NotifyDeallocation">
+               <arg type="i" name="cid" direction="in"/>
+               <arg type="ai" name="dealloc_list" direction="in"/>
+               <arg type="i" name="ret_val" direction="out"/>
+       </method>
+       <method name="NotifyDeallocationByCid">
+               <arg type="i" name="cid" direction="in"/>
+               <arg type="i" name="ret_val" direction="out"/>
+       </method>
+       <method name="NotifyDeallocationByPid">
+               <arg type="i" name="pid" direction="in"/>
+               <arg type="i" name="ret_val" direction="out"/>
+       </method>
+       <method name="NotifyCallback">
+               <arg type="ai" name="list" direction="in"/>
+               <arg type="i" name="ret_val" direction="out"/>
+       </method>
+       </interface>
+</node>
diff --git a/include_internal/rms_debug.h b/include_internal/rms_debug.h
new file mode 100644 (file)
index 0000000..26214bf
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+\r
+#ifndef __RMS_DEBUG_H__\r
+#define __RMS_DEBUG_H__\r
+\r
+#include <dlog.h>\r
+\r
+\r
+#ifdef LOG_TAG\r
+#undef LOG_TAG\r
+#endif//LOG_TAG\r
+\r
+#define LOG_TAG "RSC_MGR_SERVER"\r
+\r
+#ifndef SERVER_ERR\r
+#define SERVER_ERR(fmt, args...)SLOGE(fmt, ##args)\r
+#endif\r
+\r
+#ifndef SERVER_DBG\r
+#define SERVER_DBG(fmt, args...)SLOGD(fmt, ##args)\r
+#endif\r
+\r
+#ifndef SERVER_INFO\r
+#define SERVER_INFO(fmt, args...)SLOGI(fmt, ##args)\r
+#endif\r
+\r
+#ifndef SERVER_WARN\r
+#define SERVER_WARN(fmt, args...)SLOGW(fmt, ##args)\r
+#endif\r
+\r
+\r
+#endif//__RMS_DEBUG_H__\r
+\r
diff --git a/include_internal/rms_log.h b/include_internal/rms_log.h
new file mode 100644 (file)
index 0000000..fa8ae0a
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __RMS_LOG_H__\r
+#define __RMS_LOG_H__\r
+\r
+#include <stdio.h>\r
+\r
+static char g_rms_dlog_msg[4096] = {0,};\r
+static int g_rms_dlog_msg_pose = 0;\r
+\r
+static void rms_log_reset() { g_rms_dlog_msg_pose = 0; }\r
+static void rms_log_add(const char *format_str, ...) __attribute__ ((format (printf, 1, 2)));\r
+static void rms_log_add(const char *format_str, ...) {\r
+       va_list argptr;\r
+       va_start(argptr, format_str);\r
+       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);\r
+       va_end(argptr);\r
+}\r
+\r
+#define RMS_LOGE_FLUSH() SLOGE("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0\r
+#define RMS_LOGI_FLUSH() SLOGI("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0\r
+#define RMS_LOGD_FLUSH() SLOGD("%s", g_rms_dlog_msg); g_rms_dlog_msg_pose = 0\r
+\r
+#endif //__RMS_LOG_H__\r
+\r
diff --git a/include_internal/rms_type.h b/include_internal/rms_type.h
new file mode 100644 (file)
index 0000000..ce9eecc
--- /dev/null
@@ -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 <resource-information/ri-common-type.h>
+
+#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 (file)
index 0000000..6e89c2d
--- /dev/null
@@ -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 (file)
index 0000000..d98cdeb
--- /dev/null
@@ -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 (file)
index 0000000..75b0fa5
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+    <request>
+        <domain name="_"/>
+    </request>
+</manifest>
diff --git a/src/CAsyncQueue.cpp b/src/CAsyncQueue.cpp
new file mode 100644 (file)
index 0000000..537d878
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_debug.h>\r
+#include <CAsyncQueue.h>\r
+\r
+CAsyncQueue::CAsyncQueue(void)\r
+{\r
+       queue = g_async_queue_new();\r
+}\r
+\r
+CAsyncQueue::CAsyncQueue(destoryNotify destory_cb)\r
+{\r
+       queue = g_async_queue_new_full(destory_cb);\r
+}\r
+\r
+CAsyncQueue::~CAsyncQueue(void)\r
+{\r
+       g_async_queue_unref(queue);\r
+}\r
+\r
+void CAsyncQueue::push(void *data)\r
+{\r
+       g_async_queue_push(queue, data);\r
+}\r
+\r
+void CAsyncQueue::push(CAsyncQueue *src_queue)\r
+{\r
+       if (src_queue->length() <= 0)\r
+               return;\r
+\r
+       SERVER_INFO("push given queue (%d)", src_queue->length());\r
+\r
+       g_async_queue_lock(queue);\r
+\r
+       while (src_queue->length() > 0) {\r
+               g_async_queue_push_unlocked(queue, src_queue->pop());\r
+       }\r
+\r
+       g_async_queue_unlock(queue);\r
+}\r
+\r
+void CAsyncQueue::push_front(void *data)\r
+{\r
+       g_async_queue_push_front(queue, data);\r
+}\r
+\r
+void CAsyncQueue::push_front(CAsyncQueue *src_queue)\r
+{\r
+       if (src_queue->length() <= 0)\r
+               return;\r
+\r
+       SERVER_INFO("push_front given queue (%d)", src_queue->length());\r
+\r
+       g_async_queue_lock(queue);\r
+\r
+       while (src_queue->length() > 0) {\r
+               g_async_queue_push_front_unlocked(queue, src_queue->pop());\r
+       }\r
+\r
+       g_async_queue_unlock(queue);\r
+}\r
+\r
+void *CAsyncQueue::pop(void)\r
+{\r
+       return g_async_queue_pop(queue);\r
+}\r
+\r
+void *CAsyncQueue::pop(unsigned int timeout_ms)\r
+{\r
+       guint64 timeout_us = (guint64)((guint64) timeout_ms * 1000);\r
+\r
+       return g_async_queue_timeout_pop(queue, timeout_us);\r
+}\r
+\r
+int CAsyncQueue::length(void)\r
+{\r
+       return g_async_queue_length(queue);\r
+}\r
+\r
diff --git a/src/CCallback.cpp b/src/CCallback.cpp
new file mode 100644 (file)
index 0000000..214943c
--- /dev/null
@@ -0,0 +1,127 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <CCallback.h>\r
+\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CDebugUtils.h>\r
+\r
+#include <errno.h>\r
+#include <sys/stat.h>\r
+#include <stdio.h>\r
+#include <fcntl.h>\r
+#include <poll.h>\r
+#include <unistd.h>\r
+#include <system_info.h>\r
+\r
+#define CB_TIMEOUT_3_SEC_IN_MS 3000\r
+#define CB_TIMEOUT_10_SEC_IN_MS 10000\r
+\r
+#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0)\r
+\r
+unsigned int CCallback::GetTimeout(void)\r
+{\r
+       return (RMS_IS_DEBUG_IMAGE) ? CB_TIMEOUT_10_SEC_IN_MS : CB_TIMEOUT_3_SEC_IN_MS;\r
+}\r
+\r
+void CCallback::InitCallback(void)\r
+{\r
+       const char *cb_path = "/run/rsc_mgr";\r
+       mode_t dir_mode =  0666 | 0111;\r
+\r
+       if (mkdir(cb_path, dir_mode) !=0) {\r
+               SERVER_ERR("failed to create cb directory (%d)", errno);\r
+               return;\r
+       }\r
+\r
+       chmod(cb_path, dir_mode);\r
+}\r
+\r
+int CCallback::SendCallbackMessage(int cid, int pid, void *callback_data, int size, int *err)\r
+{\r
+       int fd = -1;\r
+       int ret = 0;\r
+\r
+       char callback_path[256] = {0,};\r
+\r
+       snprintf(callback_path, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid);\r
+\r
+       if ((fd = open(callback_path, O_WRONLY|O_NONBLOCK)) < 0) {\r
+               SERVER_ERR("open error (%s), errno(%d)\n", callback_path, errno);\r
+               *err = errno;\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       if (is_symlink_file(callback_path)) {\r
+               SERVER_ERR("%s is symbolic link file", callback_path);\r
+               *err = EPERM;\r
+               close(fd);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       ret = write(fd, callback_data, size);\r
+\r
+       if (ret <= 0) {\r
+               SERVER_ERR("failed to write callback.(%s) ret(%d), errno(%d)\n", callback_path, ret, errno);\r
+               *err = errno;\r
+               close(fd);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_DBG("succeeded to write callback.(%s)", callback_path);\r
+\r
+       close(fd);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CCallback::RemoveFIFOServerToClient(int pid, int cid)\r
+{\r
+       struct stat stat_info;\r
+       char cb_path_s2c[256] = {0, };\r
+\r
+       snprintf(cb_path_s2c, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid);\r
+\r
+       if (stat(cb_path_s2c, &stat_info) != 0) {\r
+               SERVER_INFO("%s not exists", cb_path_s2c);\r
+               return RMS_OK;\r
+       }\r
+\r
+       if (remove(cb_path_s2c) != 0) {\r
+               SERVER_ERR("failed to remove cb for S2C(%s)-(%d)", cb_path_s2c, errno);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_DBG("Removed cb for S2C(%s)", cb_path_s2c);\r
+       return RMS_OK;\r
+}\r
+\r
+int CCallback::ConvertCallbackType(int rm_return_type)\r
+{\r
+       switch (rm_return_type) {\r
+               case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER:\r
+                       return RMS_CALLBACK_TYPE_RESOURCE_CONFLICT;\r
+               case RMS_OK_UHD_RESOURCE_CONFLICT:\r
+                       return RMS_CALLBACK_TYPE_RESOURCE_CONFLICT_UD;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       SERVER_ERR("return RMS_CALLBACK_TYPE_UNKNOWN(%d)", RMS_CALLBACK_TYPE_UNKNOWN);\r
+\r
+       return RMS_CALLBACK_TYPE_UNKNOWN;\r
+}\r
diff --git a/src/CDbusHandler.cpp b/src/CDbusHandler.cpp
new file mode 100644 (file)
index 0000000..d04f6f0
--- /dev/null
@@ -0,0 +1,174 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <assert.h>\r
+#include <iostream>\r
+#include <glib.h>\r
+#include <gio/gio.h>\r
+#include <trace.h>\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <CMessage.h>\r
+#include <CAsyncQueue.h>\r
+#include <CDbusHandler.h>\r
+\r
+const GDBusInterfaceVTable CDbusHandler::m_vtable = { CDbusHandler::OnMethodCall, NULL, NULL, {0} };\r
+\r
+const std::string CDbusHandler::m_methods =\r
+       "<node>"\r
+               "<interface name = 'rscmgr.resource'>"\r
+                       "<method name = 'GetResourceState'>"\r
+                               "<arg direction='in' type='i' name='device_id'/>"\r
+                               "<arg direction='out' type='i' name='state'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetResourceList'>"\r
+                               "<arg direction='in' type='i' name='category_id'/>"\r
+                               "<arg direction='out' type='a(iissi)'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetRscCollectionState'>"\r
+                               "<arg direction='in' type='i' name='collection'/>"\r
+                               "<arg direction='out' type='a(isiiis)'/>"\r
+                       "</method>"\r
+                       "<method name = 'FindDeviceId'>"\r
+                               "<arg direction='in' type='i' name='virtual_id'/>"\r
+                               "<arg direction='out' type='i' name='real_id'/>"\r
+                       "</method>"\r
+                       "<method name = 'SwapResources'>"\r
+                               "<arg direction='in' type='i' name='device_id_a'/>"\r
+                               "<arg direction='in' type='i' name='device_id_b'/>"\r
+                               "<arg direction='out' type='i' name='result'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetScalerState'>"\r
+                               "<arg direction='in' type='i' name='category_id'/>"\r
+                               "<arg direction='out' type='a(iiiiis)'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetAppId'>"\r
+                               "<arg direction='in' type='i' name='handle'/>"\r
+                               "<arg direction='out' type='i' name='result'/>"\r
+                               "<arg direction='out' type='s' name='app_id'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetActiveAudioOut'>"\r
+                               "<arg direction='in' type='i' name='handle'/>"\r
+                               "<arg direction='out' type='i' name='audio_out'/>"\r
+                       "</method>"\r
+                       "<method name = 'GetScalerHWID'>"\r
+                               "<arg direction='in' type='i' name='zone_id'/>"\r
+                               "<arg direction='out' type='i' name='hw_id'/>"\r
+                       "</method>"\r
+                       "<method name = 'RestoreResources'>"\r
+                               "<arg direction='in' type='i' name='category_id'/>"\r
+                               "<arg direction='out' type='i' name='result'/>"\r
+                       "</method>"\r
+                       "<method name = 'NotifyResourcePolicy'>"\r
+                               "<arg direction='in' type='i' name='policy'/>"\r
+                               "<arg direction='out' type='i' name='result'/>"\r
+                       "</method>"\r
+                       "<method name = 'NotifyAppZoneInfo'>"\r
+                               "<arg direction='in' type='s' name='appid'/>"\r
+                               "<arg direction='in' type='i' name='zoneid'/>"\r
+                               "<arg direction='out' type='i' name='reply'/>"\r
+                       "</method>"\r
+               "</interface>"\r
+       "</node>";\r
+\r
+CDbusHandler::CDbusHandler(CAsyncQueue *queue)\r
+{\r
+       assert(queue);\r
+       m_async_queue = queue;\r
+       m_reg_id = 0;\r
+\r
+       if (!MakeDbusConnection())\r
+               return;\r
+\r
+       RegisterObjects();\r
+}\r
+\r
+bool CDbusHandler::MakeDbusConnection(void)\r
+{\r
+       m_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);\r
+\r
+       if (!m_conn) {\r
+               SERVER_ERR("failed to make dbus connection");\r
+               return false;\r
+       }\r
+\r
+       SERVER_INFO("making dbus connection success");\r
+       return true;\r
+}\r
+\r
+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)\r
+{\r
+       CDbusHandler *handler = static_cast<CDbusHandler*>(data);\r
+       CAsyncQueue *queue = handler->m_async_queue;\r
+       CMessage *msg = new CMessage(invoc);\r
+\r
+       SERVER_INFO("push msg(%s)", method_name);\r
+\r
+       queue->push(msg);\r
+}\r
+\r
+void CDbusHandler::GenerateReadyEvent(void)\r
+{\r
+       SERVER_INFO("We will notify clients when the server is ready by generating a ready event");\r
+}\r
+\r
+void CDbusHandler::OnBusAcquired(GDBusConnection *conn, const gchar *bus_name, gpointer data)\r
+{\r
+       trace_begin("[RSC_MGR] OnBusAcquired");\r
+       trace_end();\r
+       SERVER_INFO("bus acquired (%s)", bus_name);\r
+\r
+       CDbusHandler *handler = static_cast<CDbusHandler*>(data);\r
+       handler->GenerateReadyEvent();\r
+}\r
+\r
+void CDbusHandler::OnNameLost(GDBusConnection *conn, const gchar *bus_name, gpointer data)\r
+{\r
+       SERVER_ERR("name lost (%s)", bus_name);\r
+}\r
+\r
+void CDbusHandler::RegisterObjects(void)\r
+{\r
+       assert(m_conn);\r
+       GError *err = NULL;\r
+\r
+       GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(m_methods.c_str(), &err);\r
+\r
+       if (!node_info) {\r
+               SERVER_ERR("failed to get node_info (%s)", err ? err->message : "unknown");\r
+               g_clear_error(&err);\r
+               return;\r
+       }\r
+\r
+       m_reg_id = g_dbus_connection_register_object(m_conn, RM_DBUS_OBJ_PATH, *(node_info->interfaces), &m_vtable, this, NULL, &err);\r
+\r
+       if (m_reg_id == 0) {\r
+               SERVER_ERR("failed to register objects (%s)", err ? err->message : "unknown");\r
+               g_clear_error(&err);\r
+               return;\r
+       }\r
+\r
+       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);\r
+\r
+       if (m_own_id == 0) {\r
+               SERVER_ERR("failed to own dbus name (%s)", RM_DBUS_BUS_NAME);\r
+               return;\r
+       }\r
+\r
+       SERVER_INFO("registering dbus objects success");\r
+}\r
diff --git a/src/CHandle.cpp b/src/CHandle.cpp
new file mode 100644 (file)
index 0000000..3d53c3d
--- /dev/null
@@ -0,0 +1,27 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <CHandle.h>\r
+#include <stdlib.h>\r
+#include <rms_type.h>\r
+#include <CDebugUtils.h>\r
+CHandle::CHandle(int in_handle, int in_is_used, int in_pid)\r
+{\r
+       handle = in_handle;\r
+       is_used = in_is_used;\r
+       pid = in_pid;\r
+       rms_get_cmd_name(pid,process_name,RMS_NAME_BUF_SIZE);\r
+}\r
diff --git a/src/CHandleManager.cpp b/src/CHandleManager.cpp
new file mode 100644 (file)
index 0000000..6be09f2
--- /dev/null
@@ -0,0 +1,278 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <CHandleManager.h>\r
+#include <CHandle.h>\r
+#include <CConsumer.h>\r
+#include <CConsumerContainer.h>\r
+#include <CCallback.h>\r
+#include <CDebugUtils.h>\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <rms_log.h>\r
+\r
+#include <map>\r
+#include <stdio.h>\r
+#include <fcntl.h>\r
+#include <signal.h>\r
+#include <stdlib.h>\r
+\r
+\r
+static const int M_MIN_HANDLE = 101;\r
+static const int M_MAX_HANDLE = 200;\r
+\r
+CHandleManager::CHandleManager(CResourceManager *rsc_mgr)\r
+{\r
+       assert(rsc_mgr);\r
+       m_rsc_mgr = rsc_mgr;\r
+       m_next_handle = M_MIN_HANDLE;\r
+}\r
+\r
+int CHandleManager::m_IsValidHandle(int handle)\r
+{\r
+       return ((handle >= M_MIN_HANDLE) && (handle <= M_MAX_HANDLE)) ? 1 : 0;\r
+}\r
+\r
+int CHandleManager::m_ReclaimHandle(void)\r
+{\r
+       for (int i = M_MIN_HANDLE; i < M_MAX_HANDLE; i++) {\r
+               CHandle *handle_info = findHandle(i);\r
+\r
+               if (!handle_info)\r
+                       return i;\r
+\r
+               if (!rm_is_valid_pid(handle_info->pid)) {\r
+                       SERVER_INFO("reclaim pid(%d)/handle(%d)", handle_info->pid, handle_info->handle);\r
+\r
+                       // release resources allocated to terminated process\r
+                       m_rsc_mgr->UnregisterConsumer(handle_info->handle);\r
+                       m_RemoveHandle(handle_info->handle, handle_info->pid);\r
+                       return i;\r
+               }\r
+       }\r
+\r
+       return RMS_HANDLE_NOT_AVAILABLE;\r
+}\r
+\r
+void CHandleManager::m_PrintHandleList(void)\r
+{\r
+       for (int i = M_MIN_HANDLE; i < M_MAX_HANDLE; i++) {\r
+               std::map<int, CHandle*>::iterator it = m_handles.find(i);\r
+\r
+               if (it == m_handles.end())\r
+                       return ;\r
+\r
+               CHandle *handle_info = (*it).second;\r
+               m_PrintHandleInfo(handle_info->handle, handle_info->pid);\r
+       }\r
+}\r
+\r
+int CHandleManager::m_AddNewHandle(int handle, int pid, int main_priority, int sub_priority, int app_pid, char *app_id)\r
+{\r
+       CHandle *handle_info = new(std::nothrow) CHandle(handle, RMS_HANDLE_USE, pid);\r
+       if (!handle_info) {\r
+               SERVER_ERR("cannot create handle class");\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       handle_info->main_priority = main_priority;\r
+       handle_info->sub_priority = sub_priority;\r
+       handle_info->app_pid = app_pid;\r
+       handle_info->app_id = strndup(app_id, strlen(app_id));\r
+\r
+       m_handles.insert(std::pair<int, CHandle*>(handle, handle_info));\r
+       SERVER_DBG("handle(%d) pid(%d) inserted", handle, pid);\r
+\r
+       return RMS_OK;\r
+}\r
+int CHandleManager::m_RemoveHandle(int handle, int pid)\r
+{\r
+       CHandle *handle_info = findHandle(handle);\r
+\r
+       if (!handle_info) {\r
+               SERVER_ERR("can't find handle (%d) in list. no need to remove", handle);\r
+               return RMS_OK;\r
+       }\r
+\r
+       if (handle_info->pid != pid) {\r
+               SERVER_ERR("cannot remove handle (%d) - owner(%d)/requester(%d)", handle, handle_info->pid, pid);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       if (handle_info->app_id) {\r
+               free(handle_info->app_id);\r
+               handle_info->app_id = NULL;\r
+       }\r
+\r
+       for (int i = 0; i < RMS_NAME_BUF_SIZE; i++) {\r
+               handle_info->process_name[i] = 0;\r
+       }\r
+\r
+       delete handle_info;\r
+       m_handles.erase(handle);\r
+\r
+       CCallback::RemoveFIFOServerToClient(pid, handle);\r
+\r
+       return RMS_OK;\r
+}\r
+int CHandleManager::GetNewHandle(int pid, int main_priority, int sub_priority, int app_pid, char *app_id)\r
+{\r
+       int handle = -1;\r
+\r
+       if (m_next_handle >= (M_MAX_HANDLE - 1))\r
+               m_next_handle = M_MIN_HANDLE;\r
+\r
+       std::map<int, CHandle*>::iterator it = m_handles.find(m_next_handle);\r
+\r
+       handle = (it == m_handles.end()) ? m_next_handle:m_ReclaimHandle();\r
+\r
+       if (handle == RMS_HANDLE_NOT_AVAILABLE) {\r
+               SERVER_ERR("ERROR! can't assign new handle (FULL)");\r
+               m_PrintHandleList();\r
+               return RMS_HANDLE_NOT_AVAILABLE;\r
+       }\r
+\r
+       m_AddNewHandle(handle, pid, main_priority, sub_priority, app_pid, app_id);\r
+       ++m_next_handle;\r
+\r
+       return handle;\r
+}\r
+\r
+int CHandleManager::RemoveHandle(int handle, int pid)\r
+{\r
+       return m_RemoveHandle(handle, pid);\r
+}\r
+\r
+int CHandleManager::SetPriority(int handle, int main_priority, int sub_priority)\r
+{\r
+       CHandle *handle_info = findHandle(handle);\r
+\r
+       if (!handle_info) {\r
+               SERVER_ERR("can't find handle (%d)", handle);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle);\r
+\r
+       if (!consumer) {\r
+               SERVER_ERR("handle[%d] not registered consumer", handle);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       handle_info->main_priority = main_priority;\r
+       handle_info->sub_priority = sub_priority;\r
+\r
+       rms_priority_s priority;\r
+       priority.main = main_priority;\r
+       priority.sub = sub_priority;\r
+\r
+       consumer->SetPriority(priority);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+CHandle *CHandleManager::findHandle(int id)\r
+{\r
+       auto it = m_handles.find(id);\r
+\r
+       return (it == m_handles.end()) ? NULL:it->second;\r
+}\r
+\r
+int CHandleManager::GetPriority(int handle, int *main_priority, int *sub_priority)\r
+{\r
+       CHandle *handle_info = findHandle(handle);\r
+\r
+       if (!handle_info) {\r
+               SERVER_ERR("can't find handle (%d)", handle);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       *main_priority = handle_info->main_priority;\r
+       *sub_priority = handle_info->sub_priority;\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CHandleManager::SetAppID(int handle, char *app_id)\r
+{\r
+       CHandle *handle_info = findHandle(handle);\r
+\r
+       if (!handle_info) {\r
+               SERVER_ERR("can't find handle (%d)", handle);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       if (handle_info->app_id) {\r
+               free(handle_info->app_id);\r
+               handle_info->app_id = NULL;\r
+       }\r
+\r
+       handle_info->app_id = strndup(app_id, strlen(app_id));\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+char *CHandleManager::GetAppID(int handle)\r
+{\r
+       CHandle *handle_info = findHandle(handle);\r
+\r
+       if (!handle_info) {\r
+               SERVER_ERR("can't find handle (%d)", handle);\r
+               return NULL;\r
+       }\r
+\r
+       return strndup(handle_info->app_id, strlen(handle_info->app_id));\r
+}\r
+\r
+int CHandleManager::m_PrintHandleInfo(int handle, int pid)\r
+{\r
+       char name[RMS_NAME_BUF_SIZE] = {0,};\r
+       rms_get_cmd_name(pid, name, sizeof(name));\r
+\r
+       rms_log_reset();\r
+       rms_log_add("handle(%d) pid(%d) name(%s)", handle, pid, name);\r
+\r
+       CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle);\r
+\r
+       if (!consumer) {\r
+               rms_log_add(": no consumer info");\r
+\r
+               RMS_LOGE_FLUSH();\r
+               return RMS_OK;\r
+       }\r
+\r
+       rms_log_add(": using %d resource(s)", consumer->GetResourceNum());\r
+\r
+       RMS_LOGE_FLUSH();\r
+       return RMS_OK;\r
+}\r
+\r
+void CHandleManager::ReclaimAllInvalidCustomer(int request_pid)\r
+{\r
+       for (std::map<int, CHandle*>::iterator it = m_handles.begin(); it != m_handles.end(); it++) {\r
+               CHandle *handle_info = (*it).second;\r
+               int cid = handle_info->handle;\r
+               int pid = handle_info->pid;\r
+\r
+               if ((pid != request_pid) &&(!rm_is_valid_pid(pid))) {\r
+                       SERVER_ERR("Reclaim handle(%d)/pid(%d)", cid, pid);\r
+                       m_rsc_mgr->ReleaseResourcesOfPid(pid);\r
+                       RemoveHandle(cid, pid);\r
+                       CCallback::RemoveFIFOServerToClient(pid, cid);\r
+               }\r
+       }\r
+}\r
diff --git a/src/CMessage.cpp b/src/CMessage.cpp
new file mode 100644 (file)
index 0000000..68c1916
--- /dev/null
@@ -0,0 +1,210 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+#include <ri-api.h>\r
+#include <ri-module-api.h>\r
+#include <rms_debug.h>\r
+#include <CMessage.h>\r
+\r
+CMessage::CMessage(std::string name)\r
+{\r
+       m_sender = MSG_SENDER_INTERNAL;\r
+       m_msgq_req = NULL;\r
+       m_name = name;\r
+}\r
+\r
+CMessage::CMessage(rms_msg_request *req)\r
+{\r
+       assert(req);\r
+\r
+       m_msgq_req = (rms_msg_request*) calloc(1, sizeof(rms_msg_request));\r
+       assert(m_msgq_req);\r
+       memcpy(m_msgq_req, req, sizeof(rms_msg_request));\r
+\r
+       m_sender = MSG_SENDER_MSGQ;\r
+}\r
+\r
+CMessage::CMessage(GDBusMethodInvocation *invoc)\r
+{\r
+       assert(invoc);\r
+\r
+       m_invoc = invoc;\r
+       m_sender = MSG_SENDER_DBUS;\r
+       m_msgq_req = NULL;\r
+}\r
+\r
+CMessage::~CMessage(void)\r
+{\r
+       if (m_msgq_req)\r
+               free(m_msgq_req);\r
+}\r
+\r
+int CMessage::GetReqType(void)\r
+{\r
+       int req_type = RMS_REQUEST_MAX;\r
+       assert(m_msgq_req);\r
+\r
+       switch (m_sender) {\r
+               case MSG_SENDER_MSGQ:\r
+                       req_type = m_msgq_req->type;\r
+                       break;\r
+               case MSG_SENDER_DBUS:\r
+               case MSG_SENDER_INTERNAL:\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("undefined sender(%d)", m_sender);\r
+                       break;\r
+       }\r
+\r
+       return req_type;\r
+}\r
+\r
+bool CMessage::IsMsgForScalerDbus(void)\r
+{\r
+       std::string method_name = g_dbus_method_invocation_get_method_name(m_invoc);\r
+\r
+       if (!method_name.compare("FindDeviceId"))\r
+               return true;\r
+       if (!method_name.compare("SwapResources"))\r
+               return true;\r
+       if (!method_name.compare("GetScalerState"))\r
+               return true;\r
+       if (!method_name.compare("GetScalerHWID"))\r
+               return true;\r
+       if (!method_name.compare("RestoreResources"))\r
+               return true;\r
+\r
+       return false;\r
+}\r
+\r
+bool CMessage::IsMsgForScalerMsgQ(void)\r
+{\r
+       bool result = false;\r
+       switch (m_msgq_req->type) {\r
+               case RMS_REQUEST_ALLOCATE_RESOURCE:\r
+                       for (int i = 0; i < m_msgq_req->request_num; i++) {\r
+                               if (ri_is_video_scaler_category(m_msgq_req->resource[i]))\r
+                               {\r
+                                       result = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       break;\r
+               case RMS_REQUEST_RELEASE_RESOURCES:\r
+                       int category_type;\r
+                       for (int i = 0; i < m_msgq_req->request_num; i++) {\r
+                               ri_get_category_type_by_device_id(m_msgq_req->resource[i], &category_type);\r
+                               if (ri_is_video_scaler_category(category_type))\r
+                               {\r
+                                       result = true;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       break;\r
+               case RMS_REQUEST_UNREGISTER:\r
+               case RMS_REQUEST_REGISTER:\r
+               case RMS_REQUEST_QUERY:\r
+               case RMS_REQUEST_SET_PRIORITY:\r
+               case RMS_REQUEST_SET_APPID:\r
+                       result = false;\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("undefined req type(%d)", m_msgq_req->type);\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+void CMessage::PrintInfo(void)\r
+{\r
+       switch (m_sender) {\r
+               case MSG_SENDER_MSGQ:\r
+                       PrintMsgQ();\r
+                       break;\r
+               case MSG_SENDER_DBUS:\r
+                       PrintDbus();\r
+                       break;\r
+               case MSG_SENDER_INTERNAL:\r
+                       PrintInternal();\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("undefined sender(%d)", m_sender);\r
+                       break;\r
+       }\r
+}\r
+\r
+void CMessage::PrintDbus(void)\r
+{\r
+       SERVER_ERR("Sender:Dbus/%s", g_dbus_method_invocation_get_method_name(m_invoc));\r
+}\r
+\r
+void CMessage::PrintInternal(void)\r
+{\r
+       SERVER_ERR("Sender:Internal/%s", m_name.c_str());\r
+}\r
+\r
+void CMessage::PrintMsgQ(void)\r
+{\r
+       SERVER_ERR("Sender:MsgQ/type(%d)/cid(%d)/num(%d)", m_msgq_req->type, m_msgq_req->handle, m_msgq_req->request_num);\r
+}\r
+\r
+bool CMessage::IsUnlockMsg(void)\r
+{\r
+       if (m_sender != MSG_SENDER_INTERNAL)\r
+               return false;\r
+\r
+       return (!m_name.compare("NotifyUnlock"));\r
+}\r
+\r
+bool CMessage::IsMsgForScaler(void)\r
+{\r
+       bool result = false;\r
+\r
+       switch (m_sender) {\r
+               case MSG_SENDER_MSGQ:\r
+                       result = IsMsgForScalerMsgQ();\r
+                       break;\r
+               case MSG_SENDER_DBUS:\r
+                       result = IsMsgForScalerDbus();\r
+                       break;\r
+               case MSG_SENDER_INTERNAL:\r
+                       result = false;\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("undefined sender(%d)", m_sender);\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+bool CMessage::IsMsgFor(ResourceType rsc_type)\r
+{\r
+       bool result = false;\r
+\r
+       switch (rsc_type) {\r
+               case ResourceType::VIDEO_SCALER:\r
+                       result = IsMsgForScaler();\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
diff --git a/src/CMessageHandler.cpp b/src/CMessageHandler.cpp
new file mode 100644 (file)
index 0000000..729d79c
--- /dev/null
@@ -0,0 +1,1049 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <iostream>\r
+#include <sys/types.h>\r
+#include <sys/ipc.h>\r
+#include <sys/msg.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <trace.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+#include <gio/gio.h>\r
+\r
+#include <CMessage.h>\r
+#include <CMessageHandler.h>\r
+#include <CCallback.h>\r
+#include <CDebugUtils.h>\r
+#include <rms_debug.h>\r
+#include <CHandleManager.h>\r
+#include <CResourceManager.h>\r
+#include <CConsumerContainer.h>\r
+#include <CQueryHandler.h>\r
+#include <CAsyncQueue.h>\r
+#include <CCache.h>\r
+#include <CDbusHandler.h>\r
+\r
+#define RMS_HANLDE_COMMON 100 // common handle for the request rm_register() is not required\r
+#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))\r
+\r
+struct rms_msg_handler {\r
+       const char *msg_name;\r
+       CMessageHandler::MsgHandler handler;\r
+};\r
+\r
+CMessageHandler::CMessageHandler(CResourceManager *rsc_mgr)\r
+{\r
+       assert(rsc_mgr);\r
+\r
+       msgq_rx = new CMessageQueue(MSG_QUEUE_RX);\r
+       msgq_tx = new CMessageQueue(MSG_QUEUE_TX);\r
+       async_queue = new CAsyncQueue();\r
+       async_pending_queue = new CAsyncQueue();\r
+\r
+       m_rsc_mgr = rsc_mgr;\r
+       m_query_h = new CQueryHandler(rsc_mgr);\r
+       m_handle_mgr = new CHandleManager(rsc_mgr);\r
+       m_lock_ctr = CLockController::GetInstance();\r
+       m_lock_ctr->SetMsgQ(async_queue);\r
+\r
+       CCallback::InitCallback();\r
+       InitDbusHandlers();\r
+       InitInternalMsgHandlers();\r
+}\r
+\r
+CMessageHandler::~CMessageHandler(void)\r
+{\r
+\r
+}\r
+\r
+void CMessageHandler::InitDbusHandlers(void)\r
+{\r
+       struct rms_msg_handler dbus_handlers[] = {\r
+               {"RegisterResource", &CMessageHandler::RegisterResource},\r
+               {"GetResourceState", &CMessageHandler::GetResourceState},\r
+               {"GetResourceList", &CMessageHandler::GetResourceList},\r
+               {"GetRscCollectionState", &CMessageHandler::GetResourceCollectionState},\r
+               {"FindDeviceId", &CMessageHandler::FindDeviceId},\r
+               {"SwapResources", &CMessageHandler::SwapResources},\r
+               {"GetScalerState", &CMessageHandler::GetScalerState},\r
+               {"GetAppId", &CMessageHandler::GetAppId},\r
+               {"GetActiveAudioOut", &CMessageHandler::GetActiveAudioOut},\r
+               {"GetScalerHWID", &CMessageHandler::GetScalerHWID},\r
+               {"RestoreResources", &CMessageHandler::RestoreResources},\r
+               {"NotifyResourcePolicy", &CMessageHandler::NotifyResourcePolicy},\r
+               {"NotifyAppZoneInfo", &CMessageHandler::NotifyAppZoneInfo}\r
+               // Please add a new dbus message handler here\r
+       };\r
+\r
+       std::string msg_name;\r
+       for (unsigned int i = 0; i < ARRAY_SIZE(dbus_handlers); i++) {\r
+               msg_name.assign(dbus_handlers[i].msg_name);\r
+               m_dbus_handlers.insert(std::pair<std::string, CMessageHandler::MsgHandler>(msg_name, dbus_handlers[i].handler));\r
+       }\r
+}\r
+\r
+void CMessageHandler::InitInternalMsgHandlers(void)\r
+{\r
+       struct rms_msg_handler internal_msg_handlers[] = {\r
+               {"NotifyWatchdog", &CMessageHandler::NotifyWatchdog}\r
+               // Please add a new internal message handler here\r
+       };\r
+\r
+       std::string msg_name;\r
+       for (unsigned int i = 0; i < ARRAY_SIZE(internal_msg_handlers); i++) {\r
+               msg_name.assign(internal_msg_handlers[i].msg_name);\r
+               m_internal_msg_handlers.insert(std::pair<std::string, CMessageHandler::MsgHandler>(msg_name, internal_msg_handlers[i].handler));\r
+       }\r
+}\r
+\r
+void CMessageHandler::m_ConstructRequestedDevice(rms_msg_request *request, rms_requests_device_s *requested_resource)\r
+{\r
+       requested_resource->resources_num = request->request_num;\r
+\r
+       for (int i = 0; i < requested_resource->resources_num; i++) {\r
+               requested_resource->devices[i].device_id = request->resource[i];\r
+               requested_resource->devices[i].requested_state = (rms_requests_resource_state_e) request->state[i];\r
+       }\r
+}\r
+\r
+int CMessageHandler::Run(void)\r
+{\r
+       if (g_thread_new("rms_msgq_thread", msgQThread, this) == NULL) {\r
+               SERVER_ERR("failed to create rms_msgq thread");\r
+               assert(0);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       if (g_thread_new("rms_msg_thread", msgThread, this) == NULL) {\r
+               SERVER_ERR("event loop thread create failed\n");\r
+               assert(0);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       m_dbus_h = new CDbusHandler(async_queue);\r
+       return RMS_OK;\r
+}\r
+\r
+gpointer CMessageHandler::msgQThread(gpointer data)\r
+{\r
+       assert(data);\r
+\r
+       CMessageHandler *msg_handler = (CMessageHandler*) data;\r
+       CAsyncQueue *asyncq = msg_handler->async_queue;\r
+       CMessageQueue *msgq = msg_handler->msgq_rx;\r
+       rms_msg_request req;\r
+\r
+       while (1) {\r
+               memset(&req, 0, sizeof(rms_msg_request));\r
+\r
+               if (msgq->receive(&req, RMS_REQUEST_DATA_TYPE_ALL) != RMS_OK)\r
+                       continue;\r
+\r
+               SERVER_DBG("push req type(%d)-pid(%d)-cid(%d)-len(%d)", req.type, req.pid, req.handle, asyncq->length());\r
+\r
+               CMessage *msg = new CMessage(&req);\r
+               asyncq->push(msg);\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+gpointer CMessageHandler::msgThread(gpointer data)\r
+{\r
+       assert(data);\r
+       SERVER_INFO("prepare to handle messages");\r
+\r
+       CMessageHandler *msg_handler = (CMessageHandler*) data;\r
+\r
+       while (1) {\r
+               msg_handler->ProcessMessage();\r
+               usleep(30000);\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+bool CMessageHandler::IsRegisteredHandle(int handle)\r
+{\r
+       return (CConsumerContainer::getInstance()->findConsumer(handle) != NULL);\r
+}\r
+\r
+void CMessageHandler::SetRequesterInfo(rms_msg_request *request)\r
+{\r
+       char *app_id = m_handle_mgr->GetAppID(request->handle);\r
+       m_handle_mgr->GetPriority(request->handle, &request->main_priority, &request->sub_priority);\r
+\r
+       snprintf(request->app_id, RMS_APPID_LENGTH, "%s", (app_id) ? app_id : "");\r
+\r
+       SERVER_INFO("handle(%d)-app_id(%s)", request->handle, request->app_id);\r
+\r
+       if (app_id)\r
+               free(app_id);\r
+}\r
+\r
+\r
+void CMessageHandler::m_RegisterConsumer(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       char cmd[RMS_NAME_BUF_SIZE] = {0,};\r
+\r
+       int handle = m_handle_mgr->GetNewHandle(request->pid, request->main_priority, request->sub_priority, request->app_pid, request->app_id);\r
+\r
+       response->result = (handle == RMS_HANDLE_NOT_AVAILABLE) ? RMS_ERROR : RMS_OK;\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_REGISTER, handle, request->pid);\r
+\r
+       if (response->result == RMS_ERROR)\r
+               return;\r
+\r
+       if (m_rsc_mgr->RegisterConsumer(handle, request->pid, request->app_id, request->main_priority, request->sub_priority) != RMS_OK)\r
+               SERVER_ERR("failed to add consumer to manager. handle[%d]", handle);\r
+\r
+       rms_get_cmd_name(request->pid, cmd, sizeof(cmd));\r
+\r
+       SERVER_INFO("newly assigned handle(%d) - pid(%d)-(%s)", response->handle, request->pid, cmd);\r
+}\r
+\r
+void CMessageHandler::m_UnregisterConsumer(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       SERVER_INFO("request for unregister handle(%d)", request->handle);\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_UNREGISTER, request->handle, request->pid);\r
+\r
+       if (!IsRegisteredHandle(request->handle)) {\r
+               response->result = RMS_ERROR;\r
+               return;\r
+       }\r
+\r
+       response->result = m_handle_mgr->RemoveHandle(request->handle, request->pid);\r
+\r
+       if (response->result != RMS_OK)\r
+               return;\r
+\r
+       m_rsc_mgr->UnregisterConsumer(request->handle);\r
+}\r
+\r
+void CMessageHandler::m_FreeAllocatedDevice(rms_return_device_s *allocated_device)\r
+{\r
+       if (allocated_device->device_ids) {\r
+               free(allocated_device->device_ids);\r
+               allocated_device->device_ids = NULL;\r
+       }\r
+\r
+       for (int i=0 ; i < allocated_device->resources_num; i++) {\r
+               if (allocated_device->devices[i].device_path) {\r
+                       free((void*)allocated_device->devices[i].device_path);\r
+                       allocated_device->devices[i].device_path = NULL;\r
+               }\r
+       }\r
+\r
+       if (allocated_device->devices) {\r
+               free(allocated_device->devices);\r
+               allocated_device->devices = NULL;\r
+       }\r
+}\r
+\r
+void CMessageHandler::m_Free(consumer_reclaim_s *consumer_info)\r
+{\r
+       if (!consumer_info)\r
+               return;\r
+\r
+       if (!consumer_info->consumer_info)\r
+               return;\r
+\r
+       for (int i = 0; i < consumer_info->ret_quantity; i++) {\r
+               if (consumer_info->consumer_info[i].conflicted_resources != NULL)\r
+                       free(consumer_info->consumer_info[i].conflicted_resources);\r
+       }\r
+\r
+       free(consumer_info->consumer_info);\r
+}\r
+\r
+void CMessageHandler::m_AllocateResources(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       trace_begin("RSC ALLOCATE START");\r
+       trace_end();\r
+\r
+       if (!IsRegisteredHandle(request->handle)) {\r
+               m_ConstructResponse(response, request->data_type, RMS_RESPONSE_ALLOCATE_RESOURCE, request->handle, request->pid);\r
+               response->result = RMS_ERROR;\r
+               return;\r
+       }\r
+\r
+       int result = RMS_OK;\r
+       bool need_response = true;\r
+       rms_return_device_s allocated_device;\r
+       memset(&allocated_device, 0, sizeof(rms_return_device_s));\r
+\r
+       m_handle_mgr->ReclaimAllInvalidCustomer(request->pid);\r
+\r
+       SetRequesterInfo(request);\r
+\r
+       result = m_rsc_mgr->AllocateResources(request, &allocated_device);\r
+\r
+       bool needReclaimResources = (result == RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+\r
+       if (needReclaimResources) {\r
+               consumer_reclaim_s consumers_reclaim;\r
+               memset(&consumers_reclaim, 0, sizeof(consumers_reclaim));\r
+               int zone_id = -1;\r
+               if (m_rsc_mgr->FindReclaimableConsumers(request, &consumers_reclaim, &zone_id) == RMS_OK) {\r
+                       CResourceDB::getInstance()->AddReclaimResources(&consumers_reclaim);\r
+                       if (ReclaimResources(result, request->handle, zone_id, &consumers_reclaim, &need_response) == RMS_OK) {\r
+                               result = m_rsc_mgr->AllocateResources(request, &allocated_device);\r
+                       }\r
+                       CResourceDB::getInstance()->ClearReclaimResources();\r
+               }\r
+               m_Free(&consumers_reclaim);\r
+       }\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_ALLOCATE_RESOURCE, request->handle, request->pid);\r
+\r
+       response->result = result;\r
+       response->error_type = (result == RMS_OK) ? RMS_ERR_TYPE_NONE : (rms_error_type_e)allocated_device.error_type;\r
+       response->resource_num = allocated_device.resources_num;\r
+\r
+       if (!need_response)\r
+               response->error_type = RMS_ERR_TYPE_TERMINATED_PROCESS;\r
+\r
+       for (int i = 0; i < response->resource_num; i++) {\r
+               response->resource[i] = allocated_device.device_ids[i];\r
+       }\r
+\r
+       m_FreeAllocatedDevice(&allocated_device);\r
+       CCache::getInstance()->Drop();\r
+\r
+       trace_begin("RSC ALLOCATE END");\r
+       trace_end();\r
+}\r
+\r
+void CMessageHandler::m_ReleaseResources(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       SERVER_DBG("request for deallocation");\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_RELEASE_RESOURCES, request->handle, request->pid);\r
+\r
+       if (!IsRegisteredHandle(request->handle)) {\r
+               response->result = RMS_ERROR;\r
+               return;\r
+       }\r
+\r
+       rms_requests_device_s requested_resource;\r
+       memset(&requested_resource, 0, sizeof(rms_requests_device_s));\r
+\r
+       m_ConstructRequestedDevice(request, &requested_resource);\r
+\r
+       response->result = m_rsc_mgr->ReleaseResources(request->handle, &requested_resource);\r
+}\r
+\r
+void CMessageHandler::m_Query(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       int answer = 0;\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_QUERY, request->handle, request->pid);\r
+\r
+       m_handle_mgr->ReclaimAllInvalidCustomer(request->handle);\r
+\r
+       response->result = m_query_h->GetAnswer(request, &answer);\r
+       response->is_available = answer;\r
+\r
+       SERVER_INFO("query on (%d), result(%d)", request->sub_type, answer);\r
+}\r
+\r
+void CMessageHandler::m_SetConsumerPriority(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       SERVER_INFO("request for priority setting. priority(%d)", request->main_priority);\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_SET_PRIORITY, request->handle, request->pid);\r
+\r
+       response->result = m_handle_mgr->SetPriority(request->handle, request->main_priority, request->sub_priority);\r
+}\r
+\r
+void CMessageHandler::m_SetAppID(rms_msg_request *request, rms_msg_response *response)\r
+{\r
+       SERVER_INFO("request for appid setting. appid(%s)", request->app_id);\r
+\r
+       m_ConstructResponse(response, request->data_type, RMS_RESPONSE_SET_APPID, request->handle, request->pid);\r
+\r
+       int ret = m_handle_mgr->SetAppID(request->handle, request->app_id);\r
+\r
+       if (ret != RMS_OK) {\r
+               SERVER_ERR("cannot update appid. handle(%d). ret(%d)", request->handle, ret);\r
+\r
+               response->result = RMS_ERROR;\r
+               return;\r
+       }\r
+\r
+       response->result = m_rsc_mgr->SetAppId(request->handle, request->app_id);\r
+}\r
+\r
+CMessageHandler::msg_handler CMessageHandler::handlers[RMS_REQUEST_MAX] = {\r
+       &CMessageHandler::m_RegisterConsumer,\r
+       &CMessageHandler::m_UnregisterConsumer,\r
+       &CMessageHandler::m_AllocateResources,\r
+       &CMessageHandler::m_ReleaseResources,\r
+       &CMessageHandler::m_Query,\r
+       &CMessageHandler::m_SetConsumerPriority,\r
+       &CMessageHandler::m_SetAppID,\r
+};\r
+\r
+void CMessageHandler::ProcessMsgQMessage(CMessage *msg)\r
+{\r
+       if (!IsValidRequest(msg->GetReqType())) {\r
+               SERVER_ERR("invalid req type(%d)", msg->GetReqType());\r
+               return;\r
+       }\r
+\r
+       rms_msg_response resp;\r
+       memset(&resp, 0, sizeof(rms_msg_response));\r
+\r
+       rms_msg_request *req = msg->GetRequest();\r
+       SERVER_INFO("req type(%d)-pid(%d)-cid(%d)-t(%lu)", req->type, req->pid, req->handle, req->time);\r
+\r
+       (this->*handlers[req->type])(msg->GetRequest(), &resp);\r
+\r
+       if (resp.error_type == RMS_ERR_TYPE_TERMINATED_PROCESS) {\r
+               SERVER_ERR("skip to send a response (%d)", req->pid);\r
+               return;\r
+       }\r
+\r
+       if (msgq_tx->send(&resp) != RMS_OK) {\r
+               SERVER_ERR("failed to send response");\r
+       }\r
+}\r
+\r
+GVariant *CMessageHandler::RegisterResource(GVariant *params)\r
+{\r
+       char *dev_name;\r
+       char *dev_node;\r
+       int category;\r
+       int sharable_count;\r
+\r
+       g_variant_get(params, "(&ssii)", &dev_name, &dev_node, &category, &sharable_count);\r
+\r
+       SERVER_INFO("dev_name(%s)/dev_node(%s)/category(%d)/sharable(%d)", dev_name, dev_node, category, sharable_count);\r
+       return g_variant_new("(i)", RMS_OK);\r
+}\r
+\r
+GVariant *CMessageHandler::GetResourceState(GVariant *params)\r
+{\r
+       int device_id;\r
+       int state;\r
+\r
+       g_variant_get(params, "(i)", &device_id);\r
+\r
+       state = m_rsc_mgr->GetResourceState(device_id);\r
+\r
+       SERVER_INFO("state (%d:%d)", device_id, state);\r
+\r
+       return g_variant_new("(i)", state);\r
+}\r
+\r
+GVariant *CMessageHandler::FindDeviceId(GVariant *params)\r
+{\r
+       int virtual_id;\r
+       int real_id;\r
+\r
+       g_variant_get(params, "(i)", &virtual_id);\r
+\r
+       real_id = m_rsc_mgr->FindDeviceId(virtual_id);\r
+\r
+       SERVER_INFO("real id (%d:%d)", virtual_id, real_id);\r
+\r
+       return g_variant_new("(i)", real_id);\r
+}\r
+\r
+GVariant *CMessageHandler::GetScalerHWID(GVariant *params)\r
+{\r
+       int zone_id;\r
+       int hw_id;\r
+\r
+       g_variant_get(params, "(i)", &zone_id);\r
+\r
+       hw_id = m_rsc_mgr->GetScalerHWId(zone_id);\r
+\r
+       SERVER_INFO("hw id (%d:%d)", zone_id, hw_id);\r
+\r
+       return g_variant_new("(i)", hw_id);\r
+}\r
+\r
+GVariant *CMessageHandler::SwapResources(GVariant *params)\r
+{\r
+       int device_id_a;\r
+       int device_id_b;\r
+       int result = 0;\r
+\r
+       g_variant_get(params, "(ii)", &device_id_a, &device_id_b);\r
+\r
+       result = m_rsc_mgr->SwapResources(device_id_a, device_id_b);\r
+\r
+       SERVER_INFO("swap result (%d:%d) > (%d)", device_id_a, device_id_b, result);\r
+\r
+       return g_variant_new("(i)", result);\r
+}\r
+\r
+GVariant *CMessageHandler::RestoreResources(GVariant *params)\r
+{\r
+       int category_id;\r
+       int result = 0;\r
+\r
+       g_variant_get(params, "(i)", &category_id);\r
+\r
+       result = m_rsc_mgr->RestoreResources(category_id);\r
+\r
+       SERVER_INFO("restore result (%d) > (%d)", category_id, result);\r
+\r
+       return g_variant_new("(i)", result);\r
+}\r
+\r
+GVariant *CMessageHandler::NotifyResourcePolicy(GVariant *params)\r
+{\r
+       int policy;\r
+       int result = 0;\r
+\r
+       g_variant_get(params, "(i)", &policy);\r
+\r
+       m_rsc_mgr->ResetZoneIds();\r
+\r
+       SERVER_INFO("notify result (%d) > (%d)", policy, result);\r
+       return g_variant_new("(i)", result);\r
+}\r
+\r
+GVariant *CMessageHandler::NotifyAppZoneInfo(GVariant *params)\r
+{\r
+       char *app_id;\r
+       int zone_id;\r
+       int result = 0;\r
+\r
+       g_variant_get(params, "(&si)", &app_id, &zone_id);\r
+\r
+       if (!app_id) {\r
+               result = -1;\r
+               SERVER_INFO("invalid param (%s:%d) - result(%d)", "null", zone_id, result);\r
+               return g_variant_new("(i)", result);\r
+       }\r
+\r
+       m_rsc_mgr->UpdateZoneIds(app_id, zone_id);\r
+\r
+       SERVER_INFO("notify result (%s:%d) > (%d)", app_id, zone_id, result);\r
+       return g_variant_new("(i)", result);\r
+}\r
+\r
+GVariant *CMessageHandler::GetResourceList(GVariant *params)\r
+{\r
+       int category_id;\r
+\r
+       g_variant_get(params, "(i)", &category_id);\r
+\r
+       SERVER_DBG("category (%d)", category_id);\r
+\r
+       GVariantBuilder builder;\r
+       g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(iissi))"));\r
+\r
+       g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iissi)"));\r
+       m_rsc_mgr->GetResourceList(category_id, &builder);\r
+       g_variant_builder_close(&builder);\r
+\r
+       return g_variant_builder_end(&builder);\r
+}\r
+\r
+GVariant *CMessageHandler::GetScalerState(GVariant *params)\r
+{\r
+       SERVER_INFO("GetScalerState");\r
+\r
+       GVariantBuilder builder;\r
+       g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(iiiiis))"));\r
+\r
+       g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iiiiis)"));\r
+       m_rsc_mgr->GetScalerState(&builder);\r
+       g_variant_builder_close(&builder);\r
+\r
+       return g_variant_builder_end(&builder);\r
+}\r
+\r
+GVariant *CMessageHandler::GetAppId(GVariant *params)\r
+{\r
+       int result = 0;\r
+       int handle;\r
+       g_variant_get(params, "(i)", &handle);\r
+\r
+       SERVER_INFO("GetAppId(%d)", handle);\r
+\r
+       CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(handle);\r
+       if (!consumer) {\r
+               SERVER_ERR("consumer(%d) not found", handle);\r
+               result = -1;\r
+               return g_variant_new("(is)", result, "");\r
+       }\r
+\r
+       return g_variant_new("(is)", result, (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str());\r
+}\r
+\r
+GVariant *CMessageHandler::GetResourceCollectionState(GVariant *params)\r
+{\r
+       int collection;\r
+\r
+       g_variant_get(params, "(i)", &collection);\r
+\r
+       SERVER_INFO("collection (%d)", collection);\r
+\r
+       GVariantBuilder builder;\r
+       g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(isiiis))"));\r
+\r
+       g_variant_builder_open(&builder, G_VARIANT_TYPE("a(isiiis)"));\r
+       m_rsc_mgr->GetResourceCollectionState(collection, &builder);\r
+       g_variant_builder_close(&builder);\r
+\r
+       return g_variant_builder_end(&builder);\r
+}\r
+\r
+GVariant *CMessageHandler::GetActiveAudioOut(GVariant *params)\r
+{\r
+       int cid;\r
+       int active_audio_out;\r
+\r
+       g_variant_get(params, "(i)", &cid);\r
+\r
+       active_audio_out = m_rsc_mgr->GetActiveAudioOut(cid);\r
+       SERVER_INFO("active_audio_out(%d:%d)", cid, active_audio_out);\r
+\r
+       return g_variant_new("(i)", active_audio_out);\r
+}\r
+\r
+void CMessageHandler::ProcessDbusMessage(CMessage *msg)\r
+{\r
+       GDBusMethodInvocation *invoc = msg->GetMethodInvocation();\r
+       std::string method_name(g_dbus_method_invocation_get_method_name(invoc));\r
+\r
+       auto it = m_dbus_handlers.find(method_name);\r
+       if (it == m_dbus_handlers.end()) {\r
+               SERVER_ERR("handler is not found (%s)", method_name.c_str());\r
+               return;\r
+       }\r
+\r
+       GVariant *params = g_dbus_method_invocation_get_parameters(invoc);\r
+       GVariant *result = (this->*(it->second))(params);\r
+\r
+       g_dbus_method_invocation_return_value(invoc, result);\r
+}\r
+\r
+void CMessageHandler::ProcessInternalMessage(CMessage *msg)\r
+{\r
+       auto it = m_internal_msg_handlers.find(msg->GetName());\r
+       if (it == m_internal_msg_handlers.end()) {\r
+               SERVER_ERR("handler is not found (%s)", msg->GetName().c_str());\r
+               return;\r
+       }\r
+\r
+       (this->*(it->second))(NULL);\r
+}\r
+\r
+void CMessageHandler::EmptyPendingQueue(void)\r
+{\r
+       if (async_pending_queue->length() <= 0)\r
+               return;\r
+\r
+       SERVER_WARN("empty pending queue(%d)", async_pending_queue->length());\r
+       async_queue->push(async_pending_queue);\r
+}\r
+\r
+void CMessageHandler::InsertPendingQueue(CMessage *msg)\r
+{\r
+       SERVER_WARN("msg locked");\r
+       msg->PrintInfo();\r
+       async_pending_queue->push(msg);\r
+}\r
+\r
+int CMessageHandler::ProcessMessage(void)\r
+{\r
+       CMessage *msg = (CMessage*) async_queue->pop();\r
+       assert(msg);\r
+\r
+       if ((m_lock_ctr->GetLockCount() > 0) && m_lock_ctr->IsLocked(msg)) {\r
+               InsertPendingQueue(msg);\r
+               return 0;\r
+       }\r
+\r
+       if (msg->IsUnlockMsg()) {\r
+               EmptyPendingQueue();\r
+               delete msg;\r
+               return 0;\r
+       }\r
+\r
+       switch (msg->GetSender()) {\r
+               case MSG_SENDER_MSGQ:\r
+                       ProcessMsgQMessage(msg);\r
+                       break;\r
+               case MSG_SENDER_DBUS:\r
+                       ProcessDbusMessage(msg);\r
+                       break;\r
+               case MSG_SENDER_INTERNAL:\r
+                       ProcessInternalMessage(msg);\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       delete msg;\r
+\r
+       return 0;\r
+}\r
+\r
+bool CMessageHandler::IsAllResourcesReclaimed(rms_consumer_tobe_returned_s *consumer_info)\r
+{\r
+       for (int idx = 0; idx < consumer_info->n_conflicted; idx++) {\r
+               if (!m_rsc_mgr->IsReclaimed(consumer_info->conflicted_resources[idx].device_id, consumer_info->consumer_id)) {\r
+                       SERVER_WARN("IsReclaimed is failed");\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       SERVER_WARN("all conflicted resources are freed");\r
+\r
+       return true;\r
+}\r
+\r
+void CMessageHandler::ProcessMessage(CAsyncQueue *queue, CMessage *msg, int cid_requester, int cid_releaser)\r
+{\r
+       rms_msg_request *req = msg->GetRequest();\r
+       rms_msg_response resp;\r
+       int handle;\r
+       char cmd[RMS_NAME_BUF_SIZE] = {0,};\r
+\r
+       switch (req->type) {\r
+               case RMS_REQUEST_RELEASE_RESOURCES:\r
+\r
+                       rms_requests_device_s requested_resource;\r
+                       memset(&requested_resource, 0, sizeof(rms_requests_device_s));\r
+\r
+                       m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_RELEASE_RESOURCES, req->handle, req->pid);\r
+                       m_ConstructRequestedDevice(req, &requested_resource);\r
+\r
+                       if ((resp.result = m_rsc_mgr->ReleaseResources(req->handle, &requested_resource)) != RMS_OK)\r
+                               SERVER_ERR("failed to release resources requested by (%d)", req->handle);\r
+\r
+                       SendResponse(&resp);\r
+\r
+                       break;\r
+\r
+               case RMS_REQUEST_UNREGISTER:\r
+\r
+                       m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_UNREGISTER, req->handle, req->pid);\r
+\r
+                       SERVER_WARN("unregister requested by handle(%d)", req->handle);\r
+\r
+                       if (req->handle == cid_requester) {\r
+                               SERVER_WARN("unregister request from requester(%d), send to internal queue", req->handle);\r
+\r
+                               PushMessage(queue, msg);\r
+                       } else {\r
+                               if ((resp.result = m_handle_mgr->RemoveHandle(req->handle, req->pid)) == RMS_OK) {\r
+                                       m_rsc_mgr->UnregisterConsumer(req->handle);\r
+                               }\r
+\r
+                               SendResponse(&resp);\r
+                       }\r
+                       break;\r
+\r
+               case RMS_REQUEST_REGISTER:\r
+                       handle = m_handle_mgr->GetNewHandle(req->pid, req->main_priority, req->sub_priority, req->app_pid, req->app_id);\r
+\r
+                       resp.result = (handle == RMS_HANDLE_NOT_AVAILABLE) ? RMS_ERROR : RMS_OK;\r
+                       m_ConstructResponse(&resp, req->data_type, RMS_RESPONSE_REGISTER, handle, req->pid);\r
+\r
+                       if (resp.result == RMS_ERROR) {\r
+                               SendResponse(&resp);\r
+                               break;\r
+                       }\r
+\r
+                       if (m_rsc_mgr->RegisterConsumer(handle, req->pid, req->app_id, req->main_priority, req->sub_priority) != RMS_OK)\r
+                               SERVER_ERR("failed to add consumer to manager. handle[%d]", handle);\r
+\r
+                       rms_get_cmd_name(req->pid, cmd, sizeof(cmd));\r
+\r
+                       SERVER_INFO("newly assigned handle(%d) date type(%ld)- pid(%d)-(%s)", resp.handle, req->data_type, req->pid, cmd);\r
+                       SendResponse(&resp);\r
+                       break;\r
+\r
+               default:\r
+                       SERVER_ERR("unexpected request(%d) by handle(%d)/pid(%d)", req->type, req->handle, req->pid);\r
+\r
+                       if (req->handle == cid_releaser) {\r
+                               m_ConstructResponse(&resp, req->data_type, (rms_response_type_e)req->type, req->handle, req->pid);\r
+                               resp.result = RMS_ERROR;\r
+\r
+                               SendResponse(&resp);\r
+                       } else {\r
+                               PushMessage(queue, msg);\r
+                       }\r
+                       break;\r
+       }\r
+}\r
+\r
+int CMessageHandler::ProcessCallbackMessage(rms_consumer_tobe_returned_s *consumer_info, int requester_cid)\r
+{\r
+       CMessage *msg = NULL;\r
+       int result = RMS_OK;\r
+       CAsyncQueue *queue = new CAsyncQueue();\r
+\r
+       unsigned int timeout_ms = CCallback::GetTimeout();\r
+\r
+       while (!IsAllResourcesReclaimed(consumer_info)) {\r
+               msg = (CMessage*) async_queue->pop(timeout_ms);\r
+\r
+               if (!msg) {\r
+                       SERVER_ERR("receive cb request timeout! CID[%d]/PID[%ld]", consumer_info->consumer_id, consumer_info->process_id);\r
+                       result = RMS_ERROR;\r
+                       goto out;\r
+               }\r
+\r
+               if (msg->GetSender() == MSG_SENDER_DBUS) {\r
+                       ProcessDbusMessage(msg);\r
+               } else if (msg->GetSender() == MSG_SENDER_MSGQ) {\r
+                       SERVER_WARN("[MSG_SENDER_MSGQ] requester cid %d consumer id %d", requester_cid, consumer_info->consumer_id);\r
+                       ProcessMessage(queue, msg, requester_cid, consumer_info->consumer_id);\r
+               } else {\r
+                       ProcessInternalMessage(msg);\r
+               }\r
+\r
+               delete msg;\r
+       }\r
+\r
+out:\r
+       async_queue->push_front(queue);\r
+\r
+       delete queue;\r
+\r
+       return result;\r
+}\r
+\r
+int *CMessageHandler::m_SerializeCallbackData(const rms_consumer_tobe_returned_s *consumer_info, int reason, int *data_size)\r
+{\r
+       int num_conflicted_resources = consumer_info->n_conflicted;\r
+\r
+       int *callback_data = (int*) calloc(num_conflicted_resources + 4, sizeof(int));\r
+       assert(callback_data);\r
+\r
+       callback_data[0] = CCallback::ConvertCallbackType(reason);\r
+       callback_data[1] = consumer_info->consumer_id;\r
+       callback_data[2] = consumer_info->process_id;\r
+       callback_data[3] = num_conflicted_resources;\r
+\r
+       for (int res = 0; res < num_conflicted_resources; res++) {\r
+               callback_data[(res+4)] = consumer_info->conflicted_resources[res].virtual_id;\r
+               SERVER_DBG("- virtual_id:%d ", consumer_info->conflicted_resources[res].virtual_id);\r
+       }\r
+\r
+       *data_size = (num_conflicted_resources + 4) * sizeof(int);\r
+\r
+       return callback_data;\r
+}\r
+\r
+bool CMessageHandler::IsValidProcess(int pid)\r
+{\r
+       return rm_is_valid_pid(pid);\r
+}\r
+\r
+bool CMessageHandler::IsValidRequest(int req_type)\r
+{\r
+       return (req_type >= RMS_REQUEST_REGISTER && req_type < RMS_REQUEST_MAX);\r
+}\r
+\r
+int CMessageHandler::ReleaseInvalidProcessResources(int pid, int handle)\r
+{\r
+       m_handle_mgr->RemoveHandle(handle, pid);\r
+       CCallback::RemoveFIFOServerToClient(pid, handle);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+void CMessageHandler::NotifyConflict(consumer_reclaim_s *conflict_info, int zone_id)\r
+{\r
+       if (!conflict_info)\r
+               return;\r
+\r
+       int consumer_id = -1;\r
+       int device_id = -1;\r
+       int category_id = -1;\r
+       int app_zone_id = -1;\r
+       int n_consumer = conflict_info->ret_quantity;\r
+       CConsumer *consumer = NULL;\r
+\r
+       GError *error = NULL;\r
+       GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);\r
+\r
+       if (!connection) {\r
+               SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown");\r
+               goto out;\r
+       }\r
+\r
+       for (int i = 0; i < n_consumer; i++) {\r
+               consumer_id = conflict_info->consumer_info[i].consumer_id;\r
+               consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id);\r
+\r
+               for (int j = 0; j < conflict_info->consumer_info[i].n_conflicted; j++) {\r
+                       device_id = conflict_info->consumer_info[i].conflicted_resources[j].device_id;\r
+                       app_zone_id = m_rsc_mgr->GetZoneId(device_id);\r
+                       category_id = conflict_info->consumer_info[i].conflicted_resources[j].category_id;\r
+                       SERVER_INFO("send resource conflict (%d:%d:%d:%s:%d:%d)",\r
+                               category_id, device_id, consumer_id, (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str(), app_zone_id, zone_id);\r
+                       if (!g_dbus_connection_emit_signal(connection,\r
+                                                               NULL,\r
+                                                               RM_DBUS_OBJ_PATH,\r
+                                                               RM_DBUS_INTERFACE_NAME,\r
+                                                               "RscConflicted",\r
+                                                               g_variant_new("(iiisii)", category_id, device_id, consumer_id,\r
+                                                                       (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str() : consumer->GetAppID().c_str(), app_zone_id, zone_id),\r
+                                                               &error)) {\r
+                               SERVER_ERR("failed to send resource conflict (%d:%d:%d:%s)-%s", category_id, device_id, consumer_id,\r
+                                       (consumer->GetAppID().empty()) ? consumer->GetCmdName().c_str():consumer->GetAppID().c_str(), (error) ? error->message : "unknown");\r
+                       }\r
+               }\r
+       }\r
+out:\r
+       if (error)\r
+               g_error_free(error);\r
+}\r
+\r
+int CMessageHandler::ReclaimResources(int reason, int requester_cid, int requester_zone_id, consumer_reclaim_s *conflict_info, bool *need_response)\r
+{\r
+       int num_consumers = conflict_info->ret_quantity;\r
+       int data_size = 0;\r
+       int *callback_data = NULL;\r
+       char cmd[RMS_NAME_BUF_SIZE] = {0,};\r
+       int err = 0;\r
+       int cid = 0;\r
+       int pid = 0;\r
+\r
+       SERVER_WARN("start to reclaim - retirable consumers : (%d)", num_consumers);\r
+\r
+       if (num_consumers > 0)\r
+               NotifyConflict(conflict_info, requester_zone_id);\r
+\r
+       for (int i = 0; i < num_consumers; i++) {\r
+               pid = (int) conflict_info->consumer_info[i].process_id;\r
+               cid = conflict_info->consumer_info[i].consumer_id;\r
+\r
+               if (!IsValidProcess(pid)) {\r
+                       SERVER_ERR("handle(%d)/pid(%d) terminated", cid, pid);\r
+                       m_rsc_mgr->ReleaseResourcesOfPid(pid);\r
+                       ReleaseInvalidProcessResources(pid, cid);\r
+                       continue;\r
+               }\r
+\r
+               SERVER_DBG("[%d]th cid[%d]/rscs[%d]", i+1, cid, conflict_info->consumer_info[i].n_conflicted);\r
+\r
+               callback_data = m_SerializeCallbackData(&conflict_info->consumer_info[i], reason, &data_size);\r
+\r
+               if (CCallback::SendCallbackMessage(cid, pid, (void*) callback_data, data_size, &err) != RMS_OK) {\r
+                       if (err == ENXIO) { //ENXIO No such device or address\r
+                               SERVER_ERR("Process cannot get callback (CID:%d)/(PID:%d)", cid, pid);\r
+                               m_rsc_mgr->ReleaseResourcesOfPid(pid);\r
+                               ReleaseInvalidProcessResources(pid, cid);\r
+                               free(callback_data);\r
+                               continue;\r
+                       }\r
+\r
+                       if (err == ENOENT && !IsRegisteredHandle(cid)) {\r
+                               SERVER_ERR("already unregistred (%d)", cid);\r
+                               free(callback_data);\r
+                               continue;\r
+                       }\r
+\r
+                       SERVER_ERR("failed to send callback message to (CID:%d)/(PID:%d), errno(%d)", cid, pid, err);\r
+                       free(callback_data);\r
+                       return RMS_ERROR;\r
+               }\r
+\r
+               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);\r
+\r
+               if (ProcessCallbackMessage(&conflict_info->consumer_info[i], requester_cid) != RMS_OK) {\r
+                       if (!IsValidProcess(pid)) {\r
+                               SERVER_ERR("handle(%d)/pid(%d) terminated", cid, pid);\r
+                               m_rsc_mgr->ReleaseResourcesOfPid(pid);\r
+                               ReleaseInvalidProcessResources(pid, cid);\r
+                               free(callback_data);\r
+\r
+                               if (!IsRegisteredHandle(requester_cid)) {\r
+                                       SERVER_ERR("requester(%d:%d) terminated as well", pid, requester_cid);\r
+                                       *need_response = false;\r
+                                       return RMS_ERROR;\r
+                               }\r
+                               continue;\r
+                       }\r
+\r
+                       rms_get_cmd_name(pid, cmd, sizeof(cmd));\r
+                       SERVER_ERR("failed to process callback request from : (%s) /(CID:%d)/(PID:%d)", cmd, cid, pid);\r
+\r
+                       rms_display_timeout_error_popup(RMS_ALARM_NO_DEALLOCATION, conflict_info->consumer_info[i]);\r
+                       int ret = rms_report_emergency(cid, pid, RMS_EMERGENCY_CONSUMER_NOT_RESPONDING);\r
+\r
+                       SERVER_ERR("release resources of cosumer(%d) forcely", pid);\r
+                       m_rsc_mgr->UnregisterConsumer(cid);\r
+                       m_handle_mgr->RemoveHandle(cid, pid);\r
+\r
+                       free(callback_data);\r
+                       return ret;\r
+               }\r
+\r
+               free(callback_data);\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CMessageHandler::SendResponse(rms_msg_response *response)\r
+{\r
+       return msgq_tx->send(response);\r
+}\r
+\r
+int CMessageHandler::PushMessage(CAsyncQueue *queue, CMessage *msg)\r
+{\r
+       CMessage *msg_copy = new CMessage(msg->GetRequest());\r
+       rms_msg_request *req = msg->GetRequest();\r
+       SERVER_INFO("push_front msg type(%d)-pid(%d)-cid(%d)", req->type, req->pid, req->handle);\r
+\r
+       queue->push_front(msg_copy);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+void CMessageHandler::m_ConstructResponse(rms_msg_response *response, int data_type, rms_response_type_e msg_type, int handle, int pid)\r
+{\r
+       assert(response);\r
+\r
+       response->data_type = data_type;\r
+       response->type = msg_type;\r
+       response->handle = handle;\r
+       response->pid = pid;\r
+}\r
+\r
+void CMessageHandler::NotifyWatchdog(void)\r
+{\r
+       if (!async_queue)\r
+               return;\r
+\r
+       SERVER_INFO("push watchdog msg");\r
+       async_queue->push(new CMessage("NotifyWatchdog"));\r
+}\r
+\r
+GVariant *CMessageHandler::NotifyWatchdog(GVariant *params)\r
+{\r
+       SERVER_INFO("send watchdog notify completed");\r
+       return NULL;\r
+}\r
diff --git a/src/CMessageQueue.cpp b/src/CMessageQueue.cpp
new file mode 100644 (file)
index 0000000..8f114ba
--- /dev/null
@@ -0,0 +1,140 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+#include <errno.h>\r
+#include <sys/types.h>\r
+#include <sys/ipc.h>\r
+#include <sys/msg.h>\r
+#include <unistd.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CMessageQueue.h>\r
+\r
+CMessageQueue::CMessageQueue(msgq_type_e type)\r
+{\r
+       msgq_type = type;\r
+\r
+       if (init() != RMS_OK) {\r
+               SERVER_ERR("failed to initialize message queue(%d)", type);\r
+               assert(0 && "failed to initialize message queue");\r
+       }\r
+}\r
+\r
+CMessageQueue::~CMessageQueue(void)\r
+{\r
+}\r
+\r
+int CMessageQueue::init(void)\r
+{\r
+       int key = getKey(msgq_type);\r
+\r
+       msgq_id = msgget((key_t) key, 0666 | IPC_CREAT);\r
+       if (msgq_id == -1) {\r
+               SERVER_ERR("failed to create a message queue (%d), errno(%d)", key, errno);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       struct msqid_ds queue_stat;\r
+       long prev_size = 0;\r
+\r
+       if (msgctl(msgq_id, IPC_STAT, &queue_stat) != 0) {\r
+               SERVER_ERR("failed to get queue info (%d:%d), errno(%d)", key, msgq_id, errno);\r
+               goto out;\r
+       }\r
+\r
+       prev_size = queue_stat.msg_qbytes;\r
+       queue_stat.msg_qbytes = msgq_size;\r
+\r
+       if (msgctl(msgq_id, IPC_SET, &queue_stat) != 0) {\r
+               SERVER_ERR("failed to set queue info (%d:%d), errno(%d)", key, msgq_id, errno);\r
+               goto out;\r
+       }\r
+\r
+       SERVER_INFO("msgq(%d:%d) size changed (%ld) -> (%ld)", key, msgq_id, prev_size, msgq_size);\r
+\r
+out:\r
+       return RMS_OK;\r
+}\r
+\r
+int CMessageQueue::send(rms_msg_response *response)\r
+{\r
+       int retry = 0;\r
+\r
+       while (msgsnd(msgq_id, (void*) response, sizeof(rms_msg_response) - sizeof(long), 0) == -1) {\r
+               SERVER_ERR("failed to send response message (%d), retry(%d) - type(%d)/cid(%d)", errno, retry, response->type, response->handle);\r
+\r
+               if (errno == EIDRM) { // errno 43 : identifier removed\r
+                       SERVER_ERR("msgid removed from system");\r
+                       if (recover() != RMS_OK)\r
+                               return RMS_ERROR;\r
+               } else if ((errno == EINVAL) && (response->data_type > 0)) {\r
+                       SERVER_ERR("msgid might be removed from system");\r
+                       if (recover() != RMS_OK) {\r
+                               return RMS_ERROR;\r
+                       }\r
+               }\r
+\r
+               if (retry >= 5) { //timeout\r
+                       return RMS_ERROR;\r
+               }\r
+\r
+               usleep(20*1000); // 20ms\r
+               retry++;\r
+       }\r
+\r
+       return RMS_OK;\r
+\r
+}\r
+\r
+int CMessageQueue::receive(rms_msg_request *request, int msg_type)\r
+{\r
+       int ret = -1;\r
+       ret = msgrcv(msgq_id, (void*) request, sizeof(rms_msg_request) - sizeof(long), msg_type, 0);\r
+\r
+       if (ret == -1) {\r
+               SERVER_ERR("failed to receive msg(%d:%d). errno(%d)", msgq_type, msgq_id, errno);\r
+\r
+               if (errno == EIDRM) { // errno 43 : identifier removed\r
+                       SERVER_ERR("WARNING! msgq(%d:%d) removed from system", msgq_type, msgq_id);\r
+                       recover();\r
+               }\r
+\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CMessageQueue::recover(void)\r
+{\r
+       int key = getKey(msgq_type);\r
+\r
+       msgq_id = msgget((key_t) key, 0666 | IPC_CREAT);\r
+\r
+       if (msgq_id == -1) {\r
+               SERVER_ERR("failed to get new msgq_id, key(%d), errno(%d)", key, errno);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_ERR("message queue recovered - (%d:%d)", key, msgq_id);\r
+       return RMS_OK;\r
+}\r
+\r
+int CMessageQueue::getKey(msgq_type_e type)\r
+{\r
+       return (type == MSG_QUEUE_RX) ? key_rx : key_tx;\r
+}\r
diff --git a/src/CQueryHandler.cpp b/src/CQueryHandler.cpp
new file mode 100644 (file)
index 0000000..a3cf4b6
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+#include <glib.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CDebugUtils.h>\r
+#include <CQueryHandler.h>\r
+\r
+CQueryHandler::CQueryHandler(CResourceManager *rsc_mgr)\r
+{\r
+       assert(rsc_mgr);\r
+       m_rsc_mgr = rsc_mgr;\r
+}\r
+\r
+CQueryHandler::~CQueryHandler(void)\r
+{\r
+}\r
+\r
+int CQueryHandler::GetAnswer(rms_msg_request *request, int *answer_out)\r
+{\r
+       int result = RMS_OK;\r
+       int answer = 0;\r
+       char process_name[RMS_NAME_BUF_SIZE] = {0,};\r
+\r
+       switch (request->sub_type) {\r
+               case RMS_QUERY_ALLOCATION:\r
+                       result = m_rsc_mgr->IsCategoryAvailableToUse(request, &answer);\r
+                       *answer_out = answer;\r
+                       break;\r
+               case RMS_QUERY_TERMINATE:\r
+                       rms_get_cmd_name(request->pid, process_name, RMS_NAME_BUF_SIZE);\r
+                       result = RMS_OK;\r
+                       *answer_out = process_htable_contains(process_name);\r
+                       break;\r
+               case RMS_QUERY_ACTIVE_DECS:\r
+                       *answer_out = m_rsc_mgr->GetActiveDecoderNum();\r
+                       result = RMS_OK;\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("not defined query type (%d)", request->sub_type);\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
diff --git a/src/CRequest.cpp b/src/CRequest.cpp
new file mode 100644 (file)
index 0000000..673ef53
--- /dev/null
@@ -0,0 +1,432 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <iostream>\r
+\r
+#include <rms_debug.h>\r
+#include "CSysInfo.h"\r
+#include "CRequester.h"\r
+#include "CRequest.h"\r
+\r
+CRequest::CRequest(CRequester *requester)\r
+:m_requester(requester)\r
+{\r
+       m_device_id = 0;\r
+       m_category_id = 0;\r
+       m_category_option = 0;\r
+       m_category = RMS_CATEGORY_NONE;\r
+       m_result = RMS_ERROR;\r
+       m_candidate_device = RMS_DEVICE_NONE;\r
+       m_allocated_device = RMS_DEVICE_NONE;\r
+       m_virtual_device = RMS_DEVICE_NONE;\r
+}\r
+\r
+CRequest::~CRequest()\r
+{\r
+}\r
+\r
+CRequester *CRequest::getRequester(void)\r
+{\r
+       return m_requester;\r
+}\r
+\r
+int CRequest::ToMultiviewZoneId(int category_option)\r
+{\r
+       const int ZONE_INFO = 0x1E00000;\r
+       int zone_id = ((category_option & ZONE_INFO) >> 21);\r
+       return zone_id;\r
+}\r
+\r
+void CRequest::SetCategory(int category_id, int category_option)\r
+{\r
+       m_category_id = category_id;\r
+       m_category_option = category_option;\r
+       m_category = ToResourceCategory(category_id, category_option);\r
+       m_mixing_mode = ToMixingMode(category_id, category_option);\r
+       m_mv_zone_id = ToMultiviewZoneId(category_option);\r
+}\r
+\r
+void CRequest::SetState(int req_state)\r
+{\r
+       m_state = (rms_requests_resource_state_e) req_state;\r
+}\r
+\r
+void CRequest::SetResult(rms_return_code_e req_result)\r
+{\r
+       m_result = req_result;\r
+}\r
+\r
+rms_return_code_e CRequest::GetResult(void)\r
+{\r
+       return m_result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::GetCategory(void)\r
+{\r
+       return m_category;\r
+}\r
+\r
+bool CRequest::IsMainDeviceRequest(void)\r
+{\r
+       if (m_state == RMS_STATE_EXCLUSIVE_AUTO)\r
+               return false;\r
+\r
+       SERVER_INFO("m_category_id(%d), option(%d)", m_category_id, m_category_option);\r
+\r
+       if (IsSupportedCategory(m_category_option)) {\r
+               if ((m_category_option & RMS_DEVICE_OPT_MAIN) || (m_category_option & RMS_FORCE_TO_MAIN))\r
+                       return true;\r
+       }\r
+\r
+       if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED)) {\r
+               return (m_category_option & RMS_DEVICE_OPT_MAIN);\r
+       }\r
+\r
+       if (m_category_id == RMS_CATEGORY_AUDIO_DECODER) {\r
+               if (m_category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED)\r
+                       return false;\r
+               if (m_category_option == RMS_DEVICE_OPT_NONE)\r
+                       return true;\r
+\r
+               return (m_category_option & RMS_DEVICE_OPT_MAIN);\r
+       }\r
+\r
+       if (m_category_id == RMS_CATEGORY_MJPEG_DECODER)\r
+               return (m_category_option & RMS_DEVICE_OPT_MAIN);\r
+\r
+       if (m_category == RMS_CATEGORY_SCALER_MULTIVIEW)\r
+               return (m_category_option & RMS_DEVICE_OPT_MAIN);\r
+\r
+       return false;\r
+}\r
+\r
+bool CRequest::IsAIDeviceRequest(void)\r
+{\r
+       if (m_state == RMS_STATE_EXCLUSIVE_AUTO)\r
+               return false;\r
+\r
+       if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED))\r
+               return (m_category_option & RMS_VIDEO_DEC_OPT_AI);\r
+\r
+       return false;\r
+}\r
+\r
+bool CRequest::IsSubDeviceRequest(void)\r
+{\r
+       if (m_state == RMS_STATE_EXCLUSIVE_AUTO)\r
+               return false;\r
+\r
+       //SERVER_DBG("m_category_id(%d), option(%d)", m_category_id, m_category_option);\r
+\r
+       if (IsSupportedCategory(m_category_option)) {\r
+               if ((m_category_option & RMS_DEVICE_OPT_SUB) || (m_category_option & RMS_FORCE_TO_SUB))\r
+                       return true;\r
+       }\r
+\r
+       if ((m_category_id == RMS_CATEGORY_VIDEO_DECODER_SUB) && (m_category_option != RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED))\r
+               return (m_category_option & RMS_DEVICE_OPT_SUB);\r
+\r
+       if (m_category_id == RMS_CATEGORY_AUDIO_DECODER_SUB) {\r
+               if (m_category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED)\r
+                       return false;\r
+               if (m_category_option == RMS_DEVICE_OPT_NONE)\r
+                       return true;\r
+\r
+               return (m_category_option & RMS_DEVICE_OPT_SUB);\r
+       }\r
+\r
+       if (m_category_id == RMS_CATEGORY_MJPEG_DECODER)\r
+               return (m_category_option & RMS_DEVICE_OPT_SUB);\r
+\r
+       if (m_category == RMS_CATEGORY_SCALER_MULTIVIEW)\r
+               return (m_category_option & RMS_DEVICE_OPT_SUB);\r
+\r
+       return false;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToVideoDecoderCategory(int category, int category_option, bool force_main, bool force_sub)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+\r
+       if (category_option == RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED) {\r
+               result = RMS_CATEGORY_NONE;\r
+       } else if ((category_option > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (category_option < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else {\r
+               if (category == RMS_CATEGORY_VIDEO_DECODER) {\r
+                       result =  (rms_rsc_category_e) ((force_sub) ? RMS_CATEGORY_VIDEO_DECODER_SUB : category);\r
+               } else if (category == RMS_CATEGORY_VIDEO_DECODER_SUB) {\r
+                       result = (rms_rsc_category_e) ((force_main) ? (rms_rsc_category_e) RMS_CATEGORY_VIDEO_DECODER : category);\r
+               } else {\r
+                       result = (rms_rsc_category_e) category;\r
+               }\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToImageDecoderCategory(int category, int category_option)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+\r
+       SERVER_INFO("category(%d)/category_option(%d)", category, category_option);\r
+\r
+       if (category_option == RMS_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED) {\r
+               result = RMS_CATEGORY_NONE;\r
+       } else if ((category_option > RMS_CATEGORY_HEIC_DECODER_OPTION) && (category_option < RMS_CATEGORY_HEIC_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else if ((category_option > RMS_CATEGORY_JPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else {\r
+               result = (rms_rsc_category_e) category;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToJpegDecoderCategory(int category, int category_option)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+\r
+       SERVER_INFO("category(%d)/category_option(%d)", category, category_option);\r
+\r
+       if (category_option == RMS_CATEGORY_JPEG_DECODER_NOT_SUPPORTED) {\r
+               result = RMS_CATEGORY_NONE;\r
+       } else if ((category_option > RMS_CATEGORY_JPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else {\r
+               result = (rms_rsc_category_e) category;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToMJpegDecoderCategory(int category, int category_option)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+\r
+       if (category_option == RMS_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED) {\r
+               result = RMS_CATEGORY_NONE;\r
+       } else if ((category_option > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (category_option < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else {\r
+               result = (rms_rsc_category_e)category;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToAudioDecoderCategory(int category, int category_option, bool force_main, bool force_sub)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+       bool support_mixing = CSysInfo::GetInstance()->IsAudioMixingSupported();\r
+\r
+       if (category_option == RMS_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED) {\r
+               result = RMS_CATEGORY_NONE;\r
+       } else if (category_option == RMS_CATEGORY_NOT_PERMITTED) {\r
+               result = RMS_CATEGORY_NOT_PERMITTED;\r
+       } else if (support_mixing && (category_option > RMS_CATEGORY_AUDIO_DECODER_OPTION && category_option < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)) {\r
+               result = (rms_rsc_category_e) category_option;\r
+       } else {\r
+               if (category == RMS_CATEGORY_AUDIO_DECODER) {\r
+                       result = (rms_rsc_category_e) ((force_sub) ? RMS_CATEGORY_AUDIO_DECODER_SUB : category);\r
+               } else if (category == RMS_CATEGORY_AUDIO_DECODER_SUB) {\r
+                       result = (rms_rsc_category_e) ((force_main) ? RMS_CATEGORY_AUDIO_DECODER : category);\r
+               } else {\r
+                       result = (rms_rsc_category_e) category;\r
+               }\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToScalerCategory(int category, int category_option, bool force_main, bool force_sub)\r
+{\r
+       if (category_option == RMS_CATEGORY_NOT_PERMITTED)\r
+               return (rms_rsc_category_e) category_option;\r
+\r
+       if (force_sub)\r
+               return RMS_CATEGORY_SCALER_SUB;\r
+\r
+       if (force_main)\r
+               return RMS_CATEGORY_SCALER;\r
+\r
+       if (category > RMS_CATEGORY_SCALER_OPTION && category < RMS_CATEGORY_SCALER_OPTION_MAX)\r
+               return (rms_rsc_category_e) category_option;\r
+\r
+       if (category_option > RMS_CATEGORY_SCALER_OPTION && category_option < RMS_CATEGORY_SCALER_OPTION_MAX)\r
+               return (rms_rsc_category_e) category_option;\r
+\r
+       return (rms_rsc_category_e) category;\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToAudioOutCategory(int category, int category_option, bool force_main, bool force_sub)\r
+{\r
+       if (category_option == RMS_CATEGORY_NOT_PERMITTED)\r
+               return (rms_rsc_category_e) category_option;\r
+\r
+       if (force_sub)\r
+               return RMS_CATEGORY_AUDIO_SUB_OUT;\r
+\r
+       if (force_main)\r
+               return RMS_CATEGORY_AUDIO_MAIN_OUT;\r
+\r
+       return (rms_rsc_category_e) category;\r
+}\r
+\r
+bool CRequest::IsSupportedCategory(int category_option)\r
+{\r
+       bool result = true;\r
+\r
+       switch (category_option) {\r
+               case RMS_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED:\r
+               case RMS_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED:\r
+               case RMS_CATEGORY_JPEG_DECODER_NOT_SUPPORTED:\r
+               case RMS_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED:\r
+               case RMS_CATEGORY_NOT_PERMITTED:\r
+                       result = false;\r
+                       break;\r
+               default:\r
+                       result = true;\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+int CRequest::UnmaskMainSubOptions(int category_option)\r
+{\r
+       int result = category_option;\r
+\r
+       result = (result & ~RMS_DEVICE_OPT_MAIN);\r
+       result = (result & ~RMS_DEVICE_OPT_SUB);\r
+\r
+       return result;\r
+}\r
+\r
+int CRequest::UnmaskMixingOptions(int category_option)\r
+{\r
+       int result = category_option;\r
+\r
+       result = (result & ~RMS_MIXING_OPT_DEFAULT);\r
+       result = (result & ~RMS_MIXING_OPT_MULTIVIEW);\r
+       result = (result & ~RMS_MIXING_OPT_INTERACTION_SOUND);\r
+\r
+       return result;\r
+}\r
+\r
+int CRequest::UnmaskForceOptions(int category_option)\r
+{\r
+       int result = category_option;\r
+\r
+       result = (result & ~RMS_FORCE_TO_MAIN);\r
+       result = (result & ~RMS_FORCE_TO_SUB);\r
+\r
+       return result;\r
+}\r
+\r
+int CRequest::UnmaskMVZoneInfo(int category_option)\r
+{\r
+       const int ZONE_INFO = 0x1E00000;\r
+\r
+       return (category_option & ~ZONE_INFO);\r
+}\r
+\r
+rms_rsc_category_e CRequest::ToResourceCategory(int category, int category_option)\r
+{\r
+       rms_rsc_category_e result = RMS_CATEGORY_NONE;\r
+       bool supported = IsSupportedCategory(category_option);\r
+       bool force_main = false;\r
+       bool force_sub = false;\r
+\r
+       if (supported) {\r
+               force_main = (category_option & RMS_FORCE_TO_MAIN);\r
+               force_sub = (category_option & RMS_FORCE_TO_SUB);\r
+               category_option = UnmaskMainSubOptions(category_option);\r
+       }\r
+\r
+       switch (category) {\r
+               case RMS_CATEGORY_VIDEO_DECODER:\r
+               case RMS_CATEGORY_VIDEO_DECODER_SUB:\r
+                       if (supported) {\r
+                               category_option = UnmaskMVZoneInfo(category_option);\r
+                               category_option = (category_option & ~RMS_VIDEO_DEC_OPT_AI);\r
+                               category_option = UnmaskForceOptions(category_option);\r
+                       }\r
+                       result = ToVideoDecoderCategory(category, category_option, force_main, force_sub);\r
+                       break;\r
+               case RMS_CATEGORY_JPEG_DECODER:\r
+                       result = ToJpegDecoderCategory(category, category_option);\r
+                       break;\r
+               case RMS_CATEGORY_MJPEG_DECODER:\r
+                       if (supported)\r
+                               category_option = UnmaskMVZoneInfo(category_option);\r
+\r
+                       result = ToMJpegDecoderCategory(category, category_option);\r
+                       break;\r
+               case RMS_CATEGORY_IMAGE_DECODER:\r
+                       result = ToImageDecoderCategory(category, category_option);\r
+                       break;\r
+               case RMS_CATEGORY_AUDIO_DECODER:\r
+               case RMS_CATEGORY_AUDIO_DECODER_SUB:\r
+                       if (supported) {\r
+                               category_option = UnmaskMixingOptions(category_option);\r
+                               category_option = UnmaskForceOptions(category_option);\r
+                       }\r
+\r
+                       result = ToAudioDecoderCategory(category, category_option, force_main, force_sub);\r
+                       break;\r
+               case RMS_CATEGORY_SCALER:\r
+               case RMS_CATEGORY_SCALER_SUB:\r
+                       if (supported)\r
+                               category_option = UnmaskMVZoneInfo(category_option);\r
+\r
+                       result = ToScalerCategory(category, category_option, force_main, force_sub);\r
+                       break;\r
+               case RMS_CATEGORY_AUDIO_MAIN_OUT:\r
+               case RMS_CATEGORY_AUDIO_SUB_OUT:\r
+                       result = ToAudioOutCategory(category, category_option, force_main, force_sub);\r
+                       break;\r
+               default:\r
+                       result = (rms_rsc_category_e) category;\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+rms_mixing_mode_e CRequest::ToMixingMode(int category, int category_option)\r
+{\r
+       if (category != RMS_CATEGORY_AUDIO_DECODER && category != RMS_CATEGORY_AUDIO_DECODER_SUB)\r
+               return RMS_MIXING_MODE_DEFAULT;\r
+\r
+       if (category_option & RMS_MIXING_OPT_MULTIVIEW)\r
+               return RMS_MIXING_MODE_MULTIVIEW;\r
+\r
+       if (category_option & RMS_MIXING_OPT_INTERACTION_SOUND)\r
+               return RMS_MIXING_MODE_INTERACTION_SOUND;\r
+\r
+       return RMS_MIXING_MODE_DEFAULT;\r
+}\r
+\r
+void CRequest::PrintResult(void)\r
+{\r
+       SERVER_WARN("result (%d) - con(%d:%s) / cat(%d) / req(%d:%d) / devId(%d) / vId(%d) / rsn(%d)",\r
+               m_result,\r
+               m_requester->getHandle(),\r
+               m_requester->getAppId().empty() ? m_requester->GetCmdName().c_str() : m_requester->getAppId().c_str(),\r
+               m_category, m_category_id, m_category_option, m_allocated_device, m_virtual_device, m_reason);\r
+}\r
diff --git a/src/CRequester.cpp b/src/CRequester.cpp
new file mode 100644 (file)
index 0000000..13de37d
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "CDebugUtils.h"\r
+#include "CRequester.h"\r
+\r
+CRequester::CRequester()\r
+{\r
+       m_handle = 0;\r
+       m_pid = 0;\r
+       m_main_priority = 0;\r
+       m_sub_priority = 0;\r
+       m_app_id.assign("");\r
+}\r
+\r
+CRequester::CRequester(rms_msg_request *req)\r
+{\r
+       m_handle = req->handle;\r
+       m_pid = req->pid;\r
+       m_main_priority = req->main_priority;\r
+       m_sub_priority = req->sub_priority;\r
+       m_app_id.assign(req->app_id);\r
+       SetCmdName(req->pid);\r
+}\r
+\r
+CRequester::~CRequester()\r
+{\r
+}\r
+\r
+void CRequester::SetCmdName(int pid)\r
+{\r
+       char cmd_name[512] = {0, };\r
+       std::string delimiter = "/";\r
+\r
+       rms_get_cmd_name(pid, cmd_name, 512);\r
+       m_cmd_name.assign(cmd_name);\r
+       m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length());\r
+}\r
+\r
+int CRequester::getHandle(void)\r
+{\r
+       return m_handle;\r
+}\r
+\r
+int CRequester::getPid(void)\r
+{\r
+       return m_pid;\r
+}\r
+\r
+int CRequester::getMainPriority(void)\r
+{\r
+       return m_main_priority;\r
+}\r
+\r
+int CRequester::getSubPriority(void)\r
+{\r
+       return m_sub_priority;\r
+}\r
diff --git a/src/CResourceService.cpp b/src/CResourceService.cpp
new file mode 100644 (file)
index 0000000..7fe4b7a
--- /dev/null
@@ -0,0 +1,123 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <glib.h>\r
+#include <vconf.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <iostream>\r
+#include <assert.h>\r
+#include <trace.h>\r
+#include <dlfcn.h>\r
+\r
+#include <CResourceService.h>\r
+#include <CDebugUtils.h>\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CMessageHandler.h>\r
+#include <CResourceManager.h>\r
+\r
+#define RM_SERVER_SMART_DEADLOCK_WATCHDOG_TIME_90_SEC 90\r
+#define RM_SERVER_WATCHDOG_TIME_10000_MSEC  10000\r
+#define RM_SERVER_INVALID_TABLE_TIME_30000_MSEC 30000\r
+\r
+int CResourceService::Init(GMainLoop *main_loop)\r
+{\r
+       CResourceManager *rsc_mgr = new CResourceManager();\r
+       if (rsc_mgr->RegisterResources() != RMS_OK) {\r
+               SERVER_ERR("RegisterResources is failed");\r
+               g_timeout_add(RM_SERVER_INVALID_TABLE_TIME_30000_MSEC, InvalidResourceTableMsgCallback, NULL);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       m_msg_h = new CMessageHandler(rsc_mgr);\r
+       if (m_msg_h->Run() != RMS_OK) {\r
+               SERVER_ERR("RUN failed");\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_INFO("Done");\r
+       return RMS_OK;\r
+}\r
+\r
+int CResourceService::IsFirstLaunch(void)\r
+{\r
+       const char *vconf_key = "memory/rsc_mgr/is_launched_before";\r
+       int is_launched_before = 0;\r
+\r
+       if (vconf_get_int(vconf_key, &is_launched_before) != 0)\r
+               SERVER_ERR("Failed to get %s", vconf_key);\r
+\r
+       if (is_launched_before == 1) {\r
+               SERVER_ERR("!!!!! Resource Manager 2nd Launch !!!!!");\r
+               return 0;\r
+       }\r
+\r
+       if (vconf_set_int(vconf_key, 1) != 0)\r
+               SERVER_ERR("Failed to set %s", vconf_key);\r
+\r
+       return 1;\r
+}\r
+\r
+void CResourceService::RequestColdPowerOff(void)\r
+{\r
+       const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg";\r
+\r
+       if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) {\r
+               SERVER_ERR("Failed to set %s", vconf_request_cold_poweroff);\r
+       }\r
+}\r
+\r
+void CResourceService::CreateWatchDogTimer(void)\r
+{\r
+}\r
+\r
+void CResourceService::SetVIPProcess(void)\r
+{\r
+       void *handle;\r
+       void (*vip_func)(void);\r
+\r
+       handle = dlopen("/lib/libproc-stat.so.5", RTLD_LAZY);\r
+\r
+       if (!handle) {\r
+               SERVER_ERR("failed to open libproc-stat.so (%s)", dlerror());\r
+               return;\r
+       }\r
+\r
+       *(void**)&vip_func = dlsym(handle, "proc_stat_set_vip_process");\r
+\r
+       if (!vip_func) {\r
+               SERVER_ERR("failed to find proc_stat_set_vip_process");\r
+               dlclose(handle);\r
+               return;\r
+       }\r
+\r
+       SERVER_INFO("set vip process");\r
+       vip_func();\r
+       dlclose(handle);\r
+}\r
+\r
+gboolean CResourceService::WatchDogCallback(gpointer data)\r
+{\r
+       return G_SOURCE_CONTINUE;\r
+}\r
+\r
+gboolean CResourceService::InvalidResourceTableMsgCallback(gpointer data)\r
+{\r
+       SERVER_ERR("resource table not loaded!");\r
+       rms_print_model_info();\r
+       return G_SOURCE_CONTINUE;\r
+}\r
diff --git a/src/CSysInfo.cpp b/src/CSysInfo.cpp
new file mode 100644 (file)
index 0000000..e33c761
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <iostream>\r
+#include <assert.h>\r
+#include <system_info.h>\r
+#include <rms_debug.h>\r
+#include <CSysInfo.h>\r
+\r
+CSysInfo *CSysInfo::m_instance = NULL;\r
+\r
+CSysInfo *CSysInfo::GetInstance(void)\r
+{\r
+       if (!m_instance) {\r
+               m_instance = new(std::nothrow) CSysInfo;\r
+               assert(m_instance);\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+bool CSysInfo::IsAudioMixingSupported(void)\r
+{\r
+       static bool init = false;\r
+       bool supported = false;\r
+\r
+       if (init)\r
+               return m_support_audio_mixing;\r
+\r
+       if (system_info_get_custom_bool("com.samsung/featureconf/multiview.dualsound", &supported) != SYSTEM_INFO_ERROR_NONE) {\r
+               SERVER_ERR("failed to get com.samsung/featureconf/multiview.dualsound");\r
+               return m_support_audio_mixing;\r
+       }\r
+\r
+       m_support_audio_mixing = supported;\r
+       init = true;\r
+       SERVER_INFO("multiview.dualsound (%d)", supported);\r
+       return m_support_audio_mixing;\r
+}\r
diff --git a/src/gen_rm_msgq.cpp b/src/gen_rm_msgq.cpp
new file mode 100644 (file)
index 0000000..92e8cd5
--- /dev/null
@@ -0,0 +1,119 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <sys/types.h>\r
+#include <sys/ipc.h>\r
+#include <sys/msg.h>\r
+#include <errno.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <sys/stat.h>\r
+#include <unistd.h>\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <unistd.h>\r
+\r
+#define RM_MSGQ_KEY_TX 8212\r
+#define RM_MSGQ_KEY_RX 8211\r
+\r
+static int _is_symlink_file(const char *path)\r
+{\r
+       struct stat st;\r
+       if (lstat(path, &st) == -1) {\r
+               SERVER_ERR("stat error. file path(%s)", path);\r
+               return 0;\r
+       }\r
+\r
+       return (S_ISLNK(st.st_mode)) ? 1 : 0;\r
+}\r
+\r
+static int _is_realpath(const char *path)\r
+{\r
+       char *rms_realpath = NULL;\r
+       int len_path = 0;\r
+       int len_realpath = 0;\r
+       int result = 1;\r
+\r
+       rms_realpath = realpath(path, NULL);\r
+\r
+       if (!rms_realpath) {\r
+               SERVER_INFO("realpath(%s) is null(%d)", path, errno);\r
+               return 0;\r
+       }\r
+\r
+       len_path = strlen(path);\r
+       len_realpath = strlen(rms_realpath);\r
+\r
+       if (len_path != len_realpath) {\r
+               SERVER_ERR("length mismatch(%d:%d)", len_path, len_realpath);\r
+               result = 0;\r
+               goto out;\r
+       }\r
+\r
+       if (strncmp(path, rms_realpath, len_path)) {\r
+               SERVER_ERR("path mismatch(%s:%s)", path, rms_realpath);\r
+               result = 0;\r
+               goto out;\r
+       }\r
+\r
+out:\r
+       free(rms_realpath);\r
+\r
+       return result;\r
+}\r
+\r
+int main()\r
+{\r
+       int msgq_tx = -1, msgq_rx = -1;\r
+       msgq_tx = msgget((key_t)RM_MSGQ_KEY_TX, 0666 | IPC_CREAT);\r
+       msgq_rx = msgget((key_t)RM_MSGQ_KEY_RX, 0666 | IPC_CREAT);\r
+\r
+       if ((msgq_tx == -1) || (msgq_rx == -1)) {\r
+               SERVER_ERR("NEW MSGQ_CREATE failed to get msgq_id - msgq_tx(%d), msgq_rx(%d)", msgq_tx, msgq_rx);\r
+               return -1;\r
+       }\r
+\r
+       SERVER_INFO("msgq_tx (%d), msgq_rx(%d)", msgq_tx, msgq_rx);\r
+\r
+       FILE *fp = NULL;\r
+       const char *flag_path = "/run/rsc_mgr_ready";\r
+\r
+       fp = fopen(flag_path,"w");\r
+\r
+       if (!fp) {\r
+               SERVER_ERR("NEW_MSGQ_CREATE Failed to create message queue(%s) errno(%d)", flag_path, errno);\r
+               return -1;\r
+       }\r
+\r
+       if (!_is_realpath(flag_path)) {\r
+               SERVER_ERR("%s is not realpath", flag_path);\r
+               fclose(fp);\r
+               return -1;\r
+       }\r
+\r
+       if (_is_symlink_file(flag_path)) {\r
+               SERVER_ERR("%s is symbolic link file", flag_path);\r
+               fclose(fp);\r
+               return -1;\r
+       }\r
+\r
+       SERVER_INFO("NEW_MSGQ_CREATE resource manager message queue(%s) created", flag_path);\r
+\r
+       fflush(fp);\r
+       fsync(fileno(fp));\r
+       fclose(fp);\r
+       return 0;\r
+}\r
diff --git a/src/manager/CCache.cpp b/src/manager/CCache.cpp
new file mode 100644 (file)
index 0000000..adde21f
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <CCache.h>\r
+\r
+CCache *CCache::m_instance = NULL;\r
+\r
+CCache *CCache::getInstance(void)\r
+{\r
+       if (!m_instance) {\r
+               m_instance = new(std::nothrow) CCache;\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+void CCache::SetAppStatus(std::string app_id, int status)\r
+{\r
+       m_visibility.insert(std::pair<std::string, int>(app_id, status));\r
+}\r
+\r
+int CCache::GetAppStatus(std::string app_id)\r
+{\r
+       auto it = m_visibility.find(app_id);\r
+\r
+       return (it == m_visibility.end()) ? -1 : it->second;\r
+}\r
+\r
+void CCache::Drop(void)\r
+{\r
+       m_visibility.clear();\r
+}\r
diff --git a/src/manager/CConsumer.cpp b/src/manager/CConsumer.cpp
new file mode 100644 (file)
index 0000000..12bac79
--- /dev/null
@@ -0,0 +1,237 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <trace.h>\r
+#include <stdlib.h>\r
+#include <iostream>\r
+#include <vconf.h>\r
+#include <aul.h>\r
+#include <system_info.h>\r
+#include <unistd.h>\r
+\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CConsumer.h>\r
+#include <CDebugUtils.h>\r
+#include <CCache.h>\r
+\r
+CConsumer::CConsumer(IN const rms_consumer_s *consumer)\r
+{\r
+       m_consumerID = consumer->consumer_id;\r
+       m_priority = consumer->priority;\r
+       m_pid = consumer->process_id;\r
+       m_app_id.assign(consumer->app_id);\r
+\r
+       SetCmdName(m_pid);\r
+}\r
+\r
+void CConsumer::SetCmdName(long pid)\r
+{\r
+       char cmd_name[RMS_NAME_BUF_SIZE] = {0, };\r
+       std::string delimiter = "/";\r
+\r
+       rms_get_cmd_name(m_pid, cmd_name, RMS_NAME_BUF_SIZE);\r
+       m_cmd_name.assign(cmd_name);\r
+       SERVER_WARN("pid %ld cmd name %s", m_pid, cmd_name);\r
+       m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length());\r
+       SERVER_WARN("m_cmd_name %s", m_cmd_name.c_str());\r
+}\r
+\r
+bool CConsumer::AddResource(IN int device_id)\r
+{\r
+       if (IsUsingResource(device_id)) {\r
+               SERVER_INFO("already registered device id(%d) in Consumer(%d)", device_id, m_consumerID);\r
+               return false;\r
+       }\r
+\r
+       m_resources.insert(device_id);\r
+       return true;\r
+}\r
+\r
+int CConsumer::ReleaseResource(IN int device_id)\r
+{\r
+       if (!IsUsingResource(device_id)) {\r
+               SERVER_WARN("CID[%d] / DevID[%d] the consumer does not use this device", m_consumerID, device_id);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       m_resources.erase(device_id);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CConsumer::IsUsingResource(IN int device_id)\r
+{\r
+       auto it = m_resources.find(device_id);\r
+\r
+       return (it != m_resources.end());\r
+}\r
+\r
+void CConsumer::SetAppID(IN const char *app_id)\r
+{\r
+       m_app_id.assign(app_id);\r
+}\r
+\r
+std::string CConsumer::GetAppId(int pid)\r
+{\r
+       char app_id[RMS_NAME_BUF_SIZE] ={0, };\r
+       std::string result;\r
+\r
+       if (aul_app_get_appid_bypid(pid, app_id, sizeof(app_id)) != AUL_R_OK) {\r
+               SERVER_ERR("failed to get appid of %d", pid);\r
+               return result;\r
+       }\r
+\r
+       result.assign(app_id);\r
+\r
+       return result;\r
+}\r
+\r
+rms_error_type_e CConsumer::ComparePriority(CConsumer *requester)\r
+{\r
+       std::string app_id = requester->GetAppID();\r
+\r
+       m_app_id = (m_app_id.empty()) ? GetAppId((int) m_pid) : m_app_id;\r
+\r
+       if (!CheckVisibility(app_id)) {\r
+               SERVER_ERR("The application is not visible. cannot take resource");\r
+               return RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS;\r
+       }\r
+\r
+       rms_priority_s requester_priority = requester->GetPriority();\r
+\r
+       if (!ComparePriority(requester_priority, m_priority)) {\r
+               char cmd[RMS_NAME_BUF_SIZE] = {0,};\r
+               rms_get_cmd_name(m_pid, cmd, sizeof(cmd));\r
+               SERVER_ERR("rqs_priority(%d/%d) - user_priority(%s-%d/%d)", requester_priority.main, requester_priority.sub, cmd, m_priority.main, m_priority.sub);\r
+               return RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS;\r
+       }\r
+\r
+       return RMS_ERR_TYPE_NONE;\r
+}\r
+\r
+bool CConsumer::ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2)\r
+{\r
+       if (priority1.main > priority2.main) {\r
+               return true;\r
+       } else if (priority1.main == priority2.main) {\r
+               return priority1.sub >= priority2.sub;\r
+       } else {\r
+               return false;\r
+       }\r
+}\r
+\r
+bool CConsumer::CheckVisibility(IN std::string app_id_requester)\r
+{\r
+       if (app_id_requester.empty()) {\r
+               SERVER_INFO("requester app id : (null)");\r
+               return true;\r
+       }\r
+\r
+       bool visibility_consumer = (m_app_id.empty()) ? true : GetAppVisibility(m_app_id, false);\r
+       bool visibility_requester = GetAppVisibility(app_id_requester, true);\r
+\r
+       if (visibility_requester) {\r
+               SERVER_INFO("requester is visible(%s)", app_id_requester.c_str());\r
+               return true;\r
+       }\r
+\r
+       if (!visibility_consumer) {\r
+               SERVER_INFO("current consumer(%d) is invisible(%s)", m_consumerID, m_app_id.c_str());\r
+               return true;\r
+       }\r
+\r
+       SERVER_ERR("current consumer(%s)- visibility:(%d)", (m_app_id.empty()) ? "null" : m_app_id.c_str(), visibility_consumer);\r
+       SERVER_ERR("requester(%s)- visibility:(%d)", app_id_requester.c_str(), visibility_requester);\r
+\r
+       return false;\r
+}\r
+\r
+int CConsumer::UpdateAppStatus(std::string app_id)\r
+{\r
+       char buf[RMS_NAME_BUF_SIZE];\r
+       int status;\r
+       int n_max = 4;\r
+       snprintf(buf, RMS_NAME_BUF_SIZE, "Get visibility of application '%s'", app_id.c_str());\r
+\r
+       for (int i = 0; i < n_max; i++) {\r
+               usleep(50*1000);\r
+\r
+               trace_begin(buf);\r
+               status = aul_app_get_status(app_id.c_str());\r
+               trace_end();\r
+               SERVER_INFO("app(%s) / status(%d) / (%d)", app_id.c_str(), status, i);\r
+\r
+               if (IsVisibleStatus(status)) {\r
+                       SERVER_ERR("status %d", status);\r
+                       return status;\r
+               }\r
+       }\r
+       return status;\r
+}\r
+\r
+bool CConsumer::NeedStatusUpdate(std::string app_id)\r
+{\r
+       return false;\r
+}\r
+\r
+bool CConsumer::IsVisibleStatus(int status)\r
+{\r
+       return (status == STATUS_FOCUS || status == STATUS_VISIBLE);\r
+}\r
+\r
+bool CConsumer::GetAppVisibility(std::string app_id, bool requester)\r
+{\r
+       CCache *cache = CCache::getInstance();\r
+       int status = cache->GetAppStatus(app_id);\r
+\r
+       if (status == -1) {\r
+               status = aul_app_get_status(app_id.c_str());\r
+\r
+               if (!IsVisibleStatus(status) && requester && NeedStatusUpdate(app_id))\r
+                       status = UpdateAppStatus(app_id);\r
+\r
+               cache->SetAppStatus(app_id, status);\r
+       }\r
+\r
+       return IsVisibleStatus(status);\r
+}\r
+\r
+bool CConsumer::CheckWebAppState(IN std::string app_id_requesting)\r
+{\r
+       if (app_id_requesting.length() == 0)\r
+               return false;\r
+\r
+       std::string webapp_vconf_key = std::string("rtc/memory/WebApp/") + app_id_requesting;\r
+\r
+       char *status = vconf_get_str(webapp_vconf_key.c_str());\r
+       if (!status) {\r
+               SERVER_INFO("%s is not webapp", app_id_requesting.c_str());\r
+               return false;\r
+       }\r
+\r
+       std::string webapp_status(status);\r
+       if (webapp_status.compare("resume")) {\r
+               SERVER_INFO("%s is not in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str());\r
+               free(status);\r
+               return false;\r
+       }\r
+\r
+       SERVER_INFO("%s is in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str());\r
+       free(status);\r
+\r
+       return true;\r
+}\r
diff --git a/src/manager/CConsumerContainer.cpp b/src/manager/CConsumerContainer.cpp
new file mode 100644 (file)
index 0000000..3e75cb5
--- /dev/null
@@ -0,0 +1,84 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+#include <CConsumer.h>\r
+#include <CConsumerContainer.h>\r
+\r
+CConsumerContainer *CConsumerContainer::m_instance = NULL;\r
+\r
+CConsumerContainer *CConsumerContainer::getInstance(void)\r
+{\r
+       if (!m_instance) {\r
+               m_instance = new(std::nothrow) CConsumerContainer;\r
+               assert(m_instance);\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+CConsumer *CConsumerContainer::findConsumer(int consumer_id)\r
+{\r
+       std::map<int, CConsumer*>::iterator it = m_consumers.find(consumer_id);\r
+\r
+       return (it == m_consumers.end()) ? NULL : (*it).second;\r
+}\r
+\r
+bool CConsumerContainer::AddConsumer(int consumer_id, CConsumer *consumer)\r
+{\r
+       std::map<int, CConsumer*>::iterator it = m_consumers.find(consumer_id);\r
+\r
+       if (it != m_consumers.end())\r
+               return false;\r
+\r
+       m_consumers.insert(std::pair<int, CConsumer*>(consumer_id, consumer));\r
+       return true;\r
+}\r
+\r
+void CConsumerContainer::RemoveConsumer(int consumer_id)\r
+{\r
+       m_consumers.erase(consumer_id);\r
+}\r
+\r
+std::map<int, CConsumer*> CConsumerContainer::findConsumers(int pid)\r
+{\r
+       std::map<int, CConsumer*> result;\r
+\r
+       for (auto const &it : m_consumers) {\r
+               CConsumer *consumer = it.second;\r
+\r
+               if (consumer->GetPid() != pid)\r
+                       continue;\r
+\r
+               result.insert(std::pair<int, CConsumer*>(it.first, it.second));\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+std::map<int, CConsumer*> CConsumerContainer::FindConsumers(std::string app_id)\r
+{\r
+       std::map<int, CConsumer*> result;\r
+       for (auto const &it : m_consumers) {\r
+               CConsumer *consumer = it.second;\r
+               if (app_id.compare(consumer->GetAppID()))\r
+                       continue;\r
+\r
+               result.insert(std::pair<int, CConsumer*>(it.first, it.second));\r
+       }\r
+\r
+       return result;\r
+}\r
diff --git a/src/manager/CDebugUtils.cpp b/src/manager/CDebugUtils.cpp
new file mode 100644 (file)
index 0000000..5e24806
--- /dev/null
@@ -0,0 +1,734 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <unistd.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <glib.h>\r
+#include <stdlib.h>\r
+\r
+#include <vconf.h>\r
+#include <stdio.h>\r
+#include <system_info.h>\r
+#include <sys/types.h>\r
+#include <signal.h>\r
+#include <vconf.h>\r
+#include <tzplatform_config.h>\r
+#include <dlfcn.h>\r
+\r
+#include <CDebugUtils.h>\r
+#include <rms_debug.h>\r
+#include <bundle.h>\r
+#include <bundle_internal.h>\r
+#include <syspopup_caller.h>\r
+\r
+\r
+static bool product_type_init = false;\r
+static int product_type = 0; //SYSTEM_INFO_PRODUCT_TYPE_TV;\r
+\r
+// The process list which is killed by resource manager\r
+static GHashTable *process_htable = NULL;\r
+\r
+#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0)\r
+\r
+const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum)\r
+{\r
+       switch (state_enum) {\r
+               case RMS_INTERNAL_STATE_FREE:\r
+                       return "FREE";\r
+               case RMS_INTERNAL_STATE_SHARABLE:\r
+                       return "SHARABLE";\r
+               case RMS_INTERNAL_STATE_SHARED:\r
+                       return "SHARED";\r
+               case RMS_INTERNAL_STATE_EXCLUSIVE:\r
+                       return "EXCLUSIVE";\r
+               case RMS_INTERNAL_STATE_ERROR:\r
+               default:\r
+                       return "NONE";\r
+       }\r
+}\r
+\r
+const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum)\r
+{\r
+       switch (state_enum) {\r
+               case RMS_STATE_PASSIVE:\r
+                       return "PASSIVE";\r
+               case RMS_STATE_SHARABLE:\r
+                       return "SHARABLE";\r
+               case RMS_STATE_EXCLUSIVE:\r
+                       return "EXCLUSIVE";\r
+               case RMS_STATE_EXCLUSIVE_CONDITIONAL:\r
+                       return "EXCLUSIVE_CONDITIONAL";\r
+               case RMS_STATE_EXCLUSIVE_AUTO:\r
+                       return "EXCLUSIVE_AUTO";\r
+               case RMS_STATE_EXCLUSIVE_PREFERENCE:\r
+                       return "EXCLUSIVE_PREFERENCE";\r
+               default:\r
+                       return "NONE";\r
+       }\r
+}\r
+\r
+const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum)\r
+{\r
+       switch (category_enum) {\r
+               case RMS_CATEGORY_NONE:\r
+                       return "NONE";\r
+               case RMS_CATEGORY_AUDIO_DECODER:\r
+                       return "Audio_Decoder";\r
+               case RMS_CATEGORY_AUDIO_SPDIF_ES_OUTPUT:\r
+                       return "Not Defined Yet";\r
+               case RMS_CATEGORY_VIDEO_DECODER:\r
+                       return "Video_Decoder";\r
+               case RMS_CATEGORY_DEMUX:\r
+                       return "Demux_Main";\r
+               case RMS_CATEGORY_AUDIO_ENCODER:\r
+                       return "Audio_Encoder";\r
+               case RMS_CATEGORY_VIDEO_ENCODER:\r
+                       return "Video_Encoder";\r
+               case RMS_CATEGORY_SCALER:\r
+                       return "Video_Scaler";\r
+               case RMS_CATEGORY_TUNER:\r
+                       return "Tuner";\r
+               case RMS_CATEGORY_AUDIO_MAIN_OUT:\r
+                       return "Audio_Main_Out";\r
+               case RMS_CATEGORY_AUDIO_REMOTE_OUT:\r
+                       return "Audio_Remote_Out";\r
+               case RMS_CATEGORY_AUDIO_SCART_OUT:\r
+                       return "Audio_Scart_Out";\r
+               case RMS_CATEGORY_MM_PCM_OUT:\r
+                       return "MM_PCM_playback";\r
+               case RMS_CATEGORY_AUDIO_DECODER_SUB:\r
+                       return "Audio_Decorder_Sub";\r
+               case RMS_CATEGORY_JPEG_DECODER:\r
+                       return "JPEG_Decoder";\r
+               case RMS_CATEGORY_MJPEG_DECODER:\r
+                       return "MJPEG_Decoder";\r
+               case RMS_CATEGORY_SCALER_SUB:\r
+                       return "Video_Scaler_Sub";\r
+               case RMS_CATEGORY_EXT_VIDEO_SRC:\r
+                       return "Ext_Video_Src";\r
+               case RMS_CATEGORY_EXT_AUDIO_SRC:\r
+                       return "Ext_Audio_Src";\r
+               case RMS_CATEGORY_EXT_HDMI_SRC:\r
+                       return "Ext_HDMI_Src";\r
+               case RMS_CATEGORY_VIDEO_DECODER_SUB:\r
+                       return "Video_Decoder_Sub";\r
+               case RMS_CATEGORY_CAMERA:\r
+                       return "Camera";\r
+               case RMS_CATEGORY_DEMUX_REC:\r
+                       return "Demux_Rec";\r
+               case RMS_CATEGORY_TUNER_SUB:\r
+                       return "Tuner_Sub";\r
+               case RMS_CATEGORY_VIDEO_DECODER_UHD:\r
+                       return "Video_Decoder UHD";\r
+               case RMS_CATEGORY_INPUT_SRC_DTV:\r
+                       return "Input_Src_DTV";\r
+               case RMS_CATEGORY_INPUT_SRC_ATV:\r
+                       return "Input_Src_ATV";\r
+               case RMS_CATEGORY_INPUT_SRC_HDMI:\r
+                       return "Input_Src_HDMI";\r
+               case RMS_CATEGORY_INPUT_SRC_COMP:\r
+                       return "Input_Src_COMP";\r
+               case RMS_CATEGORY_INPUT_SRC_AV:\r
+                       return "Input_Src_AV";\r
+               case RMS_CATEGORY_INPUT_SRC_SCART:\r
+                       return "Input_Src_SCART";\r
+               case RMS_CATEGORY_MIC:\r
+                       return "Mic";\r
+               case RMS_CATEGORY_SW_DECODER:\r
+                       return "SWDecoder";\r
+               case RMS_CATEGORY_MMP_MEMORY_CLUSTER:\r
+                       return "MMPlayer MemoryCluster";\r
+               case RMS_CATEGORY_JPEG_DECODER_8K:\r
+                       return "JPEG_Decoder 8K";\r
+               case RMS_CATEGORY_SCALER_BG:\r
+                       return "Video_Scaler_BG";\r
+               default:\r
+                       return "";\r
+       }\r
+}\r
+\r
+const char *rm_convert_device_enum_to_string(rms_device_e device_enum)\r
+{\r
+       switch (device_enum) {\r
+               case RMS_DEVICE_NONE:\r
+                       return "NONE";\r
+               case RMS_DEVICE_AUDIO_MAIN_OUT:\r
+                       return "audio_main_out";\r
+               case RMS_DEVICE_AUDIO_REMOTE_OUT:\r
+                       return "audio_remote_out";\r
+               case RMS_DEVICE_AUDIO_SCART_OUT:\r
+                       return "audio_scart_out";\r
+               case RMS_DEVICE_MM_PCM_OUT:\r
+                       return "mm_pcm_out";\r
+               case RMS_DEVICE_JPEG_DECODER:\r
+                       return "jpeg_decoder";\r
+               case RMS_DEVICE_DEMUX0:\r
+                       return "demux0";\r
+               case RMS_DEVICE_DEMUX1:\r
+                       return "demux1";\r
+               case RMS_DEVICE_DEMUX2:\r
+                       return "demux2";\r
+               case RMS_DEVICE_DEMUX3:\r
+                       return "demux3";\r
+               case RMS_DEVICE_AUDIO_ENCODER:\r
+                       return "audio_encoder";\r
+               case RMS_DEVICE_VIDEO_ENCODER:\r
+                       return "video_encoder";\r
+               case RMS_DEVICE_SCALER:\r
+                       return "scaler";\r
+               case RMS_DEVICE_EXT_VIDEO_SRC:\r
+                       return "ext_video_src";\r
+               case RMS_DEVICE_EXT_AUDIO_SRC:\r
+                       return "ext_autio_src";\r
+               case RMS_DEVICE_EXT_HDMI_SRC:\r
+                       return "ext_hdmi_src";\r
+               case RMS_DEVICE_CAMERA:\r
+                       return "camera";\r
+               case RMS_DEVICE_TUNER:\r
+                       return "tuner";\r
+               case RMS_DEVICE_TUNER_SUB:\r
+                       return "tuner_sub";\r
+               case RMS_DEVICE_SCALER_SUB:\r
+                       return "scaler_sub";\r
+               case RMS_DEVICE_AUDIO_DECODER:\r
+                       return "audio_decoder";\r
+               case RMS_DEVICE_AUDIO_DECODER_SUB:\r
+                       return "audio_decoder_sub";\r
+               case RMS_DEVICE_VIDEO_DECODER_MAIN:\r
+                       return "video_decoder_main";\r
+               case RMS_DEVICE_VIDEO_DECODER_SUB:\r
+                       return "video_decoder_sub";\r
+               case RMS_DEVICE_VIDEO_DECODER_UDDEC:\r
+                       return "video_decoder_uddec";\r
+               case RMS_DEVICE_VIDEO_DECODER_UDHEVC:\r
+                       return "video_decoder_udhevc";\r
+               case RMS_DEVICE_AUDIO_SPDIF_ES_OUTPUT:\r
+                       return "audio_spdif_es_output";\r
+               case RMS_DEVICE_MIC:\r
+                       return "mic";\r
+               case RMS_DEVICE_EXT_COMP_SRC:\r
+                       return "ext_comp_src";\r
+               case RMS_DEVICE_EXT_AV_SRC:\r
+                       return "av_src";\r
+               case RMS_DEVICE_MJPEG_DECODER:\r
+                       return "mjpeg_decoder";\r
+               case RMS_DEVICE_JPEG_DECODER_UHD:\r
+                       return "jpeg_decoder_uhd";\r
+               case RMS_DEVICE_MJPEG_DECODER_UHD:\r
+                       return "mjpeg_decoder_uhd";\r
+               case RMS_DEVICE_SW_DECODER:\r
+                       return "sw_decoder";\r
+               default:\r
+                       return "";\r
+       }\r
+}\r
+\r
+const char *rm_print_allocation_failure_reason(int ret_value)\r
+{\r
+       switch (ret_value) {\r
+               case RMS_OK:\r
+                       return "OK";\r
+               case RMS_ERROR:\r
+                       return "Cannot Allocate Resources";\r
+               case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER:\r
+                       return "RESOURCE CONFLICT - Other Consumer Is Using";\r
+               case RMS_OK_UHD_RESOURCE_CONFLICT:\r
+                       return "UHD RESOURCE CONFLICT - Other Consumer Is Using";\r
+               default:\r
+                       return "";\r
+       }\r
+}\r
+void rms_create_popup(const char *title, const char *text)\r
+{\r
+       bundle *(*bundle_create_fp) (void);\r
+       int (*bundle_add_fp)(bundle*, const char*, const char*);\r
+       const char *(*bundle_get_val_fp) (bundle*, const char*);\r
+       int (*bundle_free_fp) (bundle*);\r
+       int (*syspopup_launch_fp) (char*, bundle*);\r
+       void *libsyspopup_handle = NULL;\r
+       void *libbundle_handle = NULL;\r
+       bundle *b = NULL;\r
+       char *error;\r
+\r
+       libsyspopup_handle = dlopen(LIBDIR"/libsyspopup_caller.so.0.1.0", RTLD_LAZY);\r
+       if (!libsyspopup_handle) {\r
+               SERVER_ERR("failed to load syspopup library");\r
+               goto end;\r
+       }\r
+\r
+       libbundle_handle = dlopen(LIBDIR"/libbundle.so.0", RTLD_LAZY);\r
+\r
+       if (!libbundle_handle) {\r
+               SERVER_ERR("failed to load bundle library");\r
+               goto end;\r
+       }\r
+\r
+       error = NULL;\r
+\r
+       bundle_create_fp = (bundle *(*)(void)) dlsym(libbundle_handle, "bundle_create");\r
+\r
+       if ((error = dlerror()) != NULL) {\r
+               SERVER_ERR("failed to find bundle_create");\r
+               goto end;\r
+\r
+       }\r
+\r
+       bundle_add_fp = (int (*)(bundle*, const char*, const char*)) dlsym(libbundle_handle, "bundle_add");\r
+\r
+       if ((error = dlerror()) != NULL) {\r
+               SERVER_ERR("failed to find bundle_add");\r
+               goto end;\r
+       }\r
+\r
+       bundle_get_val_fp = (const char *(*)(bundle*, const char*)) dlsym(libbundle_handle, "bundle_get_val");\r
+\r
+       if ((error = dlerror()) != NULL) {\r
+               SERVER_ERR("failed to find bundle_get_val");\r
+               goto end;\r
+       }\r
+\r
+       bundle_free_fp = (int (*)(bundle*)) dlsym(libbundle_handle, "bundle_free");\r
+\r
+       if ((error = dlerror()) != NULL) {\r
+               SERVER_ERR("failed to find bundle_free");\r
+               goto end;\r
+       }\r
+\r
+       syspopup_launch_fp = (int (*)(char*, bundle*)) dlsym(libsyspopup_handle, "syspopup_launch");\r
+\r
+       if ((error = dlerror()) != NULL) {\r
+               SERVER_ERR("failed to find alert-syspopup");\r
+               goto end;\r
+       }\r
+\r
+       b = bundle_create_fp();\r
+       if (!b) {\r
+               SERVER_ERR("failed to create bundle");\r
+               goto end;\r
+       }\r
+\r
+       bundle_add_fp(b, "type", "title_message_1button");\r
+       bundle_add_fp(b, "title", title);\r
+       bundle_add_fp(b, "text", text);\r
+\r
+       bundle_get_val_fp(b, "type");\r
+       bundle_get_val_fp(b, "title");\r
+       bundle_get_val_fp(b, "text");\r
+\r
+       syspopup_launch_fp((char*)"alert-syspopup", b);\r
+       bundle_free_fp(b);\r
+\r
+end:\r
+       if (libsyspopup_handle)\r
+               dlclose(libsyspopup_handle);\r
+\r
+       if (libbundle_handle)\r
+               dlclose(libbundle_handle);\r
+}\r
+\r
+int rms_get_cmd_name(pid_t pid, char *name_out, int size)\r
+{\r
+       char name[RMS_NAME_BUF_SIZE] = {0,};\r
+       FILE *f;\r
+       size_t sz;\r
+\r
+       snprintf(name, sizeof(name), "/proc/%d/cmdline", pid);\r
+       f = fopen(name, "r");\r
+       if (!f) {\r
+               SERVER_ERR("failed to open cmdline(%s) : %d", name, errno);\r
+               return RMS_ERROR;\r
+       } else {\r
+               sz = fread(name, sizeof(char), sizeof(name)-1, f);\r
+               name[sz] = '\0';\r
+               fclose(f);\r
+       }\r
+\r
+       snprintf(name_out, size, "%s", name);\r
+       return RMS_OK;\r
+}\r
+\r
+void rms_print_log_console(char *buf)\r
+{\r
+       int fd, ret;\r
+       char output[RMS_CONSOLE_BUF_SIZE] ={0,};\r
+\r
+       struct timespec tnow;\r
+\r
+       fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);\r
+\r
+       if (fd < 0) {\r
+               SERVER_ERR("console device open fail");\r
+               return;\r
+       }\r
+\r
+       if (is_symlink_file("/dev/console")) {\r
+               SERVER_ERR("%s is symbolic link file", "/dev/console");\r
+               close(fd);\r
+               return;\r
+       }\r
+\r
+       ret = clock_gettime(CLOCK_MONOTONIC, &tnow);\r
+       snprintf(output, RMS_CONSOLE_BUF_SIZE, "[RMS][%ld.%6ld] %s\n", tnow.tv_sec, tnow.tv_nsec/1000, buf);\r
+       ret = write(fd, output, strlen(output));\r
+\r
+       if (ret < 0) {\r
+               SERVER_ERR("Fail to write on console directly");\r
+       }\r
+\r
+       close(fd);\r
+}\r
+\r
+int rm_get_product_type(void)\r
+{\r
+       if (product_type_init)\r
+               return product_type;\r
+\r
+       int type = 0; /* SYSTEM_INFO_PRODUCT_TYPE_TV */\r
+\r
+       if (system_info_get_custom_int("com.samsung/featureconf/product.product_type", &type) != SYSTEM_INFO_ERROR_NONE) {\r
+               SERVER_ERR("Failed to get com.samsung/featureconf/product.product_type");\r
+       }\r
+\r
+       product_type_init = true;\r
+       product_type = type;\r
+\r
+       return product_type;\r
+}\r
+\r
+int rm_is_valid_pid(int pid)\r
+{\r
+       if (kill((pid_t) pid, 0) == 0) {\r
+               SERVER_INFO("pid(%d) is alive", pid);\r
+               return 1;\r
+       }\r
+\r
+       SERVER_ERR("pid(%d)/errno(%d)", pid, errno);\r
+\r
+       return (errno == ESRCH) ? 0 : 1;\r
+}\r
+\r
+static void process_htable_destory_key(gpointer key)\r
+{\r
+       if (key)\r
+               free(key);\r
+}\r
+\r
+static void process_htable_create(void)\r
+{\r
+       if (process_htable) {\r
+               SERVER_ERR("hash table already created");\r
+               return;\r
+       }\r
+\r
+       process_htable = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)process_htable_destory_key, NULL);\r
+\r
+       SERVER_INFO("process hash table created");\r
+}\r
+\r
+static void process_htable_clear(void)\r
+{\r
+       SERVER_INFO("clear process hash table");\r
+\r
+       if (!process_htable)\r
+               return;\r
+\r
+       g_hash_table_remove_all(process_htable);\r
+}\r
+\r
+static void process_htable_insert(const char *name)\r
+{\r
+       const int PROCESS_DATA_LIMIT = 100; // The maxinum size is (RMS_NAME_BUF_SIZE * PROCESS_DATA_LIMIT)\r
+\r
+       if (!process_htable)\r
+               process_htable_create();\r
+\r
+       if (g_hash_table_contains(process_htable, name))\r
+               return;\r
+\r
+       if (g_hash_table_size(process_htable) >= PROCESS_DATA_LIMIT)\r
+               process_htable_clear();\r
+\r
+       char *key_name = (char*) strndup(name, strlen(name));\r
+\r
+       g_hash_table_insert(process_htable, key_name, (gpointer) 1);\r
+\r
+       SERVER_ERR("process info (%s) inserted to hash table (%d)", name, g_hash_table_size(process_htable));\r
+}\r
+\r
+\r
+bool process_htable_contains(const char *name)\r
+{\r
+       bool result = false;\r
+\r
+       if (!process_htable) {\r
+               SERVER_INFO("(%s) - no table", name);\r
+               return false;\r
+       }\r
+\r
+       if (g_hash_table_size(process_htable) == 0) {\r
+               SERVER_INFO("(%s) - empty", name);\r
+               return false;\r
+       }\r
+\r
+       result = g_hash_table_contains(process_htable, name);\r
+\r
+       SERVER_INFO("(%s) - result(%d)", name, result);\r
+\r
+       // resource manager is supposed to clear data once it's checked by application\r
+       process_htable_clear();\r
+\r
+       return result;\r
+}\r
+\r
+int rms_report_emergency(IN int cid, IN int pid, IN int requester)\r
+{\r
+       const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg";\r
+       int retry = 25; // 20ms * 25 times => 500ms\r
+       int ret = 0;\r
+\r
+       SERVER_ERR("consumer is not responding....CID[%d]/PID[%d]/Requester(%d) - set cold power off mode", cid, pid, requester);\r
+\r
+       if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) {\r
+               SERVER_ERR("Failed to set request cold power off");\r
+       } else {\r
+               SERVER_ERR("memory/boot/cold_poweroff_request_pkg set as resource-manager");\r
+       }\r
+\r
+       char process_name[RMS_NAME_BUF_SIZE] = {0,};\r
+\r
+       if (rms_get_cmd_name(pid, process_name, RMS_NAME_BUF_SIZE) == RMS_OK) {\r
+               process_htable_insert(process_name);\r
+       }\r
+\r
+       SERVER_ERR("kill PID(%d)", pid);\r
+\r
+       int signal = SIGKILL;\r
+\r
+       if (RMS_IS_DEBUG_IMAGE) {\r
+               signal = SIGABRT;\r
+               retry = 250; // 20ms * 250 times => 5 sec\r
+       }\r
+\r
+       ret = kill(pid, signal);\r
+\r
+       if (ret!=0) {\r
+               SERVER_ERR("Failed to kill(%d), errno(%d)", pid, errno);\r
+       }\r
+\r
+       // wait until process is really terminated for 500ms\r
+       while (retry > 0 && rm_is_valid_pid(pid)) {\r
+               retry--;\r
+               SERVER_ERR("pid(%d) still alive(%d)", pid, retry);\r
+               usleep(20*1000);\r
+               continue;\r
+       }\r
+\r
+       if (RMS_IS_DEBUG_IMAGE && retry <= 0) {\r
+               //process didn't get terminated for 5 seconds\r
+               SERVER_ERR("pid(%d) is not terminated.", pid);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info)\r
+{\r
+       const char *title = "Resource Allocation Failure";\r
+       const char *style_notification_msg = "<font_size=30 color=#00FF00>";\r
+       const char *style_process_name = "<font_size=25 color=#C90000>";\r
+       const char *indent = "                             ";\r
+       const char *notification_msg = "Please contact the owner(s) of process(es) below<br>";\r
+       const char *reason0 = " Resource allocation failed because there is no callback response from below process(es)<br> ";\r
+       const char *reason1 = " Resource allocation failed because below process(es) did not request deallocation<br> ";\r
+\r
+       char name[RMS_NAME_BUF_SIZE] = {0,};\r
+       GString *gstr;\r
+\r
+       if (!RMS_IS_DEBUG_IMAGE) {\r
+               SERVER_ERR("Not debug mode. Timeout alarm popup is not shown. reason(%d)", (int)reason);\r
+               return;\r
+       }\r
+\r
+       SERVER_ERR("timeout alarm");\r
+\r
+       gstr = g_string_new("");\r
+\r
+       if (!gstr) {\r
+               SERVER_ERR("Failed to create debug popup command");\r
+               return;\r
+       }\r
+\r
+       g_string_append_printf(gstr, "%s", style_notification_msg);\r
+\r
+       switch (reason) {\r
+               case RMS_ALARM_NO_CALLBACK_RESPONSE:\r
+                       g_string_append_printf(gstr, "%s%s", indent, reason0);\r
+                       break;\r
+               case RMS_ALARM_NO_DEALLOCATION:\r
+                       g_string_append_printf(gstr, "%s%s", indent, reason1);\r
+                       break;\r
+               default :\r
+                       break;\r
+       }\r
+\r
+       g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_process_name);\r
+\r
+       rms_get_cmd_name(info.process_id, name, sizeof(name));\r
+       g_string_append_printf(gstr, "%s%s : %d - %s%s", indent, "pid", (int)(info.process_id), name, " <br>");\r
+\r
+       for (int i = 0; i < info.n_conflicted; i++) {\r
+               g_string_append_printf(gstr, "%s [%d] %s%s", indent, i+1, rm_convert_category_enum_to_string(info.conflicted_resources[i].category_id), " <br>");\r
+       }\r
+       rms_create_popup(title, gstr->str);\r
+       SERVER_ERR("Command: %s", gstr->str);\r
+       g_string_free(gstr, true);\r
+}\r
+\r
+static bool rms_read_index(int *data)\r
+{\r
+       FILE *fp = NULL;\r
+       char str[10] = {0,};\r
+       size_t str_size;\r
+       const char *filename = "/proc/device-tree/rm_tbl_idx";\r
+\r
+       if (!data) {\r
+               SERVER_ERR("invalid input : null data");\r
+               return false;\r
+       }\r
+\r
+       fp = fopen(filename, "rb");\r
+\r
+       if (!fp) {\r
+               SERVER_ERR("failed to open (%s) - errno(%d)", filename, errno);\r
+               return false;\r
+       }\r
+\r
+       str_size = fread(str, sizeof(char), sizeof(str)-1, fp);\r
+\r
+       str[str_size] = '\0';\r
+\r
+       if (str_size == 0) {\r
+               fclose(fp);\r
+               return false;\r
+       }\r
+\r
+       *data = atoi(str);\r
+\r
+       fclose(fp);\r
+       fp = NULL;\r
+\r
+       return true;\r
+}\r
+\r
+void rms_display_resource_table_error_popup(void)\r
+{\r
+       const char *title = "FATAL ERROR!!!";\r
+       const char *reason = " Resource Manager can't find a resource table for this board<br> ";\r
+       const char *style_notification_msg = "<font_size=30 color=#FF0000>";\r
+       const char *indent = "  ";\r
+       const char *notification_msg = "<br>";\r
+\r
+       GString *gstr = g_string_new("");\r
+       char *chipset_info;\r
+       int model_index = -1;\r
+\r
+       if (!gstr) {\r
+               SERVER_ERR("Failed to create debug popup command");\r
+               return;\r
+       }\r
+\r
+       g_string_append_printf(gstr, "%s%s", indent, reason);\r
+       g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_notification_msg);\r
+       g_string_append_printf(gstr, "%sProduct type : %d%s", indent, rm_get_product_type(), " <br>");\r
+\r
+       if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) {\r
+               SERVER_ERR("Failed to get chipset from system-info\n");\r
+               goto end;\r
+       }\r
+\r
+       g_string_append_printf(gstr, "%sChipset : %s%s", indent, chipset_info, " <br>");\r
+\r
+       if (!rms_read_index(&model_index)) {\r
+               SERVER_ERR("failed to read model index");\r
+       }\r
+\r
+       g_string_append_printf(gstr, "%sIndex : %d%s", indent, model_index, " <br>");\r
+\r
+       rms_create_popup(title,gstr->str);\r
+\r
+       if (chipset_info) {\r
+               free(chipset_info);\r
+       }\r
+\r
+end:\r
+       g_string_free(gstr, true);\r
+       return;\r
+}\r
+\r
+void rms_print_model_info(void)\r
+{\r
+       static char *chipset_info = NULL;\r
+       static int rm_index = -1;\r
+\r
+       if (!chipset_info) {\r
+               if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE)\r
+                       SERVER_ERR("Failed to get chipset");\r
+       }\r
+\r
+       if (rm_index == -1) {\r
+               if (!rms_read_index(&rm_index))\r
+                       SERVER_ERR("failed to read rm index");\r
+       }\r
+\r
+       SERVER_ERR("> chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index);\r
+\r
+       char buf[512];\r
+       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);\r
+       rms_print_log_console(buf);\r
+}\r
+\r
+int is_symlink_file(const char *path)\r
+{\r
+       struct stat st;\r
+       if (lstat(path, &st) == -1) {\r
+               SERVER_ERR("stat error. file path(%s)", path);\r
+               return 0;\r
+       }\r
+\r
+       return (S_ISLNK(st.st_mode)) ? 1 : 0;\r
+}\r
+\r
+const char *rm_convert_error_type_to_string(rms_error_type_e error_type)\r
+{\r
+       switch (error_type) {\r
+               case RMS_ERR_TYPE_NONE:\r
+                       return "None";\r
+               case RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS:\r
+                       return "Request of invisible process";\r
+               case RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS:\r
+                       return "Request of low priority process";\r
+               case RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE:\r
+                       return "Not available resource";\r
+               case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST:\r
+                       return "Requested resource does not exist";\r
+               case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER:\r
+                       return "Take resource from other consumer";\r
+               default:\r
+                       return "";\r
+       }\r
+}\r
diff --git a/src/manager/CLockController.cpp b/src/manager/CLockController.cpp
new file mode 100644 (file)
index 0000000..b094c2a
--- /dev/null
@@ -0,0 +1,84 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <mutex>\r
+#include <CLockController.h>\r
+\r
+std::mutex m;\r
+CLockController *CLockController::m_instance = nullptr;\r
+\r
+CLockController *CLockController::GetInstance(void)\r
+{\r
+       if (m_instance == nullptr)\r
+       {\r
+               m_instance = new(std::nothrow) CLockController();\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+void CLockController::Lock(ResourceType rsc_type)\r
+{\r
+       std::unique_lock<std::mutex> lock(m);\r
+       unsigned int count = 0;\r
+       auto it = m_locks.find(rsc_type);\r
+\r
+       count = (it == m_locks.end()) ? 1 : ++it->second;\r
+\r
+       m_locks.insert(std::pair<ResourceType, unsigned int>(rsc_type, count));\r
+}\r
+\r
+void CLockController::Unlock(ResourceType rsc_type)\r
+{\r
+       std::unique_lock<std::mutex> lock(m);\r
+\r
+       auto it = m_locks.find(rsc_type);\r
+       if (it == m_locks.end())\r
+               return;\r
+\r
+       if (it->second == 0)\r
+               return;\r
+\r
+       m_locks.at(rsc_type) = --it->second;\r
+\r
+       if (m_locks.at(rsc_type) == 0)\r
+               NotifyUnlock();\r
+}\r
+\r
+unsigned int CLockController::GetLockCount(void)\r
+{\r
+       std::unique_lock<std::mutex> lock(m);\r
+       unsigned int count = 0;\r
+\r
+       for (auto &it : m_locks)\r
+               count += it.second;\r
+\r
+       return count;\r
+}\r
+\r
+void CLockController::NotifyUnlock(void)\r
+{\r
+       CMessage *msg = new CMessage("NotifyUnlock");\r
+       m_msg_q->push(msg);\r
+}\r
+\r
+bool CLockController::IsLocked(CMessage *msg)\r
+{\r
+       if ((m_locks.at(ResourceType::VIDEO_SCALER) > 0) && msg->IsMsgFor(ResourceType::VIDEO_SCALER))\r
+               return true;\r
+\r
+       return false;\r
+}\r
diff --git a/src/manager/CPriority.cpp b/src/manager/CPriority.cpp
new file mode 100644 (file)
index 0000000..f85ee21
--- /dev/null
@@ -0,0 +1,156 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+#include <CConsumer.h>\r
+#include <CResourceDB.h>\r
+#include <CConsumerContainer.h>\r
+#include <CPriority.h>\r
+\r
+int CPriority::compare(int cur_consumer_id, int consumer_id)\r
+{\r
+       CConsumerContainer *c_container = CConsumerContainer::getInstance();\r
+       CConsumer *cur_consumer = c_container->findConsumer(cur_consumer_id);\r
+       if (!cur_consumer)\r
+               return HIGH_PRIORITY;\r
+\r
+       CConsumer *consumer = c_container->findConsumer(consumer_id);\r
+       if (!consumer)\r
+               return LOW_PRIORITY;\r
+\r
+       return (cur_consumer->ComparePriority(consumer) == RMS_ERR_TYPE_NONE) ? HIGH_PRIORITY : LOW_PRIORITY;\r
+}\r
+\r
+int CPriority::compareCurConsumers(int device_id, int consumer_id)\r
+{\r
+       CConsumerContainer *c_container = CConsumerContainer::getInstance();\r
+\r
+       CConsumer *consumer = c_container->findConsumer(consumer_id);\r
+       if (!consumer)\r
+               return LOW_PRIORITY;\r
+\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+       if (!resource)\r
+               return HIGH_PRIORITY;\r
+\r
+       std::set<int> rsc_consumers = resource->GetConsumers();\r
+\r
+       for (auto const &it : rsc_consumers) {\r
+               CConsumer *rsc_consumer = c_container->findConsumer(it);\r
+\r
+               if (!rsc_consumer)\r
+                       continue;\r
+\r
+               if (rsc_consumer->GetId() == consumer_id) {\r
+                       SERVER_WARN("consumer(%d) is already using (%d)", consumer_id, device_id);\r
+                       return SAME_PRIORITY;\r
+               }\r
+\r
+               if (rsc_consumer->ComparePriority(consumer) != RMS_ERR_TYPE_NONE) {\r
+                       SERVER_WARN("LOW PRORITY consumer (%d) device (%d)", consumer_id, device_id);\r
+                       return LOW_PRIORITY;\r
+               }\r
+       }\r
+\r
+       return HIGH_PRIORITY;\r
+}\r
+\r
+int CPriority::getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+       CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id);\r
+\r
+       if (!resource || !requester)\r
+               return RMS_ERROR;\r
+\r
+       if (resource->IsSharableState())\r
+               return RMS_ERROR;\r
+\r
+       std::set<int> consumers = resource->GetConsumers();\r
+\r
+       for (auto const &it : consumers) {\r
+               int cid = it;\r
+\r
+               if (isReclaimableConsumer(cid , consumer_id, err_type)) {\r
+                       reclaimables->insert(std::pair<int, int>(device_id, cid));\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (reclaimables->empty()) {\r
+               SERVER_ERR("high priority consumer is using device(%d)", device_id);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CPriority::isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type)\r
+{\r
+       CConsumerContainer *c_container = CConsumerContainer::getInstance();\r
+       CConsumer *consumer = c_container->findConsumer(consumer_id);\r
+       CConsumer *requester = c_container->findConsumer(requester_id);\r
+\r
+       if (!consumer || !requester)\r
+               return false;\r
+\r
+       if (consumer_id == requester_id)\r
+               return false;\r
+\r
+       rms_error_type_e error_type = consumer->ComparePriority(requester);\r
+\r
+       if (error_type != RMS_ERR_TYPE_NONE) {\r
+               if (err_type)\r
+                       *err_type = error_type;\r
+\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+int CPriority::getReclaimableConsumers(int device_id, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+       CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id);\r
+\r
+       if (!resource || !requester)\r
+               return RMS_ERROR;\r
+\r
+       if (resource->IsFreeState())\r
+               return RMS_ERROR;\r
+\r
+       std::set<int> consumers = resource->GetConsumers();\r
+\r
+       for (auto const &it : consumers) {\r
+               int cid = it;\r
+\r
+               if (!isReclaimableConsumer(cid , consumer_id, err_type))\r
+                       continue;\r
+\r
+               reclaimables->insert(std::pair<int, int>(device_id, cid));\r
+       }\r
+\r
+       if (reclaimables->empty())\r
+       {\r
+               SERVER_ERR("high priority consumer is using device(%d)", device_id);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
diff --git a/src/manager/CResource.cpp b/src/manager/CResource.cpp
new file mode 100644 (file)
index 0000000..11505ed
--- /dev/null
@@ -0,0 +1,506 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <iostream>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <algorithm>\r
+#include <time.h>\r
+\r
+#include <trace.h>\r
+#include <vconf.h>\r
+\r
+#include <CDebugUtils.h>\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <ri-common-type.h>\r
+#include <ri-module-api.h>\r
+\r
+#include <CResourceObserver.h>\r
+#include <CResource.h>\r
+\r
+#define RMS_SUBSCALER_FLAG "memory/rsc_mgr/subscaler_status"\r
+\r
+using namespace std;\r
+void CResource::m_SetSubScalerFlag(int next_state)\r
+{\r
+       if (next_state == RMS_INTERNAL_STATE_ERROR)\r
+               return;\r
+       int value = 0;\r
+       switch (next_state) {\r
+               case RMS_INTERNAL_STATE_FREE:\r
+                       value = 0;\r
+                       break;\r
+               case RMS_INTERNAL_STATE_SHARABLE:\r
+               case RMS_INTERNAL_STATE_SHARED:\r
+               case RMS_INTERNAL_STATE_EXCLUSIVE:\r
+                       value = 1;\r
+                       break;\r
+       }\r
+       if (vconf_set_int(RMS_SUBSCALER_FLAG,value) != 0) {\r
+               SERVER_ERR("Failed to Set vconf key - %s",RMS_SUBSCALER_FLAG);\r
+               return;\r
+       }\r
+       SERVER_INFO("Subscaler flag set to - %d", value);\r
+}\r
+\r
+CResource::CResource(const int device_id, const rms_rsc_category_e category_type, const char *name, const char *path,\r
+                                                std::set<unsigned int> mem_cluster, int is_main_device, const char *audio_codec, int sharable_count)\r
+:m_id(device_id), m_device_name(name), m_device_path(path), m_is_main_device(is_main_device), m_sharable_count(sharable_count)\r
+{\r
+       m_state = RMS_INTERNAL_STATE_FREE;\r
+       m_occupied_bw = 0;\r
+       m_default_bw = 0;\r
+       m_is_reserved = false;\r
+       m_reserved_consumer_id = 0;\r
+       m_mixing_mode = RMS_MIXING_MODE_DEFAULT;\r
+       m_mem_clusters = mem_cluster;\r
+       m_virtual_id = 0;\r
+       m_mv_zone_id = -1;\r
+\r
+       if (audio_codec)\r
+               m_audio_codec.assign(audio_codec);\r
+\r
+       m_category_type = category_type;\r
+       m_cur_category = category_type;\r
+       m_is_scaler = IsScaler(category_type);\r
+}\r
+\r
+CResource::~CResource()\r
+{\r
+}\r
+\r
+bool CResource::IsScaler(rms_rsc_category_e category)\r
+{\r
+       bool result = false;\r
+\r
+       switch (category) {\r
+               case RMS_CATEGORY_SCALER:\r
+               case RMS_CATEGORY_SCALER_BG:\r
+               case RMS_CATEGORY_SCALER_SUB:\r
+               case RMS_CATEGORY_SCALER_SUB2:\r
+               case RMS_CATEGORY_SCALER_SUB3:\r
+                       result = true;\r
+                       break;\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+void CResource::UpdateProperties(std::set<unsigned int> mem_clusters, int bw, int category, int category_class, int vrsc_id)\r
+{\r
+       m_mem_clusters = mem_clusters;\r
+       m_occupied_bw = bw;\r
+       m_cur_category = category;\r
+       m_category_class = category_class;\r
+       m_vrsc_id = vrsc_id;\r
+}\r
+\r
+int CResource::ReserveExclusive(int consumer_id)\r
+{\r
+       if (m_is_reserved && (consumer_id != m_reserved_consumer_id)) {\r
+               SERVER_ERR("rsc(%d) already reserved by(%d)", m_id, m_reserved_consumer_id);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       m_reserved_consumer_id = consumer_id;\r
+       m_is_reserved = true;\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CResource::ReserveShared(int consumer_id)\r
+{\r
+       if (m_is_reserved) {\r
+               SERVER_ERR("rsc(%d) already reserved by (%d) with exclusive mode", m_id, m_reserved_consumer_id);\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       m_reserved_count++;\r
+\r
+       if ( (m_shared_count + m_reserved_count) > m_sharable_count) {\r
+               SERVER_ERR("can't reserve(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count);\r
+               m_reserved_count--;\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_INFO("reserve share(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count);\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CResource::Reserve(int consumer_id, rms_requests_resource_state_e state)\r
+{\r
+       return (state == RMS_STATE_SHARABLE) ? ReserveShared(consumer_id):ReserveExclusive(consumer_id);\r
+}\r
+\r
+void CResource::CancelReservation(rms_requests_resource_state_e state)\r
+{\r
+       if (state == RMS_STATE_SHARABLE)\r
+               m_reserved_count = (--m_reserved_count < 0) ? 0 : m_reserved_count;\r
+       else\r
+               m_is_reserved = false;\r
+}\r
+\r
+void CResource::AddConsumer(IN const int consumer_id, IN rms_requests_resource_state_e state)\r
+{\r
+       if (IsRegisteredConsumer(consumer_id)) {\r
+               IncreaseRefCount(consumer_id);\r
+               m_shared_count++;\r
+               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());\r
+               return;\r
+       }\r
+\r
+       m_consumers.insert(std::pair<int, int>(consumer_id, 1));\r
+       m_consumer_ids.insert(consumer_id);\r
+\r
+       if (state == RMS_STATE_SHARABLE) {\r
+               m_shared_consumers.insert(consumer_id);\r
+               m_shared_count++;\r
+               SERVER_INFO("[rsc(%d)] consumer(%d) shares resource, shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size());\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+void CResource::ResetConsumer(std::set<int> new_consumers)\r
+{\r
+       m_consumers.clear();\r
+       m_consumer_ids.clear();\r
+       m_shared_consumers.clear();\r
+       m_shared_count = 0;\r
+\r
+       for (auto &it : new_consumers) {\r
+               AddConsumer(it, RMS_STATE_EXCLUSIVE);\r
+       }\r
+}\r
+\r
+bool CResource::IsRegisteredConsumer(int consumer_id)\r
+{\r
+       std::map<int, int>::iterator it = m_consumers.find(consumer_id);\r
+\r
+       return (it != m_consumers.end());\r
+}\r
+\r
+int CResource::IncreaseRefCount(int consumer_id)\r
+{\r
+       int ref_count = 0;\r
+       std::map<int, int>::iterator it = m_consumers.find(consumer_id);\r
+\r
+       if (it == m_consumers.end())\r
+               return 0;\r
+\r
+       ref_count = it->second;\r
+       m_consumers[consumer_id] = ++ref_count;\r
+\r
+       return ref_count;\r
+}\r
+\r
+int CResource::DecreaseRefCount(int consumer_id)\r
+{\r
+       int ref_count = 0;\r
+       std::map<int, int>::iterator it = m_consumers.find(consumer_id);\r
+\r
+       if (it == m_consumers.end())\r
+               return 0;\r
+\r
+       ref_count = it->second;\r
+       --ref_count;\r
+       ref_count = (ref_count < 0) ? 0 : ref_count;\r
+       m_consumers[consumer_id] = ref_count;\r
+\r
+       return ref_count;\r
+}\r
+\r
+int CResource::RemoveConsumer(IN int consumer_id, IN bool force)\r
+{\r
+       if (!IsRegisteredConsumer(consumer_id)) {\r
+               SERVER_ERR("[rsc(%d)] consumer(%d) is not found in list", m_id, consumer_id);\r
+               return 0;\r
+       }\r
+\r
+       int ref_count = DecreaseRefCount(consumer_id);\r
+\r
+       if (m_state == RMS_INTERNAL_STATE_SHARABLE || m_state == RMS_INTERNAL_STATE_SHARED) {\r
+               m_shared_count = (--m_shared_count < 0) ? 0 : m_shared_count;\r
+\r
+               if (force)\r
+                       m_shared_count = ((m_shared_count -= ref_count) < 0) ? 0 : m_shared_count;\r
+       }\r
+\r
+       if (ref_count > 0 && !force) {\r
+               SERVER_INFO("consumer(%d) is still sharing resource(%d), ref(%d)", consumer_id, m_id, ref_count);\r
+               return ref_count;\r
+       }\r
+\r
+       m_consumer_ids.erase(consumer_id);\r
+       m_consumers.erase(consumer_id);\r
+       ChangeStateByRelease(consumer_id);\r
+\r
+       return 0;\r
+}\r
+\r
+void CResource::ChangeState(rms_resource_internal_state_e next_state)\r
+{\r
+       if (m_state == next_state)\r
+               return;\r
+\r
+       SERVER_INFO("state changed (%s : %s) - (%s -> %s)",\r
+               rm_convert_category_enum_to_string(m_category_type),\r
+               m_device_name,\r
+               rm_convert_state_enum_to_string(m_state),\r
+               rm_convert_state_enum_to_string(next_state));\r
+\r
+       m_state = next_state;\r
+\r
+       if (m_category_type == RMS_CATEGORY_SCALER_SUB)\r
+               m_SetSubScalerFlag(next_state);\r
+}\r
+\r
+bool CResource::ChangeStateByAllocation(IN rms_requests_resource_state_e requested_state, const int consumer_id, int mv_zone_id)\r
+{\r
+       if (requested_state == RMS_STATE_EXCLUSIVE_CONDITIONAL || requested_state == RMS_STATE_EXCLUSIVE_AUTO || requested_state == RMS_STATE_EXCLUSIVE_PREFERENCE)\r
+               requested_state = RMS_STATE_EXCLUSIVE;\r
+\r
+       rms_resource_internal_state_e allocation_resource_state_matrix[4][3] =\r
+                                                               {{RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_EXCLUSIVE},\r
+                                                               {RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR},\r
+                                                               {RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR},\r
+                                                               {RMS_INTERNAL_STATE_EXCLUSIVE, RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_ERROR}};\r
+\r
+       bool need_notify_by_alloc_matrix[4][3] = {{false, true, true},\r
+                                                                       {false, true, false},\r
+                                                                       {false, true, false},\r
+                                                                       {false, false, true}};\r
+\r
+       rms_resource_internal_state_e next_state = allocation_resource_state_matrix[m_state][requested_state];\r
+       SERVER_INFO("m_state %d requested_state %d next_state %d", m_state, requested_state, next_state);\r
+\r
+       bool need_notify = need_notify_by_alloc_matrix[m_state][requested_state];\r
+\r
+       m_is_reserved = false;\r
+       m_reserved_consumer_id = 0;\r
+\r
+       if (next_state == RMS_INTERNAL_STATE_ERROR) {\r
+               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));\r
+               return false;\r
+       }\r
+\r
+       m_state = next_state;\r
+\r
+       if (m_category_type == RMS_CATEGORY_SCALER_SUB)\r
+               m_SetSubScalerFlag(next_state);\r
+\r
+       if (mv_zone_id > 0) {\r
+               m_mv_zone_id = mv_zone_id;\r
+               SERVER_INFO("(%d) > zone_id(%d)", m_id, m_mv_zone_id);\r
+       }\r
+\r
+       if (need_notify)\r
+               NotifyObservers(UPDATED_BY_ALLOC, consumer_id);\r
+\r
+       return true;\r
+}\r
+\r
+bool CResource::ChangeStateByRelease(int consumer_id)\r
+{\r
+       rms_resource_internal_state_e current_state = m_state;\r
+       rms_resource_internal_state_e next_state = RMS_INTERNAL_STATE_ERROR;\r
+\r
+       bool need_notify = false;\r
+\r
+       SERVER_INFO("current_state %d m_shared_count %d", current_state, m_shared_count);\r
+\r
+       switch (current_state) {\r
+               case RMS_INTERNAL_STATE_SHARED:\r
+                       m_shared_consumers.erase(consumer_id);\r
+                       need_notify = true;\r
+\r
+                       if (m_shared_count > 1) {\r
+                               next_state = RMS_INTERNAL_STATE_SHARED;\r
+                       } else if (m_shared_count == 1) {\r
+                               next_state = RMS_INTERNAL_STATE_SHARABLE;\r
+                       } else {\r
+                               next_state = RMS_INTERNAL_STATE_FREE;\r
+                       }\r
+                       break;\r
+               case RMS_INTERNAL_STATE_EXCLUSIVE:\r
+               case RMS_INTERNAL_STATE_SHARABLE:\r
+                       next_state = RMS_INTERNAL_STATE_FREE;\r
+                       need_notify = true;\r
+                       break;\r
+               case RMS_INTERNAL_STATE_FREE:\r
+               default:\r
+                       SERVER_ERR("unexpected resource state (%d)", current_state);\r
+                       next_state = RMS_INTERNAL_STATE_FREE;\r
+                       break;\r
+       }\r
+\r
+       m_state = next_state;\r
+       SERVER_INFO("m_state %d need notify %d", m_state, need_notify);\r
+\r
+       if (m_category_type == RMS_CATEGORY_SCALER_SUB)\r
+               m_SetSubScalerFlag(next_state);\r
+\r
+       if (need_notify) {\r
+               m_mv_zone_id = -1;\r
+               NotifyObservers(UPDATED_BY_RELEASE, consumer_id);\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CResource::IsAllocatableState(IN rms_requests_resource_state_e requested_state)\r
+{\r
+       bool can_allocation_matrix[4][6] =\r
+                                               /*requested_state*/ /* PASSIVE */ /*SHARABLE*/ /*EXCLUSIVE*/ /* EXCLUSIVE CON */ /* EXCLUSIVE AUTO */ /* EXCLUSIVE PREFERENCE */\r
+                       /* m_state */ /* FREE */{ {false, true, true, true, true, true },\r
+                                               /* SHARABLE */ { true, true, false, false, false, false },\r
+                                               /* SHARED */ { true, true, false, false, false, false },\r
+                                               /* EXCLUSIVE */ { true, false, false, false, false, false } };\r
+\r
+       SERVER_INFO("Status - DevID[%d:%s] / CatID[%d] / CurState[%s] / ReqState[%s]",\r
+               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));\r
+\r
+       /* check requested_state is valid */\r
+       if ((requested_state < RMS_STATE_PASSIVE) || (requested_state > RMS_STATE_EXCLUSIVE_PREFERENCE)) {\r
+               SERVER_ERR("rquested state is invalid");\r
+               return false;\r
+       }\r
+\r
+       return can_allocation_matrix[m_state][requested_state];\r
+}\r
+\r
+void CResource::SetDefaultBW(unsigned int bw)\r
+{\r
+       m_default_bw = bw;\r
+       m_occupied_bw = bw;\r
+}\r
+void CResource::SetAllocatedTime(void)\r
+{\r
+       struct timespec t;\r
+       clock_gettime(CLOCK_MONOTONIC, &t);\r
+       unsigned long sec = t.tv_sec * 1000;\r
+       unsigned long nsec = t.tv_nsec / 1000000;\r
+       m_allocated_time = sec + nsec;\r
+}\r
+\r
+void CResource::RegisterObserver(CResourceObserver *observer)\r
+{\r
+       if (!observer) {\r
+               SERVER_ERR("observer NULL");\r
+               return;\r
+       }\r
+\r
+       m_observers.push_back(observer);\r
+}\r
+\r
+void CResource::UnregisterObserver(CResourceObserver *observer)\r
+{\r
+       auto it = std::find(m_observers.begin(), m_observers.end(), observer);\r
+\r
+       if (it == m_observers.end()) {\r
+               SERVER_ERR("not registered observer");\r
+               return;\r
+       }\r
+\r
+       m_observers.erase(it);\r
+\r
+       SERVER_INFO("observer removed");\r
+}\r
+\r
+void CResource::NotifyObservers(resource_update_type_e type, const int consumer_id)\r
+{\r
+       for (CResourceObserver *observer : m_observers) {\r
+               observer->Update(type, m_id, consumer_id);\r
+       }\r
+}\r
+\r
+bool CResource::Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id)\r
+{\r
+       if (!ChangeStateByAllocation(state, consumer_id, mv_zone_id))\r
+               return false;\r
+\r
+       AddConsumer(consumer_id, state);\r
+       return true;\r
+}\r
+\r
+void CResource::SetZoneId(int zone_id)\r
+{\r
+       SERVER_INFO("(%d) > zone_id(%d)", m_id, zone_id);\r
+       m_mv_zone_id = zone_id;\r
+}\r
+\r
+void CResource::UpdateAudioCodec(std::string codec_name)\r
+{\r
+       m_audio_codec = codec_name;\r
+}\r
+\r
+bool CResource::IsAudioDevice(void)\r
+{\r
+       if (m_category_type == RMS_CATEGORY_AUDIO_DECODER)\r
+               return true;\r
+       if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_SUB)\r
+               return true;\r
+       if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_PRIMARY)\r
+               return true;\r
+       if ((m_category_type > RMS_CATEGORY_AUDIO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX))\r
+               return true;\r
+\r
+       return false;\r
+}\r
+\r
+bool CResource::IsVideoDecoder(void)\r
+{\r
+       if (m_category_type == RMS_CATEGORY_VIDEO_DECODER)\r
+               return true;\r
+       if (m_category_type == RMS_CATEGORY_VIDEO_DECODER_SUB)\r
+               return true;\r
+       if ((m_category_type > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX))\r
+               return true;\r
+       if (m_category_type == RMS_CATEGORY_MJPEG_DECODER)\r
+               return true;\r
+       if ((m_category_type > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX))\r
+               return true;\r
+\r
+       return false;\r
+}\r
+\r
+int CResource::GetFirstConsumer(void)\r
+{\r
+       if (m_consumer_ids.empty())\r
+               return -1;\r
+\r
+       auto it = m_consumer_ids.begin();\r
+       return *it;\r
+}\r
+\r
+int CResource::GetVirtualDeviceId(void)\r
+{\r
+       return (m_virtual_id < RI_VIRTUAL_ID_SCALER) ? m_id : m_virtual_id;\r
+}\r
+\r
+bool CResource::IsJpegDecoder(void)\r
+{\r
+       if (m_category_type == RMS_CATEGORY_JPEG_DECODER)\r
+               return true;\r
+       if ((m_category_type > RMS_CATEGORY_JPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX))\r
+               return true;\r
+\r
+       return false;\r
+}\r
diff --git a/src/manager/CResourceCategory.cpp b/src/manager/CResourceCategory.cpp
new file mode 100644 (file)
index 0000000..0633a61
--- /dev/null
@@ -0,0 +1,155 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <iostream>\r
+\r
+#include <CResourceCategory.h>\r
+#include <CBandwidth.h>\r
+#include <CRequest.h>\r
+#include <CVirtualResource.h>\r
+#include <CDebugUtils.h>\r
+#include <CDependencyController.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CAllocateStrategyProvider.h>\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+\r
+CResourceCategory::CResourceCategory(IN rms_rsc_category_e resource_category_id, IN int category_class)\r
+:m_categoryID(resource_category_id)\r
+{\r
+       m_alloc_strategy = CAllocateStrategyProvider::getInstance()->GetStrategy(resource_category_id, category_class);\r
+       assert(m_alloc_strategy);\r
+}\r
+\r
+void CResourceCategory::AddVirtualResource(IN int device_id, IN CVirtualResource *vresource)\r
+{\r
+       std::map<int, CVirtualResource *>::iterator it = m_device_id_to_vresource_map.find(device_id);\r
+\r
+       if (it != m_device_id_to_vresource_map.end())\r
+               return;\r
+\r
+       m_device_id_to_vresource_map.insert(std::pair<int, CVirtualResource *>(device_id, vresource));\r
+}\r
+\r
+CResource *CResourceCategory::ReserveCandidate(CRequest *req, bool apply_promotion)\r
+{\r
+       CVirtualResource *vrsc = m_alloc_strategy->findCandidate(m_device_id_to_vresource_map, req);\r
+\r
+       if (!vrsc)\r
+               return NULL;\r
+\r
+       if (m_alloc_strategy->reserveResource(vrsc, req) != RMS_OK) {\r
+               SERVER_INFO("can't find candidate (%d)", m_categoryID);\r
+               return NULL;\r
+       }\r
+\r
+       SERVER_INFO("candidate found (%d:%d)", m_categoryID, vrsc->GetResource()->GetDeviceID());\r
+\r
+       req->SetResult(RMS_OK);\r
+       req->SetReason(RMS_ERR_TYPE_NONE);\r
+\r
+       return vrsc->GetResource();\r
+}\r
+\r
+bool CResourceCategory::hasFreeStateResource(void)\r
+{\r
+       for (auto& it : m_device_id_to_vresource_map) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (resource->IsFreeState())\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CResourceCategory::MakeResourceMapSortedByAllocTime(std::multimap<unsigned long, CVirtualResource *> *resource_map)\r
+{\r
+       for (auto& it : m_device_id_to_vresource_map) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *rsc = vresource->GetResource();\r
+\r
+               resource_map->insert(std::pair<unsigned long, CVirtualResource *>(rsc->GetAllocatedTime(), vresource));\r
+       }\r
+}\r
+\r
+void CResourceCategory::GetRetirableConsumers(CRequest *req,\r
+                                                                                                       std::multimap<int, int>* return_ids_in_category,\r
+                                                                                                       rms_error_type_e *err_type)\r
+{\r
+       assert(return_ids_in_category);\r
+\r
+       std::multimap<unsigned long, CVirtualResource *> sorted_resource_map;\r
+       MakeResourceMapSortedByAllocTime(&sorted_resource_map);\r
+       m_alloc_strategy->GetRetirableConsumers(sorted_resource_map, req, return_ids_in_category, err_type);\r
+}\r
+\r
+bool CResourceCategory::IsAvailableToUse(rms_requests_resource_state_e request_state)\r
+{\r
+       CResource *resource;\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       for (auto& it : m_device_id_to_vresource_map) {\r
+               CVirtualResource *vresource = it.second;\r
+               resource = vresource->GetResource();\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+                       SERVER_ERR("Not available: Mem Cluster is occupied.");\r
+                       continue;\r
+               }\r
+\r
+               if (vresource->GetBW() > bandwidth->GetAvail()) {\r
+                       SERVER_ERR("Not available: BW is insufficient!!");\r
+                       continue;\r
+               }\r
+\r
+               if ((request_state == RMS_STATE_SHARABLE) && (!resource->IsSharableDevice())) {\r
+                       SERVER_ERR("Not available: resource(%d) cannot be shared", resource->GetDeviceID());\r
+                       continue;\r
+               }\r
+\r
+               if (resource->IsAllocatableState(request_state))\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CResourceCategory::GetResources(std::map<int, CResource*> *resource_map)\r
+{\r
+       int i = 0;\r
+       for (auto& it : m_device_id_to_vresource_map) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               resource_map->insert(std::pair<int, CResource*>(i++, resource));\r
+       }\r
+}\r
+\r
+CResource *CResourceCategory::FindMainResource(void)\r
+{\r
+       for (auto& it : m_device_id_to_vresource_map) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (resource->IsMainDevice())\r
+                       return resource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
diff --git a/src/manager/CResourceDB.cpp b/src/manager/CResourceDB.cpp
new file mode 100644 (file)
index 0000000..12751ec
--- /dev/null
@@ -0,0 +1,779 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <iostream>\r
+#include <assert.h>\r
+#include <stdlib.h>\r
+#include <glib.h>\r
+#include <gio/gio.h>\r
+\r
+#include <ri-module-api.h>\r
+#include <vconf.h>\r
+\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+\r
+#include <CDebugUtils.h>\r
+#include <CAudioCodecCollection.h>\r
+#include <CBandwidth.h>\r
+#include <CVirtualResource.h>\r
+#include <CConsumer.h>\r
+#include <CConsumerContainer.h>\r
+#include <CDependencyController.h>\r
+#include <CResourceDB.h>\r
+#include <CVideoController.h>\r
+#include <CResourceState.h>\r
+\r
+CResourceDB *CResourceDB::m_instance = NULL;\r
+\r
+CResourceDB *CResourceDB::getInstance(void)\r
+{\r
+       if (!m_instance) {\r
+               m_instance = new(std::nothrow) CResourceDB;\r
+               assert(m_instance);\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+CResourceCategory *CResourceDB::FindResourceCategory(IN rms_rsc_category_e category_id)\r
+{\r
+       std::map<rms_rsc_category_e, CResourceCategory*>::iterator it = m_resourceCategoryMap.find(category_id);\r
+\r
+       if (it == m_resourceCategoryMap.end())\r
+               return NULL;\r
+\r
+       return (*it).second;\r
+}\r
+\r
+CResource *CResourceDB::FindResource(IN const int device_id)\r
+{\r
+       std::map<int, CResource*>::iterator it = m_deviceid_to_rsc.find(device_id);\r
+\r
+       if (it == m_deviceid_to_rsc.end()) {\r
+               SERVER_ERR("no device id(%d) in DB", device_id);\r
+               return NULL;\r
+       }\r
+\r
+       return (*it).second;\r
+}\r
+\r
+CVirtualResource *CResourceDB::FindVirtualResource(const int vid)\r
+{\r
+       auto it = m_v_deviceid_to_rsc.find(vid);\r
+\r
+       return (it == m_v_deviceid_to_rsc.end()) ? nullptr : it->second;\r
+}\r
+\r
+void CResourceDB::AddVirtualDeviceID(IN CVirtualResource *vresource)\r
+{\r
+       int vrsc_id = vresource->GetVResourceID();\r
+\r
+       std::map<int, CVirtualResource *>::iterator it = m_v_deviceid_to_rsc.find(vrsc_id);\r
+\r
+       if (it != m_v_deviceid_to_rsc.end())\r
+               return;\r
+\r
+       m_v_deviceid_to_rsc.insert(std::pair<int, CVirtualResource *>(vrsc_id, vresource));\r
+}\r
+\r
+void CResourceDB::AddDeviceID(IN int device_id, IN CResource *resource)\r
+{\r
+       std::map<int, CResource*>::iterator it = m_deviceid_to_rsc.find(device_id);\r
+       \r
+       if (it != m_deviceid_to_rsc.end())\r
+               return;\r
+\r
+       m_deviceid_to_rsc.insert(std::pair<int, CResource*>(device_id, resource));\r
+}\r
+\r
+void CResourceDB::AddDeviceName(IN const char *device_name, IN CResource *resource)\r
+{\r
+       auto it = m_devicename_to_rsc.find(std::string(device_name));\r
+       \r
+       if (it != m_devicename_to_rsc.end()) {\r
+               SERVER_DBG("already registered device name(%s) in DB", device_name);\r
+               return;\r
+       }\r
+\r
+       m_devicename_to_rsc.insert(std::pair<std::string, CResource*>(std::string(device_name), resource));\r
+}\r
+\r
+void CResourceDB::AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category)\r
+{\r
+       std::map<rms_rsc_category_e, CResourceCategory*>::iterator it = m_resourceCategoryMap.find(category_id);\r
+\r
+       if (it != m_resourceCategoryMap.end())\r
+               return;\r
+\r
+       m_resourceCategoryMap.insert(std::pair<rms_rsc_category_e, CResourceCategory*>(category_id, resource_category));\r
+}\r
+\r
+CResource *CResourceDB::FindResource(const char *device_name)\r
+{\r
+       auto it = m_devicename_to_rsc.find(std::string(device_name));\r
+\r
+       return (it == m_devicename_to_rsc.end()) ? NULL : it->second;\r
+}\r
+\r
+void CResourceDB::AddVirtualResource(IN CVirtualResource *vrsc,\r
+                                                      IN rms_rsc_category_e resource_category_id,\r
+                                                      IN const char *name,\r
+                                                      IN const char *path,\r
+                                                      IN std::set<unsigned int> mem_cluster_info,\r
+                                                      IN unsigned int device_id_unique,\r
+                                                      IN int is_main_device,\r
+                                                      IN const char *audio_codec,\r
+                                                      IN int sharable_count,\r
+                                                      IN int mixing_count,\r
+                                                      IN CResourceObserver *observer)\r
+{\r
+       assert(name);\r
+       assert(path);\r
+\r
+       CResource *rsc = FindResource(name);\r
+\r
+       if (!rsc) {\r
+               rsc = new CResource(device_id_unique, resource_category_id, name, path, mem_cluster_info, is_main_device, audio_codec, sharable_count);\r
+\r
+               AddDeviceName(name, rsc);\r
+               AddDeviceID(device_id_unique, rsc);\r
+\r
+               rsc->RegisterObserver(this);\r
+               rsc->RegisterObserver(observer);\r
+       }\r
+\r
+       vrsc->SetResource(rsc);\r
+\r
+       CAudioCodecCollection::getInstance()->registerAudioCodec(audio_codec, mixing_count);\r
+\r
+       if (rsc->GetDefaultBW() == 0)\r
+               rsc->SetDefaultBW(vrsc->GetBW());\r
+\r
+       AddVirtualDeviceID(vrsc);\r
+}\r
+\r
+void CResourceDB::UpdateBWbyRelease(CResource *rsc)\r
+{\r
+       if (!rsc)\r
+               return;\r
+\r
+       if (rsc->GetBW() == 0)\r
+               return;\r
+\r
+       CBandwidth *bw = CBandwidth::GetInstance();\r
+       bw->RemoveConsumer(rsc->GetDeviceID(), rsc->GetCurCategory(), rsc->GetCategoryClass());\r
+       bw->Increase(rsc->GetBW(), rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID());\r
+\r
+       return;\r
+}\r
+\r
+void CResourceDB::UpdateByRelease(CResource *resource, const int device_id, const int consumer_id)\r
+{\r
+       UpdateBWbyRelease(resource);\r
+\r
+       if (resource->IsVideoDecoder())\r
+               RemoveActiveVideoDecoder(device_id, resource->GetCategoryClass());\r
+\r
+       if (resource->IsJpegDecoder())\r
+               RemoveActiveJpegDecoder(device_id);\r
+\r
+       RemoveResourceHasZoneId(resource->GetDeviceID());\r
+}\r
+\r
+void CResourceDB::UpdateBWbyAllocation(const unsigned int bandwidth, CResource *rsc)\r
+{\r
+       CBandwidth *bw = CBandwidth::GetInstance();\r
+       bw->Decrease(bandwidth, rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID());\r
+\r
+       //SERVER_INFO("bw updated avail(%d)/max(%d)", bw->GetAvail(), bw->GetMax());\r
+}\r
+\r
+void CResourceDB::UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id)\r
+{\r
+       unsigned int bw = resource->GetBW();\r
+\r
+       if (bw > 0) {\r
+               UpdateBWbyAllocation(bw, resource);\r
+               CBandwidth::GetInstance()->AddConsumer(device_id, consumer_id, resource->GetCurCategory(), resource->GetCategoryClass());\r
+       }\r
+\r
+       if (resource->IsVideoDecoder())\r
+               AddActiveVideoDecoder(device_id, consumer_id, resource->GetCategoryClass());\r
+\r
+       if (resource->IsScaler())\r
+               SetVirtualScalerId(resource);\r
+\r
+       if (resource->IsJpegDecoder())\r
+               AddActiveJpegDecoder(device_id, consumer_id);\r
+\r
+       if (resource->GetZoneId() > 0)\r
+               InsertResourceHasZoneId(resource);\r
+}\r
+\r
+void CResourceDB::SetVirtualScalerId(CResource *resource)\r
+{\r
+       int scaler_id = GetVirtualScalerId(resource);\r
+\r
+       SERVER_INFO("map scaler (%d:%d)", scaler_id, resource->GetDeviceID());\r
+\r
+       resource->SetVirtualDeviceId(scaler_id);\r
+       InsertVirtualScaler(scaler_id, resource);\r
+}\r
+\r
+void CResourceDB::PrintVirtualScalerMap(void)\r
+{\r
+       for (auto &it : m_scaler_map) {\r
+               if (it.second == nullptr) {\r
+                       //SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null");\r
+                       continue;\r
+               }\r
+               //SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId());\r
+       }\r
+}\r
+\r
+int CResourceDB::GetVirtualScalerId(CResource *resource)\r
+{\r
+       CResource *rsc = nullptr;\r
+\r
+       for (auto &it : m_scaler_map) {\r
+               rsc = it.second;\r
+               if (rsc == nullptr)\r
+                       continue;\r
+               if (rsc->GetDeviceID() == resource->GetDeviceID())\r
+                       return it.first;\r
+       }\r
+\r
+       return resource->GetDedicatedVirtualDeviceId();\r
+}\r
+\r
+void CResourceDB::AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class)\r
+{\r
+       m_active_vdecs.insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+       if (category_class == RMS_CATEGORY_CLASS_N_DECODING)\r
+               m_active_nvdecs.insert(std::pair<int, int>(device_id, consumer_id));\r
+}\r
+\r
+void CResourceDB::RemoveActiveVideoDecoder(const int device_id, const int category_class)\r
+{\r
+       m_active_vdecs.erase(device_id);\r
+\r
+       if (category_class == RMS_CATEGORY_CLASS_N_DECODING)\r
+               m_active_nvdecs.erase(device_id);\r
+}\r
+\r
+void CResourceDB::AddActiveJpegDecoder(const int device_id, const int consumer_id)\r
+{\r
+       m_active_jdecs.insert(std::pair<int, int>(device_id, consumer_id));\r
+}\r
+\r
+void CResourceDB::RemoveActiveJpegDecoder(const int device_id)\r
+{\r
+       m_active_jdecs.erase(device_id);\r
+}\r
+\r
+int CResourceDB::GetActiveDecoderNum(void)\r
+{\r
+       int num = 0;\r
+\r
+       num += m_active_vdecs.size();\r
+       num += m_active_jdecs.size();\r
+\r
+       return num;\r
+}\r
+\r
+void CResourceDB::PrintVideoDecoderConsumers(void)\r
+{\r
+       for (auto const &it : m_active_vdecs) {\r
+               SERVER_INFO("dev(%d) by (%d)", it.first, it.second);\r
+       }\r
+}\r
+\r
+bool CResourceDB::HasAvailableDecoder(void)\r
+{\r
+       int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1;\r
+       int active_vdecs = m_active_vdecs.size();\r
+       int active_ndecs = m_active_nvdecs.size();\r
+\r
+       SERVER_INFO("active(%d) / n_dec(%d) / max(%d / %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs);\r
+\r
+       if (active_ndecs > 0)\r
+               active_vdecs = active_vdecs + (1 - active_ndecs);\r
+\r
+       if (active_vdecs >= max_vdecs)\r
+               PrintVideoDecoderConsumers();\r
+\r
+       return (active_vdecs < max_vdecs);\r
+}\r
+\r
+bool CResourceDB::HasAvailableDecoderNDecoding(void)\r
+{\r
+       int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1;\r
+       int active_vdecs = m_active_vdecs.size();\r
+       int active_ndecs = m_active_nvdecs.size();\r
+\r
+       SERVER_INFO("active(%d) / n_dec(%d) / max(%d %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs);\r
+\r
+       if (active_ndecs > 0) {\r
+               active_vdecs = active_vdecs + (1 - active_ndecs);\r
+               return true;\r
+       }\r
+\r
+       if (active_vdecs >= max_vdecs)\r
+               PrintVideoDecoderConsumers();\r
+\r
+       return (active_vdecs < max_vdecs);\r
+}\r
+\r
+bool CResourceDB::HasAvailableDecoder(std::multimap<int, int> retirables)\r
+{\r
+       int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1;\r
+       std::map<int, int> retirables_vdecs;\r
+\r
+       SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs);\r
+\r
+       for (auto &it : retirables) {\r
+               CResource *rsc = FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+\r
+               if (rsc->IsVideoDecoder())\r
+                       retirables_vdecs.insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+\r
+       int active_vdecs = m_active_vdecs.size();\r
+       int active_ndecs = m_active_nvdecs.size();\r
+       int retirable_vdecs = retirables_vdecs.size();\r
+       int retirable_ndecs = CountNDecoders(retirables_vdecs);\r
+\r
+       int remain = 0;\r
+\r
+       if ((active_ndecs - retirable_ndecs) > 0)\r
+               remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs));\r
+       else\r
+               remain = active_vdecs - retirable_vdecs;\r
+\r
+       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);\r
+\r
+       if (remain >= max_vdecs)\r
+               PrintVideoDecoderConsumers();\r
+\r
+       return (remain < max_vdecs);\r
+}\r
+\r
+bool CResourceDB::HasAvailableDecoderNDecoding(std::multimap<int, int> retirables)\r
+{\r
+       int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1;\r
+       std::map<int, int> retirables_vdecs;\r
+\r
+       SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs);\r
+\r
+       for (auto &it : retirables) {\r
+               CResource *rsc = FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+\r
+               if (rsc->IsVideoDecoder())\r
+                       retirables_vdecs.insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+\r
+       int active_vdecs = m_active_vdecs.size();\r
+       int active_ndecs = m_active_nvdecs.size();\r
+       int retirable_vdecs = retirables_vdecs.size();\r
+       int retirable_ndecs = CountNDecoders(retirables_vdecs);\r
+\r
+       int remain = 0;\r
+\r
+       if ((active_ndecs - retirable_ndecs) > 0)\r
+               remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs));\r
+       else\r
+               remain = active_vdecs - retirable_vdecs;\r
+\r
+       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);\r
+\r
+       if (active_ndecs > 0 && retirable_ndecs > 0)\r
+               return true;\r
+\r
+       if (remain >= max_vdecs)\r
+               PrintVideoDecoderConsumers();\r
+\r
+       return (remain < max_vdecs);\r
+}\r
+\r
+int CResourceDB::CountNDecoders(std::map<int, int> retirables_vdecs)\r
+{\r
+       int ndecs = 0;\r
+       for (auto &it_rsc : retirables_vdecs) {\r
+               auto it_ndec = m_active_nvdecs.find(it_rsc.first);\r
+\r
+               if (it_ndec != m_active_nvdecs.end())\r
+                       ndecs++;\r
+       }\r
+\r
+       SERVER_INFO("ndecs(%d) in retirables(%zu)", ndecs, retirables_vdecs.size());\r
+       return ndecs;\r
+}\r
+\r
+void CResourceDB::Update(resource_update_type_e type, const int device_id, const int consumer_id)\r
+{\r
+       CResource *resource = FindResource(device_id);\r
+\r
+       if (!resource)\r
+               return;\r
+\r
+       switch (type) {\r
+               case UPDATED_BY_ALLOC:\r
+                       SERVER_WARN("UPDATED_BY_ALLOC");\r
+                       UpdateByAllocation(resource, device_id, consumer_id);\r
+                       break;\r
+               case UPDATED_BY_RELEASE:\r
+                       SERVER_WARN("UPDATED_BY_RELEASE");\r
+                       UpdateByRelease(resource, device_id, consumer_id);\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("unexpected update type (%d)", type);\r
+                       break;\r
+       }\r
+\r
+       NotifyResourceStateUpdatedAsync(resource, consumer_id);\r
+}\r
+\r
+void CResourceDB::AddReclaimResources(consumer_reclaim_s *consumers)\r
+{\r
+       for (int i = 0; i < consumers->ret_quantity; i++) {\r
+               for (int j = 0; j < consumers->consumer_info[i].n_conflicted; j++) {\r
+                       SERVER_INFO("add reclaim rsc (%d)", consumers->consumer_info[i].conflicted_resources[j].device_id);\r
+                       m_reclaim_rscs.insert(consumers->consumer_info[i].conflicted_resources[j].device_id);\r
+               }\r
+       }\r
+}\r
+\r
+void CResourceDB::ClearReclaimResources(void)\r
+{\r
+       m_reclaim_rscs.clear();\r
+}\r
+\r
+gboolean CResourceDB::NotifyResourceStateUpdated(gpointer data)\r
+{\r
+       if (!data) {\r
+               SERVER_ERR("invalid data");\r
+               return G_SOURCE_REMOVE;\r
+       }\r
+\r
+       CResourceState *state = (CResourceState*) data;\r
+\r
+       GError *error = NULL;\r
+       GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);\r
+\r
+       if (!connection) {\r
+               SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown");\r
+               goto out;\r
+       }\r
+\r
+       SERVER_INFO("notify state changed (device id %d( type %d) : state %d)", state->GetDeviceId(), state->GetCategoryType(), state->GetState());\r
+\r
+       if (!g_dbus_connection_emit_signal(connection,\r
+                                               NULL,\r
+                                               RM_DBUS_OBJ_PATH,\r
+                                               RM_DBUS_INTERFACE_NAME,\r
+                                               "RscStateChanged",\r
+                                               g_variant_new("(iiiis)", state->GetDeviceId(), state->GetCategoryType(), state->GetState(), state->GetConsumerId(), state->GetAppId().c_str()),\r
+                                               &error))\r
+               SERVER_ERR("failed to send state changed (%d:%s)", state->GetDeviceId(), (error) ? error->message : "unknown");\r
+\r
+out:\r
+       if (error)\r
+               g_error_free(error);\r
+\r
+       delete state;\r
+       return G_SOURCE_REMOVE;\r
+}\r
+\r
+void CResourceDB::NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id)\r
+{\r
+       int device_id = resource->GetDeviceID();\r
+       CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id);\r
+       std::string app_id = consumer->GetAppID();\r
+\r
+       if (app_id.empty())\r
+               app_id = consumer->GetCmdName();\r
+\r
+       SERVER_INFO("device id (%d) consumer id (%d)", device_id, consumer_id);\r
+\r
+       if (m_reclaim_rscs.find(device_id) != m_reclaim_rscs.end()) {\r
+               SERVER_DBG("skip to notify state updated (%d)", device_id);\r
+               return;\r
+       }\r
+\r
+       CResourceState *state = new CResourceState(resource->GetDeviceID(), resource->GetCategoryType(), consumer_id, resource->GetState(), app_id);\r
+       g_idle_add(&CResourceDB::NotifyResourceStateUpdated, state);\r
+}\r
+\r
+CResource *CResourceDB::FindMainResource(rms_rsc_category_e category_id)\r
+{\r
+       CResourceCategory *category = FindResourceCategory(category_id);\r
+       if (!category) {\r
+               SERVER_ERR("category(%d) not found", category_id);\r
+               return NULL;\r
+       }\r
+\r
+       return category->FindMainResource();\r
+}\r
+\r
+void CResourceDB::FindMainResources(IN std::map<int, CResource*> *resource_map)\r
+{\r
+       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};\r
+       CResource *resource = NULL;\r
+\r
+       for (int i = 0; i < 6; i++) {\r
+               resource = FindMainResource(categories[i]);\r
+               if (!resource) {\r
+                       SERVER_INFO("no main resource for (%d)", categories[i]);\r
+                       continue;\r
+               }\r
+\r
+               resource_map->insert(std::pair<int, CResource*>(resource->GetDeviceID(), resource));\r
+       }\r
+}\r
+\r
+void CResourceDB::FindActiveVideoDecoders(IN std::map<int, CResource*> *resource_map)\r
+{\r
+       CResource *rsc = nullptr;\r
+       for (auto const &it : m_active_vdecs) {\r
+               rsc = FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+               resource_map->insert(std::pair<int, CResource*>(it.first, rsc));\r
+       }\r
+}\r
+\r
+void CResourceDB::GetScalerList(std::map<int, CResource*> *scalers)\r
+{\r
+       CResource *rsc = nullptr;\r
+       for (auto &it : m_deviceid_to_rsc) {\r
+               rsc = it.second;\r
+               if (!rsc->IsScaler())\r
+                       continue;\r
+\r
+               scalers->insert(std::pair<int, CResource*>(rsc->GetDeviceID(), rsc));\r
+       }\r
+}\r
+\r
+void CResourceDB::InitScalerTable(void)\r
+{\r
+       CResource *rsc = nullptr;\r
+       int sub_scaler_count = 0;\r
+       int vid = 0;\r
+\r
+       std::map<int, CResource*> scalers;\r
+       GetScalerList(&scalers);\r
+\r
+       for (auto &it : scalers) {\r
+               rsc = it.second;\r
+\r
+               if (!rsc->IsMainDevice())\r
+                       sub_scaler_count++;\r
+\r
+               vid = (rsc->IsMainDevice()) ? RI_VIRTUAL_ID_SCALER : (RI_VIRTUAL_ID_SCALER + sub_scaler_count);\r
+               rsc->SetDedicatedVirtualDeviceId(vid);\r
+               rsc->SetVirtualDeviceId(vid);\r
+               //SERVER_INFO("insert scaler (%d:%d)", vid, rsc->GetDeviceID());\r
+               m_scaler_map.insert(std::pair<int, CResource*>(vid, rsc));\r
+       }\r
+}\r
+\r
+int CResourceDB::FindRealDeviceId(int virtual_id)\r
+{\r
+       auto it = m_scaler_map.find(virtual_id);\r
+\r
+       if (it == m_scaler_map.end())\r
+               return virtual_id;\r
+\r
+       CResource *rsc = it->second;\r
+\r
+       return (rsc == nullptr) ? virtual_id : rsc->GetDeviceID();\r
+}\r
+\r
+CResource *CResourceDB::FindScaler(int virtual_id)\r
+{\r
+       auto it = m_scaler_map.find(virtual_id);\r
+       if (it == m_scaler_map.end())\r
+               return nullptr;\r
+\r
+       return it->second;\r
+}\r
+\r
+int CResourceDB::ToScalerId(int device_id)\r
+{\r
+       const int SCALER_ID_MAIN = 0;\r
+       const int SCALER_ID_SUB = 1;\r
+       const int SCALER_ID_SUB2 = 2;\r
+       const int SCALER_ID_SUB3 = 3;\r
+       const int SCALER_ID_UNKNOWN = 99;\r
+       int source_id = SCALER_ID_UNKNOWN;\r
+\r
+       switch (device_id) {\r
+               case RMS_DEVICE_SCALER:\r
+                       source_id = SCALER_ID_MAIN;\r
+                       break;\r
+               case RMS_DEVICE_SCALER_SUB:\r
+                       source_id = SCALER_ID_SUB;\r
+                       break;\r
+               case RMS_DEVICE_SCALER_SUB2:\r
+                       source_id = SCALER_ID_SUB2;\r
+                       break;\r
+               case RMS_DEVICE_SCALER_SUB3:\r
+                       source_id = SCALER_ID_SUB3;\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("unexpected device_id(%d)", device_id);\r
+                       break;\r
+       }\r
+\r
+       return source_id;\r
+}\r
+\r
+void CResourceDB::UpdateVirtualScalerIds(void)\r
+{\r
+       std::map<int, int> scaler_map;\r
+       for (auto &it : m_scaler_map) {\r
+               if (it.second == nullptr) {\r
+                       SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null");\r
+                       continue;\r
+               }\r
+\r
+               scaler_map.insert(std::pair<int, int>(it.first, ToScalerId(it.second->GetDeviceID())));\r
+               SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId());\r
+       }\r
+\r
+       CVideoController::GetInstance()->UpdateVirtualScalerIds(scaler_map);\r
+}\r
+\r
+void CResourceDB::InsertVirtualScaler(int virtual_id, CResource *resource)\r
+{\r
+       m_scaler_map.erase(virtual_id);\r
+       m_scaler_map.insert(std::pair<int, CResource*>(virtual_id, resource));\r
+       PrintVirtualScalerMap();\r
+}\r
+\r
+int CResourceDB::SwapScaler(int id_a, int id_b)\r
+{\r
+       CResource *rsc_a = FindScaler(id_a);\r
+       CResource *rsc_b = FindScaler(id_b);\r
+\r
+       SERVER_INFO("scaler swap (%d <-> %d)", id_a, id_b);\r
+\r
+       if (!rsc_a || !rsc_b) {\r
+               SERVER_ERR("invalid scaler id_a(%d)/id_b(%d)", id_a, id_b);\r
+               return -1;\r
+       }\r
+\r
+       std::set<int> consumers_a = rsc_a->GetConsumers();\r
+       std::set<int> consumers_b = rsc_b->GetConsumers();\r
+\r
+       int zone_a = rsc_a->GetZoneId();\r
+       int zone_b = rsc_b->GetZoneId();\r
+\r
+       rsc_a->SetZoneId(zone_b);\r
+       rsc_b->SetZoneId(zone_a);\r
+\r
+       rms_resource_internal_state_e state_a = (rms_resource_internal_state_e) rsc_a->GetState();\r
+       rms_resource_internal_state_e state_b = (rms_resource_internal_state_e) rsc_b->GetState();\r
+       rsc_a->ChangeState(state_b);\r
+       rsc_b->ChangeState(state_a);\r
+\r
+       UpdateConsumerInfoOfResource(rsc_a, consumers_b, id_b);\r
+       UpdateConsumerInfoOfResource(rsc_b, consumers_a, id_a);\r
+\r
+       // update resource info of each consumer\r
+       SwapResource(consumers_a, rsc_a->GetDeviceID(), rsc_b->GetDeviceID());\r
+       SwapResource(consumers_b, rsc_b->GetDeviceID(), rsc_a->GetDeviceID());\r
+\r
+       // update memcluster owners\r
+       CDependencyController::getInstance()->SwapConsumers(rsc_a->GetDeviceID(), consumers_a, rsc_b->GetDeviceID(), consumers_b);\r
+\r
+       // update virtual scaler table\r
+       InsertVirtualScaler(id_a, rsc_b);\r
+       InsertVirtualScaler(id_b, rsc_a);\r
+       return 0;\r
+}\r
+\r
+void CResourceDB::UpdateConsumerInfoOfResource(CResource *resource, std::set<int> new_consumers, int new_virtual_id)\r
+{\r
+       resource->ResetConsumer(new_consumers);\r
+       resource->SetVirtualDeviceId(new_virtual_id);\r
+}\r
+\r
+void CResourceDB::SwapResource(std::set<int> consumers, int cur_device_id, int new_device_id)\r
+{\r
+       CConsumer *consumer;\r
+       for (auto &it : consumers) {\r
+               consumer = CConsumerContainer::getInstance()->findConsumer(it);\r
+               if (!consumer) {\r
+                       SERVER_ERR("invalid consumer (%d)", it);\r
+                       continue;\r
+               }\r
+\r
+               SERVER_INFO("swap resource (%d):(%d>%d)", it, cur_device_id, new_device_id);\r
+\r
+               if (consumer->IsUsingResource(new_device_id)) {\r
+                       SERVER_INFO("no need to swap (%d:%d)", it, new_device_id);\r
+                       continue;\r
+               }\r
+               consumer->ReleaseResource(cur_device_id);\r
+               consumer->AddResource(new_device_id);\r
+       }\r
+}\r
+\r
+void CResourceDB::InsertResourceHasZoneId(CResource *rsc)\r
+{\r
+       int device_id = rsc->GetDeviceID();\r
+       auto it = m_rscs_has_zone_id.find(device_id);\r
+\r
+       if (it != m_rscs_has_zone_id.end())\r
+               return;\r
+\r
+       m_rscs_has_zone_id.insert(std::pair<int, CResource*>(device_id, rsc));\r
+       SERVER_INFO("inserted (%d:%d:%zu)", device_id, rsc->GetZoneId(), m_rscs_has_zone_id.size());\r
+}\r
+\r
+void CResourceDB::RemoveResourceHasZoneId(int device_id)\r
+{\r
+       if (m_rscs_has_zone_id.empty())\r
+               return;\r
+\r
+       auto it = m_rscs_has_zone_id.find(device_id);\r
+       if (it != m_rscs_has_zone_id.end())\r
+               return;\r
+\r
+       m_rscs_has_zone_id.erase(device_id);\r
+       SERVER_INFO("removed (%d:%zu)", device_id, m_rscs_has_zone_id.size());\r
+}\r
+\r
+void CResourceDB::ResetZoneIds(void)\r
+{\r
+       CResource *rsc = nullptr;\r
+       SERVER_INFO("Reset zone ids");\r
+\r
+       for (auto &it : m_rscs_has_zone_id) {\r
+               rsc = it.second;\r
+               if (!rsc)\r
+                       continue;\r
+               rsc->SetZoneId(-1);\r
+       }\r
+       m_rscs_has_zone_id.clear();\r
+}\r
diff --git a/src/manager/CResourceManager.cpp b/src/manager/CResourceManager.cpp
new file mode 100644 (file)
index 0000000..166b724
--- /dev/null
@@ -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 <iostream>
+#include <assert.h>
+#include <vector>
+#include <set>
+#include <map>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include <algorithm>
+
+#include <ri-common-type.h>
+#include <ri-module-api.h>
+#include <ri-category-type.h>
+#include <rms_debug.h>
+
+#include <CResourceManager.h>
+#include <CResource.h>
+#include <CResourceDB.h>
+#include <CVirtualResource.h>
+#include <CResourceCategory.h>
+#include <CDebugUtils.h>
+#include <CConsumer.h>
+#include <CConsumerContainer.h>
+#include <CRequester.h>
+#include <CBandwidth.h>
+#include <CDependencyController.h>
+#include <CAllocateModeStrategy.h>
+#include <CAllocateModeStrategyProvider.h>
+
+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<CRequest *> *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<CRequest *> 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<CRequest *> 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<unsigned int> 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<int, CConsumer*> 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<int> 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<int, int> *device_id_to_consumer_id_map, std::map<int, std::set<int> > *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<int> rsc_count = (*it_count).second;
+                       rsc_count.insert(device_id);
+
+                       consumer_id_to_resource_set_map->operator[](consumer_id) = rsc_count;
+               } else {
+                       std::set<int> rsc_count;
+                       rsc_count.insert(device_id);
+                       consumer_id_to_resource_set_map->insert(std::pair< int, std::set<int> >(consumer_id, rsc_count));
+               }
+       }
+}
+
+void CResourceManager::MakeConsumerInfoToBeReturned(consumer_reclaim_s *return_consumer, std::map<int, std::set<int> > *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<int> >::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<int> 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<int>::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<CRequest *> requests;
+       MakeRequests(requester, req, &requests);
+
+       std::multimap<int, int> 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<int> > 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<CRequest *> 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<int, CResource*> 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<int, CResource*> 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<int, CResource*> 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<int> 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<int, CResource*> 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<int, CConsumer *> 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<int> 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 (file)
index 0000000..f08c8a3
--- /dev/null
@@ -0,0 +1,27 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <iostream>\r
+#include <CResourceState.h>\r
+\r
+CResourceState::CResourceState(int device_id, int category_type, int consumer_id, int state, std::string app_id)\r
+{\r
+       m_device_id = device_id;\r
+       m_category_type = category_type;\r
+       m_consumer_id = consumer_id;\r
+       m_state = state;\r
+       m_app_id = app_id;\r
+}
\ No newline at end of file
diff --git a/src/manager/CVideoController.cpp b/src/manager/CVideoController.cpp
new file mode 100644 (file)
index 0000000..db9bfc0
--- /dev/null
@@ -0,0 +1,174 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <new>\r
+#include <assert.h>\r
+#include <unistd.h>\r
+#include <trace.h>\r
+#include <rms_debug.h>\r
+#include <CVideoController.h>\r
+\r
+#define LWIPC_WM_READY "/tmp/.wm_ready"\r
+#define LWIPC_TIMEOUT_MS 10000\r
+#define LWIPC_SWAP_DONE "/tmp/.scaler_swap_done"\r
+#define LWIPC_SWAP_DONE_TIMEOUT_MS 3000\r
+#define LWIPC_SWAP_DONE_TIMEOUT_DBG_MS 4000\r
+#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0)\r
+\r
+CVideoController *CVideoController::m_instance = nullptr;\r
+\r
+static void registry_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version)\r
+{\r
+       void **tizen_video_rsc = (void**)data;\r
+\r
+       if (strncmp(interface, "tizen_video_rsc", sizeof("tizen_video_rsc")))\r
+               return;\r
+\r
+       SERVER_INFO("%p : %s", tizen_video_rsc, interface);\r
+       //*tizen_video_rsc = wl_registry_bind(wl_registry, id, &tizen_video_rsc_interface, 1);\r
+}\r
+\r
+static void registry_handle_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)\r
+{\r
+\r
+}\r
+\r
+void CVideoController::WaylandDisplayCreate(void)\r
+{\r
+       SERVER_INFO("Create Start");\r
+\r
+       SERVER_INFO("%s is created", LWIPC_WM_READY);\r
+       m_wl_display = wl_display_connect(nullptr);\r
+\r
+       if (!m_wl_display) {\r
+               SERVER_ERR("Failed to connect to the wayland display");\r
+               return;\r
+       }\r
+\r
+       m_wl_registry = wl_display_get_registry(m_wl_display);\r
+       wl_registry_add_listener(m_wl_registry, &m_registry_listener, &m_tizen_video_rsc);\r
+       SERVER_INFO("Add listener : %p", &m_tizen_video_rsc);\r
+\r
+       wl_display_roundtrip(m_wl_display);\r
+\r
+       if (!m_tizen_video_rsc)\r
+               SERVER_ERR("Failed to get tizen_video_rsc");\r
+\r
+       SERVER_INFO("Create Done");\r
+}\r
+\r
+void CVideoController::WaylandDisplayDestroy(void)\r
+{\r
+       if (m_tizen_video_rsc) {\r
+               //tizen_video_rsc_destroy(m_tizen_video_rsc);\r
+               m_tizen_video_rsc = nullptr;\r
+       }\r
+\r
+       if (m_wl_registry) {\r
+               wl_registry_destroy(m_wl_registry);\r
+               m_wl_registry = nullptr;\r
+       }\r
+\r
+       SERVER_INFO("Display disconnect");\r
+\r
+       if (m_wl_display) {\r
+               wl_display_roundtrip(m_wl_display);\r
+               wl_display_disconnect(m_wl_display);\r
+               m_wl_display = nullptr;\r
+       }\r
+\r
+       SERVER_INFO("Destroy Done");\r
+}\r
+\r
+CVideoController::CVideoController(void) : m_wl_display(nullptr), m_wl_registry(nullptr), m_tizen_video_rsc(nullptr), m_waiting_thread(nullptr)\r
+{\r
+       m_registry_listener.global = registry_handle_global;\r
+       m_registry_listener.global_remove = registry_handle_global_remove;\r
+       WaylandDisplayCreate();\r
+       m_lock_ctr = CLockController::GetInstance();\r
+\r
+       SERVER_INFO("Initialize Done");\r
+}\r
+\r
+CVideoController::~CVideoController(void)\r
+{\r
+       WaylandDisplayDestroy();\r
+       SERVER_INFO("Finalize Done");\r
+}\r
+\r
+CVideoController *CVideoController::GetInstance(void)\r
+{\r
+       if (m_instance == nullptr)\r
+       {\r
+               m_instance = new(std::nothrow) CVideoController();\r
+               assert(m_instance);\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+void CVideoController::UpdateVirtualScalerIds(std::map<int, int> scaler_id_map)\r
+{\r
+       struct wl_array mapping_list;\r
+       scaler_id_pair_t *scaler_id_pair = NULL;\r
+\r
+       wl_array_init(&mapping_list);\r
+       SERVER_ERR("Update virtual scaler ids");\r
+\r
+       for (auto it = scaler_id_map.begin(); it != scaler_id_map.end(); it++) {\r
+               scaler_id_pair = (scaler_id_pair_t*)wl_array_add(&mapping_list, sizeof(scaler_id_pair_t));\r
+               scaler_id_pair->virtual_scaler_id = it->first;\r
+               scaler_id_pair->scaler_id = it->second;\r
+               SERVER_ERR("scaler(%d:%d)", it->first, it->second);\r
+       }\r
+\r
+       //tizen_video_rsc_map_scaler_id(m_tizen_video_rsc, &mapping_list);\r
+\r
+       wl_display_roundtrip(m_wl_display);\r
+       wl_array_release(&mapping_list);\r
+\r
+       RunWaitingThread();\r
+}\r
+\r
+gpointer CVideoController::WaitingThread(gpointer data)\r
+{\r
+       assert(data);\r
+       CVideoController *ctr = (CVideoController*) data;\r
+\r
+       ctr->m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER);\r
+       ctr->m_waiting_thread =  nullptr;\r
+       return 0;\r
+}\r
+\r
+void CVideoController::RunWaitingThread(void)\r
+{\r
+       if (m_waiting_thread)\r
+       {\r
+               SERVER_ERR("already created");\r
+               return;\r
+       }\r
+\r
+       m_lock_ctr->Lock(ResourceType::VIDEO_SCALER);\r
+\r
+       m_waiting_thread = g_thread_new("waiting_swap_done", WaitingThread, this);\r
+       if (m_waiting_thread == nullptr) {\r
+               m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER);\r
+               SERVER_ERR("failed to create waiting_swap_done thread");\r
+               return;\r
+       }\r
+\r
+       SERVER_ERR("waiting_swap_done thread created");\r
+}\r
diff --git a/src/manager/CVirtualResource.cpp b/src/manager/CVirtualResource.cpp
new file mode 100644 (file)
index 0000000..c7b2aba
--- /dev/null
@@ -0,0 +1,33 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <CVirtualResource.h>\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+\r
+CVirtualResource::CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set<unsigned int> dependent, bool is_main_device, const char *audio_codec, int category_class)\r
+: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)\r
+{\r
+       m_mem_clusters = dependent;\r
+\r
+       if (audio_codec)\r
+               m_audio_codec.assign(audio_codec);\r
+}\r
+\r
+void CVirtualResource::SetResource(CResource *resource)\r
+{\r
+       m_rsc = resource;\r
+}\r
diff --git a/src/manager/dependence/CAudioCodec.cpp b/src/manager/dependence/CAudioCodec.cpp
new file mode 100644 (file)
index 0000000..15dd2b8
--- /dev/null
@@ -0,0 +1,108 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_debug.h>\r
+#include <CAudioCodec.h>\r
+\r
+CAudioCodec::CAudioCodec(const char * name)\r
+:m_ref_count(0), m_ref_count_max(0)\r
+{\r
+       m_name.assign(name);\r
+}\r
+\r
+CAudioCodec::~CAudioCodec()\r
+{\r
+}\r
+\r
+void CAudioCodec::increaseRef(int device_id, int consumer_id)\r
+{\r
+       if (m_ref_count_max == 0)\r
+               return;\r
+\r
+       if (m_ref_count >= m_ref_count_max) {\r
+               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);\r
+               return;\r
+       }\r
+\r
+       m_ref_count++;\r
+\r
+       auto it = m_consumers.find(consumer_id);\r
+\r
+       m_resources.insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+       if (it == m_consumers.end()) {\r
+               m_consumers.insert(std::pair<int, int>(consumer_id, 1));\r
+               return;\r
+       }\r
+\r
+       (*it).second = ++it->second ;\r
+}\r
+\r
+void CAudioCodec::decreaseRef(int device_id, int consumer_id)\r
+{\r
+       if (m_ref_count_max == 0)\r
+               return;\r
+\r
+       if (m_ref_count <= 0) {\r
+               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);\r
+               return;\r
+       }\r
+\r
+       auto it = m_consumers.find(consumer_id);\r
+\r
+       if (it == m_consumers.end()) {\r
+               SERVER_ERR("not registered consumer(%d)", consumer_id);\r
+               return;\r
+       }\r
+\r
+       m_resources.erase(device_id);\r
+\r
+       m_ref_count--;\r
+\r
+       if (it->second <= 1) {\r
+               m_consumers.erase(consumer_id);\r
+               return;\r
+       }\r
+\r
+       (*it).second = --it->second;\r
+}\r
+\r
+void CAudioCodec::increaseMaxRef(void)\r
+{\r
+       m_ref_count_max++;\r
+}\r
+\r
+bool CAudioCodec::isAvailableToUse(void)\r
+{\r
+       if (isUnknownCodec())\r
+               return true;\r
+\r
+       SERVER_INFO("%s > cur(%d), max(%d)", m_name.c_str(), m_ref_count, m_ref_count_max);\r
+\r
+       return (m_ref_count < m_ref_count_max);\r
+}\r
+\r
+std::set<int> CAudioCodec::getResourcesOfConsumer(int consumer_id)\r
+{\r
+       std::set<int> resources;\r
+\r
+       for (auto const &it : m_resources) {\r
+               if (it.second == consumer_id)\r
+                       resources.insert(it.first);\r
+       }\r
+\r
+       return resources;\r
+}\r
diff --git a/src/manager/dependence/CAudioCodecCollection.cpp b/src/manager/dependence/CAudioCodecCollection.cpp
new file mode 100644 (file)
index 0000000..5d73640
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+\r
+#include <CAudioCodec.h>\r
+#include <CAudioCodecCollection.h>\r
+\r
+CAudioCodecCollection *CAudioCodecCollection::m_instance = NULL;\r
+\r
+CAudioCodecCollection::CAudioCodecCollection()\r
+{\r
+\r
+}\r
+\r
+CAudioCodecCollection *CAudioCodecCollection::getInstance(void)\r
+{\r
+       if (!m_instance)\r
+               m_instance = new CAudioCodecCollection();\r
+\r
+       return m_instance;\r
+}\r
+\r
+CAudioCodecCollection::~CAudioCodecCollection()\r
+{\r
+}\r
+\r
+CAudioCodec *CAudioCodecCollection::findAudioCodec(std::string name)\r
+{\r
+       auto it = m_audio_codecs.find(name);\r
+\r
+       return (it == m_audio_codecs.end()) ? NULL : it->second;\r
+}\r
+\r
+void CAudioCodecCollection::registerAudioCodec(const char *name, int count)\r
+{\r
+       if (!name)\r
+               return;\r
+\r
+       CAudioCodec *audio_codec = findAudioCodec(name);\r
+\r
+       if (!audio_codec) {\r
+               audio_codec = new CAudioCodec(name);\r
+               m_audio_codecs.insert(std::pair<std::string, CAudioCodec*>(std::string(name), audio_codec));\r
+       }\r
+\r
+       if (count > 0)\r
+               audio_codec->increaseMaxRef();\r
+}\r
diff --git a/src/manager/dependence/CBandwidth.cpp b/src/manager/dependence/CBandwidth.cpp
new file mode 100644 (file)
index 0000000..c9535df
--- /dev/null
@@ -0,0 +1,164 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CResourceDB.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CBandwidth.h>\r
+\r
+CBandwidth *CBandwidth::m_instance = NULL;\r
+\r
+CBandwidth *CBandwidth::GetInstance(void)\r
+{\r
+       if (!m_instance)\r
+       {\r
+               m_instance = new CBandwidth();\r
+       }\r
+\r
+       return m_instance;\r
+}\r
+\r
+void CBandwidth::AddConsumerNDec(int device_id, int consumer_id, int category_id)\r
+{\r
+       auto it = m_ndec_consumers.find(category_id);\r
+       if (it == m_ndec_consumers.end())\r
+       {\r
+               std::map<int, int> consumers;\r
+               consumers.insert(std::pair<int, int>(device_id, consumer_id));\r
+               m_ndec_consumers.insert(std::pair<int, std::map<int, int>>(category_id, consumers));\r
+       }\r
+       else\r
+       {\r
+               std::map<int, int> *consumers = &it->second;\r
+               consumers->insert(std::pair<int, int>(device_id, consumer_id));\r
+       }\r
+}\r
+\r
+void CBandwidth::RemoveConsumerNDec(int device_id, int category_id)\r
+{\r
+       auto it = m_ndec_consumers.find(category_id);\r
+       if (it == m_ndec_consumers.end())\r
+               return;\r
+\r
+       it->second.erase(device_id);\r
+}\r
+\r
+void CBandwidth::GetConsumersNDec(int category_id, std::map<int, int> *consumers)\r
+{\r
+       auto it = m_ndec_consumers.find(category_id);\r
+       if (it == m_ndec_consumers.end())\r
+               return;\r
+\r
+       consumers->insert(it->second.begin(), it->second.end());\r
+}\r
+\r
+void CBandwidth::AddConsumer(int device_id, int consumer_id, int category_id, int category_class)\r
+{\r
+       m_consumers.insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+       if (category_class == RMS_CATEGORY_CLASS_N_DECODING)\r
+               AddConsumerNDec(device_id, consumer_id, category_id);\r
+}\r
+\r
+void CBandwidth::RemoveConsumer(int device_id, int category_id, int category_class)\r
+{\r
+       auto it = m_consumers.find(device_id);\r
+       if (it == m_consumers.end())\r
+               return;\r
+\r
+       m_consumers.erase(device_id);\r
+\r
+       if (category_class == RMS_CATEGORY_CLASS_N_DECODING)\r
+               RemoveConsumerNDec(device_id, category_id);\r
+}\r
+\r
+int CBandwidth::GetNConsumersNDec(int category_id)\r
+{\r
+       auto it = m_ndec_consumers.find(category_id);\r
+       if (it == m_ndec_consumers.end())\r
+               return 0;\r
+\r
+       return it->second.size();\r
+}\r
+\r
+void CBandwidth::Increase(unsigned int bw, int category_id, int category_class, int device_id)\r
+{\r
+       if ((category_class == RMS_CATEGORY_CLASS_N_DECODING) && IncludeSameDeviceGroup(category_id, device_id))\r
+               return;\r
+\r
+       m_avail += bw;\r
+       m_avail = (m_avail > m_max) ? m_max : m_avail;\r
+}\r
+\r
+void CBandwidth::Decrease(unsigned int bw, int category_id, int category_class, int device_id)\r
+{\r
+       if (category_class == RMS_CATEGORY_CLASS_N_DECODING && IncludeSameDeviceGroup(category_id, device_id))\r
+               return;\r
+\r
+       m_avail -= bw;\r
+}\r
+\r
+bool CBandwidth::IncludeSameDeviceGroup(int category_id, int device_id)\r
+{\r
+       if (GetNConsumersNDec(category_id) == 0)\r
+               return false;\r
+\r
+       CResource *c_rsc;\r
+       CVirtualResource *c_vrsc;\r
+       std::set<unsigned int> c_mc;\r
+\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       CResource *u_rsc = db->FindResource(device_id);\r
+       CVirtualResource *u_vrsc = db->FindVirtualResource(u_rsc->GetVirtualResourceID());\r
+\r
+       std::set<unsigned int> u_mc = u_vrsc->GetMemClusters();\r
+\r
+       std::map<int, int> consumers; // device_id, consumer_id\r
+       GetConsumersNDec(category_id, &consumers);\r
+\r
+       for (auto const &it : consumers)\r
+       {\r
+               c_rsc = db->FindResource(it.first);\r
+               c_vrsc = db->FindVirtualResource(c_rsc->GetVirtualResourceID());\r
+               c_mc = c_vrsc->GetMemClusters();\r
+\r
+               if (c_rsc->GetDeviceID() == u_rsc->GetDeviceID())\r
+                       continue;\r
+\r
+               if (IsSameMemClusters(c_mc, u_mc))\r
+               {\r
+                       SERVER_INFO("same mc (%d = %d) found", device_id, it.first);\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CBandwidth::IsSameMemClusters(std::set<unsigned int> c_mc, std::set<unsigned int> u_mc)\r
+{\r
+       if (c_mc.size() != u_mc.size())\r
+               return false;\r
+\r
+       for (auto const &it : u_mc)\r
+       {\r
+               if (c_mc.find(it) == c_mc.end())\r
+                       return false;\r
+       }\r
+       return true;\r
+}\r
diff --git a/src/manager/dependence/CDependencyController.cpp b/src/manager/dependence/CDependencyController.cpp
new file mode 100644 (file)
index 0000000..43354b0
--- /dev/null
@@ -0,0 +1,502 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdio.h>\r
+\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CResourceDB.h>\r
+#include <CMemCluster.h>\r
+#include <CMixingMode.h>\r
+#include <CAudioCodec.h>\r
+#include <CAudioCodecCollection.h>\r
+#include <CPriority.h>\r
+#include <CResourceCategory.h>\r
+#include <CResourceObserver.h>\r
+#include <CDependencyController.h>\r
+#include <CConsumer.h>\r
+#include <CConsumerContainer.h>\r
+\r
+#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))\r
+\r
+static rms_mixing_mode_e supported_mixing_modes[] =\r
+{\r
+       RMS_MIXING_MODE_DEFAULT,\r
+       RMS_MIXING_MODE_MULTIVIEW,\r
+       RMS_MIXING_MODE_INTERACTION_SOUND\r
+};\r
+\r
+CDependencyController *CDependencyController::m_instance = NULL;\r
+\r
+CDependencyController::CDependencyController()\r
+{\r
+       registerMixingModes();\r
+       m_cur_mixing_mode = NULL;\r
+}\r
+\r
+CDependencyController *CDependencyController::getInstance(void)\r
+{\r
+       if (!m_instance)\r
+               m_instance = new CDependencyController();\r
+\r
+       return m_instance;\r
+}\r
+\r
+CDependencyController::~CDependencyController()\r
+{\r
+}\r
+\r
+void CDependencyController::registerMixingModes(void)\r
+{\r
+       for (unsigned int i = 0; i < ARRAY_SIZE(supported_mixing_modes); i++) {\r
+               CMixingMode *mixing_mode = new CMixingMode(supported_mixing_modes[i]);\r
+               m_mixing_modes.insert(std::pair<rms_mixing_mode_e, CMixingMode*>(supported_mixing_modes[i], mixing_mode));\r
+       }\r
+}\r
+\r
+bool CDependencyController::IsRegisteredMemCluster(unsigned int id)\r
+{\r
+       auto it = m_mem_clusters.find(id);\r
+       return (it != m_mem_clusters.end());\r
+}\r
+\r
+CMemCluster *CDependencyController::findMemCluster(unsigned int id)\r
+{\r
+       auto it = m_mem_clusters.find(id);\r
+\r
+       if (it == m_mem_clusters.end())\r
+       {\r
+               SERVER_ERR("not existing mem cluster(%d)", id);\r
+               return NULL;\r
+       }\r
+\r
+       return it->second;\r
+}\r
+\r
+void CDependencyController::RegisterMemCluster(unsigned int id)\r
+{\r
+       if (IsRegisteredMemCluster(id))\r
+               return;\r
+\r
+       CMemCluster *mc = new CMemCluster(id);\r
+       SERVER_INFO("register mem cluster (%d)", id);\r
+       m_mem_clusters.insert(std::pair<unsigned int, CMemCluster*>(id, mc));\r
+}\r
+\r
+bool CDependencyController::isAvailableMemClusters(std::set<unsigned int> mc_ids)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               if (mc->IsUsed()) {\r
+                       SERVER_INFO("mem cluster (%d) is being used", mc->GetId());\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CDependencyController::isAvailableMemClusters(std::set<unsigned int> mc_ids, std::string app_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               if (mc->IsUsed() && !mc->IsUsedBy(app_id)) {\r
+                       SERVER_INFO("mem cluster (%d) is being used", mc->GetId());\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CDependencyController::isAvailableMemClusters(std::set<unsigned int> mc_ids, int category_class, int category_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               if (!mc->IsUsed())\r
+                       continue;\r
+\r
+               if (mc->GetCategoryClass() != category_class) {\r
+                       SERVER_INFO("mem cluster (%d) is in use, mc_class(%d)/category(%d)", mc->GetId(), mc->GetCategoryClass(), category_class);\r
+                       return false;\r
+               }\r
+\r
+               if (mc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING && (mc->GetCategoryId() != category_id)) {\r
+                       SERVER_INFO("mem cluster (%d) is in use, mc_category(%d)/category(%d)", mc->GetId(), mc->GetCategoryId(), category_id);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CDependencyController::isSharableMemClusters(std::set<unsigned int> mc_ids, int device_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               if (!mc->IsSharable(device_id))         {\r
+                       SERVER_INFO("mem cluster (%d) is not sharable", mc->GetId());\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+\r
+bool CDependencyController::canReclaimMemClusters(std::set<unsigned int> mc_ids, int consumer_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto const &it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               std::set<int> consumers = mc->GetConsumers();\r
+\r
+               for (auto const &it_consumer : consumers) {\r
+                       if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) {\r
+                               SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer);\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CDependencyController::canReclaimMemClusters(std::set<unsigned int> mc_ids, int consumer_id, std::string app_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+       CConsumerContainer *c_container = CConsumerContainer::getInstance();\r
+       CConsumer *consumer = NULL;\r
+\r
+       for (auto const &it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return false;\r
+               }\r
+\r
+               std::set<int> consumers = mc->GetConsumers();\r
+\r
+               for (auto const &it_consumer : consumers) {\r
+                       consumer = c_container->findConsumer(it_consumer);\r
+                       if (consumer) {\r
+                               if (!consumer->GetAppID().compare(app_id)) {\r
+                                       SERVER_INFO("skip to check priority against same app (%s:%s)", consumer->GetAppID().c_str(), app_id.c_str());\r
+                                       continue;\r
+                               }\r
+                       }\r
+\r
+                       if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) {\r
+                               SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer);\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+int CDependencyController::getReclaimableMemClusterConsumers(std::set<unsigned int> mc_ids, int consumer_id, std::multimap<int, int>* reclaimables)\r
+{\r
+       CMemCluster *mc = NULL;\r
+\r
+       for (auto const &it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return RMS_ERROR;\r
+               }\r
+\r
+               std::set<int> consumers = mc->GetConsumers();\r
+\r
+               for (auto const &it_consumer : consumers) {\r
+                       if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) {\r
+                               SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer);\r
+                               return RMS_ERROR;\r
+                       }\r
+\r
+                       std::set<int> device_ids = mc->GetAssignedDeviceId(it_consumer);\r
+                       for (auto const &it_dev_id : device_ids) {\r
+                               SERVER_INFO("[mc:%d] add (%d:%d)", mc->GetId(), it_dev_id, it_consumer);\r
+                               reclaimables->insert(std::pair<int, int>(it_dev_id, it_consumer));\r
+                       }\r
+               }\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CDependencyController::getReclaimableMemClusterConsumers(std::set<unsigned int> mc_ids, int consumer_id, std::multimap<int, int>* reclaimables, std::string app_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+       CConsumerContainer *c_container = CConsumerContainer::getInstance();\r
+       CConsumer *consumer = NULL;\r
+\r
+       for (auto const &it : mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc) {\r
+                       SERVER_INFO("mem cluster NULL");\r
+                       return RMS_ERROR;\r
+               }\r
+\r
+               std::set<int> consumers = mc->GetConsumers();\r
+\r
+               for (auto const &it_consumer : consumers) {\r
+                       consumer = c_container->findConsumer(it_consumer);\r
+                       if (!consumer->GetAppID().compare(app_id)) {\r
+                               SERVER_INFO("skip to check priority against same app (%s:%s)", consumer->GetAppID().c_str(), app_id.c_str());\r
+                               continue;\r
+                       }\r
+\r
+                       if (!CPriority::isReclaimableConsumer(it_consumer, consumer_id, NULL)) {\r
+                               SERVER_ERR("can't reclaim mc(%d) from (%d)", mc->GetId(), it_consumer);\r
+                               return RMS_ERROR;\r
+                       }\r
+\r
+                       std::set<int> device_ids = mc->GetAssignedDeviceId(it_consumer);\r
+                       for (auto const &it_dev_id : device_ids) {\r
+                               SERVER_INFO("[mc:%d] add (%d:%d)", mc->GetId(), it_dev_id, it_consumer);\r
+                               reclaimables->insert(std::pair<int, int>(it_dev_id, it_consumer));\r
+                       }\r
+               }\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+void CDependencyController::SwapConsumers(int device_id_a, std::set<int> consumers_a, int device_id_b, std::set<int> consumers_b)\r
+{\r
+       ClearMemClusterConsumer(device_id_a);\r
+       ClearMemClusterConsumer(device_id_b);\r
+\r
+       for (auto const &it : consumers_a)\r
+               addMemClusterConsumer(device_id_b, it);\r
+\r
+       for (auto const &it : consumers_b)\r
+               addMemClusterConsumer(device_id_a, it);\r
+}\r
+\r
+void CDependencyController::addMemClusterConsumer(int device_id, int consumer_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+       CResource *rsc = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!rsc)\r
+               return;\r
+\r
+       if (rsc->GetCurCategory() == RMS_CATEGORY_VIDEO_ENCODER_EXCLUSIVE)\r
+               return;\r
+\r
+       int category_class = rsc->GetCategoryClass();\r
+\r
+       std::set<unsigned int> mc_mc_ids = rsc->GetMemClusters();\r
+       for (auto const &it : mc_mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc)\r
+                       continue;\r
+\r
+               mc->AddConsumer(consumer_id, device_id, category_class, rsc->GetCurCategory());\r
+               SERVER_INFO("add consumer(%d) to mem_cluster(%d)/class(%d)", consumer_id, mc->GetId(), category_class);\r
+       }\r
+}\r
+\r
+void CDependencyController::removeMemClusterConsumer(int device_id, int consumer_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!resource)\r
+               return;\r
+\r
+       std::set<unsigned int> mc_mc_ids = resource->GetMemClusters();\r
+\r
+       for (auto const &it : mc_mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc)\r
+                       continue;\r
+\r
+               mc->RemoveConsumer(consumer_id, device_id);\r
+               SERVER_INFO("remove consumer(%d) from mem_cluster(%d)", consumer_id, mc->GetId());\r
+       }\r
+}\r
+\r
+void CDependencyController::ClearMemClusterConsumer(int device_id)\r
+{\r
+       CMemCluster *mc = NULL;\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+       if (!resource)\r
+               return;\r
+\r
+       std::set<unsigned int> mc_mc_ids = resource->GetMemClusters();\r
+\r
+       for (auto const &it : mc_mc_ids) {\r
+               mc = findMemCluster(it);\r
+               if (!mc)\r
+                       continue;\r
+\r
+               mc->ClearConsumers();\r
+               SERVER_INFO("clear consumers from mem_cluster(%d)", mc->GetId());\r
+       }\r
+}\r
+\r
+void CDependencyController::Update(resource_update_type_e type, const int device_id, const int consumer_id)\r
+{\r
+       switch (type) {\r
+               case UPDATED_BY_ALLOC:\r
+                       addMemClusterConsumer(device_id, consumer_id);\r
+                       addAudioCodecConsumer(device_id, consumer_id);\r
+                       setCurMixingMode(device_id, consumer_id);\r
+                       break;\r
+               case UPDATED_BY_RELEASE:\r
+                       removeMemClusterConsumer(device_id, consumer_id);\r
+                       removeAudioCodecConsumer(device_id, consumer_id);\r
+                       resetCurMixingMode(device_id, consumer_id);\r
+                       break;\r
+               default:\r
+                       SERVER_ERR("unexpected update type (%d)", type);\r
+                       break;\r
+       }\r
+}\r
+\r
+void CDependencyController::addAudioCodecConsumer(int device_id, int consumer_id)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!resource->IsAudioDevice())\r
+               return;\r
+\r
+       m_acodec_consumers.insert(std::pair<int, int> (device_id, consumer_id));\r
+\r
+       std::string codec_name = resource->GetAudioCodec();\r
+       CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name);\r
+\r
+       codec->increaseRef(device_id, consumer_id);\r
+}\r
+\r
+void CDependencyController::removeAudioCodecConsumer(int device_id, int consumer_id)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!resource->IsAudioDevice())\r
+               return;\r
+\r
+       m_acodec_consumers.erase(device_id);\r
+\r
+       std::string codec_name = resource->GetAudioCodec();\r
+       CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name);\r
+\r
+       codec->decreaseRef(device_id, consumer_id);\r
+}\r
+\r
+CMixingMode *CDependencyController::findMixingMode(rms_mixing_mode_e mode)\r
+{\r
+       auto it = m_mixing_modes.find(mode);\r
+\r
+       return (it == m_mixing_modes.end()) ? NULL : it->second;\r
+}\r
+\r
+void CDependencyController::setCurMixingMode(int device_id, int consumer_id)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!resource->IsAudioDevice())\r
+               return;\r
+\r
+       rms_mixing_mode_e mode_id = resource->GetMixingMode();\r
+       CMixingMode *mode = findMixingMode(mode_id);\r
+\r
+       if (!mode) {\r
+               SERVER_ERR("undefined mixing mode (%d)", mode_id);\r
+               return;\r
+       }\r
+\r
+       mode->AddConsumer(device_id, consumer_id);\r
+\r
+       m_cur_mixing_mode = mode;\r
+}\r
+\r
+void CDependencyController::resetCurMixingMode(int device_id, int consumer_id)\r
+{\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(device_id);\r
+\r
+       if (!resource->IsAudioDevice())\r
+               return;\r
+\r
+       rms_mixing_mode_e mode_id = resource->GetMixingMode();\r
+       CMixingMode *mode = findMixingMode(mode_id);\r
+\r
+       if (!mode) {\r
+               SERVER_ERR("undefined mixing mode (%d)", mode_id);\r
+               return;\r
+       }\r
+\r
+       if (mode->RemoveConsumer(device_id, consumer_id) > 0)\r
+               return;\r
+\r
+       m_cur_mixing_mode = NULL;\r
+}\r
+\r
+bool CDependencyController::isAvailableAudioCodec(std::string name)\r
+{\r
+       SERVER_DBG("cur(%zu)/max(%d)", m_acodec_consumers.size(), m_acodec_ref_count_max);\r
+       return (m_acodec_consumers.size() >= m_acodec_ref_count_max); //???\r
+}\r
+\r
+std::map<unsigned long, std::pair<int, int>> CDependencyController::getAudioCodecConsumers(void)\r
+{\r
+       std::map<unsigned long, std::pair<int, int>> consumers;\r
+\r
+       for (auto const &it : m_acodec_consumers) {\r
+               CResource *rsc = CResourceDB::getInstance()->FindResource(it.first);\r
+               consumers.insert(std::pair<unsigned long, std::pair<int, int>>(rsc->GetAllocatedTime(), std::make_pair(it.first, it.second)));\r
+       }\r
+\r
+       return consumers;\r
+}\r
diff --git a/src/manager/dependence/CMemCluster.cpp b/src/manager/dependence/CMemCluster.cpp
new file mode 100644 (file)
index 0000000..0649621
--- /dev/null
@@ -0,0 +1,141 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include "CMemCluster.h"\r
+#include "CConsumerContainer.h"\r
+#include "CConsumer.h"\r
+\r
+CMemCluster::CMemCluster(unsigned int id)\r
+{\r
+       m_id = id;\r
+       m_category_class = 0;\r
+       m_category_id = 0;\r
+}\r
+\r
+CMemCluster::~CMemCluster()\r
+{\r
+}\r
+\r
+bool CMemCluster::IsUsed(void)\r
+{\r
+       return (m_consumers.size() > 0);\r
+}\r
+\r
+bool CMemCluster::IsUsedBy(std::string app_id)\r
+{\r
+       CConsumerContainer *cc = CConsumerContainer::getInstance();\r
+       CConsumer *c = NULL;\r
+       bool result = false;\r
+\r
+       if (m_consumers.size() == 0)\r
+               return false;\r
+\r
+       for (auto it : m_consumers) {\r
+               c = cc->findConsumer(it.first);\r
+               if (!c)\r
+                       continue;\r
+               if (!c->GetAppID().compare(app_id)) {\r
+                       SERVER_INFO("mc(%d) is used by (%s)", m_id, app_id.c_str());\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+bool CMemCluster::IsSharable(int device_id)\r
+{\r
+       if (m_consumers.size() == 0)\r
+               return true;\r
+\r
+       for (auto it : m_consumers) {\r
+               auto it_dev_id = it.second.find(device_id);\r
+               if (it_dev_id != it.second.end())\r
+                       return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void CMemCluster::AddConsumer(int consumer_id, int device_id, int category_class, int category_id)\r
+{\r
+       auto it = m_consumers.find(consumer_id);\r
+       if (it == m_consumers.end()) {\r
+               std::set<int> device_ids;\r
+               device_ids.insert(device_id);\r
+               m_consumers.insert(std::pair<int, std::set<int>>(consumer_id, device_ids));\r
+               m_category_class = category_class;\r
+               m_category_id = category_id;\r
+       } else {\r
+               std::set<int> &pdevice_ids = it->second;\r
+               pdevice_ids.insert(device_id);\r
+       }\r
+}\r
+\r
+void CMemCluster::RemoveConsumer(int consumer_id, int device_id)\r
+{\r
+       auto it = m_consumers.find(consumer_id);\r
+       if (it == m_consumers.end())\r
+               return;\r
+\r
+       std::set<int> &device_ids = it->second;\r
+\r
+       auto id_it = device_ids.find(device_id);\r
+       if (id_it == device_ids.end())\r
+               return;\r
+\r
+       device_ids.erase(device_id);\r
+       if (device_ids.empty())\r
+               m_consumers.erase(consumer_id);\r
+\r
+       if (m_consumers.empty()) {\r
+               m_category_class = 0;\r
+               m_category_id = 0;\r
+       }\r
+}\r
+\r
+std::set<int> CMemCluster::GetConsumers(void)\r
+{\r
+       std::set<int> consumers;\r
+\r
+       for (auto it : m_consumers)\r
+               consumers.insert(it.first);\r
+\r
+       return consumers;\r
+}\r
+\r
+void CMemCluster::ClearConsumers(void)\r
+{\r
+       for (auto &it : m_consumers) {\r
+               std::set<int> &id_it = it.second;\r
+               id_it.clear();\r
+       }\r
+       m_consumers.clear();\r
+}\r
+\r
+std::set<int> CMemCluster::GetAssignedDeviceId(int consumer_id)\r
+{\r
+       std::set<int> device_ids;\r
+       auto it = m_consumers.find(consumer_id);\r
+\r
+       if (it == m_consumers.end())\r
+               return device_ids;\r
+\r
+       device_ids.insert(it->second.begin(), it->second.end());\r
+\r
+       return device_ids;\r
+}\r
diff --git a/src/manager/dependence/CMixingMode.cpp b/src/manager/dependence/CMixingMode.cpp
new file mode 100644 (file)
index 0000000..131bd5e
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <rms_debug.h>\r
+#include <CMixingMode.h>\r
+\r
+int CMixingMode::AddConsumer(int device_id, int consumer_id)\r
+{\r
+       auto it = m_consumers.find(device_id);\r
+\r
+       if (it != m_consumers.end()) {\r
+               SERVER_ERR("already registered device(%d) by (%d)", device_id, it->second);\r
+               return m_consumers.size();\r
+       }\r
+\r
+       SERVER_INFO("add consumer(%d:%d) to mode(%d)", consumer_id, device_id, m_mode);\r
+       m_consumers.insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+       return m_consumers.size();\r
+}\r
+\r
+int CMixingMode::RemoveConsumer(int device_id, int consumer_id)\r
+{\r
+       auto it = m_consumers.find(device_id);\r
+\r
+       if (it == m_consumers.end())\r
+               return m_consumers.size();\r
+\r
+       SERVER_INFO("remove consumer(%d:%d) from mode(%d)", consumer_id, device_id, m_mode);\r
+\r
+       m_consumers.erase(device_id);\r
+\r
+       return m_consumers.size();\r
+}\r
+\r
diff --git a/src/manager/strategy/CAllocateModeStrategyProvider.cpp b/src/manager/strategy/CAllocateModeStrategyProvider.cpp
new file mode 100644 (file)
index 0000000..9a715a3
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+\r
+#include <CAllocateModeStrategy.h>\r
+#include <CNormalModeStrategy.h>\r
+#include <CInvalidModeStrategy.h>\r
+#include <CPreferenceModeStrategy.h>\r
+#include <CAllocateModeStrategyProvider.h>\r
+\r
+enum {\r
+       INIT_MODE = -1,\r
+       NORMAL_MODE,\r
+       PREFERENCE_MODE,\r
+       INVALID_MODE\r
+};\r
+\r
+CAllocateModeStrategyProvider *CAllocateModeStrategyProvider::m_instance = NULL;\r
+\r
+CAllocateModeStrategyProvider::CAllocateModeStrategyProvider()\r
+{\r
+}\r
+\r
+CAllocateModeStrategyProvider::~CAllocateModeStrategyProvider()\r
+{\r
+}\r
+\r
+\r
+CAllocateModeStrategyProvider *CAllocateModeStrategyProvider::getInstance()\r
+{\r
+       if (!m_instance)\r
+               m_instance = new CAllocateModeStrategyProvider();\r
+\r
+       return m_instance;\r
+}\r
+\r
+int CAllocateModeStrategyProvider::getAllocateMode(rms_msg_request *req)\r
+{\r
+       int mode = INIT_MODE;\r
+\r
+       for (int i = 0; i < req->request_num; i++) {\r
+               if (req->state[i] == RMS_STATE_EXCLUSIVE_PREFERENCE) {\r
+                       if (mode == INIT_MODE) {\r
+                               mode = PREFERENCE_MODE;\r
+                       } else if (mode == NORMAL_MODE) {\r
+                               mode = INVALID_MODE;\r
+                               break;\r
+                       }\r
+               } else {\r
+                       if (mode == INIT_MODE) {\r
+                               mode = NORMAL_MODE;\r
+                       } else if (mode == PREFERENCE_MODE) {\r
+                               mode = INVALID_MODE;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return mode;\r
+}\r
+\r
+CAllocateModeStrategy *CAllocateModeStrategyProvider::GetStrategy(rms_msg_request *req)\r
+{\r
+       CAllocateModeStrategy *strategy = NULL;\r
+\r
+       switch (getAllocateMode(req)) {\r
+               case NORMAL_MODE:\r
+                       strategy = new CNormalModeStrategy();\r
+                       break;\r
+               case PREFERENCE_MODE:\r
+                       strategy = new CPreferenceModeStrategy();\r
+                       break;\r
+               default:\r
+                       strategy = new CInvalidModeStrategy();\r
+                       break;\r
+       }\r
+\r
+       return strategy;\r
+}\r
diff --git a/src/manager/strategy/CAllocateStrategy.cpp b/src/manager/strategy/CAllocateStrategy.cpp
new file mode 100644 (file)
index 0000000..621605b
--- /dev/null
@@ -0,0 +1,151 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+#include <map>\r
+#include <algorithm>\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CResourceDB.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CAllocateStrategy.h>\r
+\r
+void CAllocateStrategy::ExcludeResources(std::map<int, CVirtualResource*> vresources, std::map<int, CVirtualResource*>* filtered_resources, CRequest *req)\r
+{\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (req->IsMainDeviceRequest() && !vresource->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && vresource->IsMainDevice())\r
+                       continue;\r
+               if (req->IsAIDeviceRequest() && !vresource->IsAIDevice())\r
+                       continue;\r
+               if (req->IsRequestByDevice() && resource->GetDeviceID() != req->GetDevice())\r
+                       continue;\r
+               if (req->GetState() == RMS_STATE_SHARABLE && !resource->IsSharableDevice())\r
+                       continue;\r
+               if (req->GetState() != RMS_STATE_SHARABLE && resource->IsSharableDevice())\r
+                       continue;\r
+\r
+               filtered_resources->insert(std::pair<int, CVirtualResource*>(it.first, it.second));\r
+       }\r
+}\r
+\r
+void CAllocateStrategy::ExcludeResources(std::multimap<unsigned long, CVirtualResource*> vresources, std::multimap<unsigned long, CVirtualResource*>* filtered_resources, CRequest *req)\r
+{\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+\r
+               if (req->IsMainDeviceRequest() && !vresource->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && vresource->IsMainDevice())\r
+                       continue;\r
+               if (req->IsAIDeviceRequest() && !vresource->IsAIDevice())\r
+                       continue;\r
+\r
+               filtered_resources->insert(std::pair<unsigned long, CVirtualResource*>(it.first, it.second));\r
+       }\r
+}\r
+\r
+void CAllocateStrategy::updateReasonByResourceState(int device_id, CRequest *req)\r
+{\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       bool low_priority_consumer_using = (CPriority::compareCurConsumers(device_id, req->getRequester()->getHandle()) == HIGH_PRIORITY);\r
+\r
+       if (low_priority_consumer_using) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               SERVER_INFO("RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER");\r
+       } else {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               SERVER_INFO("RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS");\r
+       }\r
+}\r
+\r
+void CAllocateStrategy::updateReasonBySharableCount(int device_id, CRequest *req)\r
+{\r
+       if (req->GetState() != RMS_STATE_SHARABLE)\r
+               return;\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       bool low_priority_consumer_using = (CPriority::compareCurConsumers(device_id, req->getRequester()->getHandle()) == HIGH_PRIORITY);\r
+\r
+       if (low_priority_consumer_using)\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+       else\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+int CAllocateStrategy::GetReclaimedBW(std::multimap<int, int> *retirables)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       std::set<int> rsc_ids;\r
+       int bw = 0;\r
+\r
+       ExcludeDuplicatedNDecoders(retirables, &rsc_ids);\r
+\r
+       for (auto const &it : rsc_ids) {\r
+               CResource *rsc = db->FindResource(it);\r
+               if (!rsc)\r
+                       continue;\r
+               bw += rsc->GetBW();\r
+       }\r
+\r
+       //SERVER_INFO("reclaimed bw(%d) from (%d)", bw, retirables->size());\r
+       return bw;\r
+}\r
+\r
+void CAllocateStrategy::ExcludeDuplicatedNDecoders(std::multimap<int, int> *retirables, std::set<int> *excluded)\r
+{\r
+       assert(retirables);\r
+       assert(excluded);\r
+       std::map<int, int> rscs_by_category; //category id, device_id\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto &it : *retirables) {\r
+               CResource *rsc = db->FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+               if (rsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) {\r
+                       //SERVER_INFO("insert (%d:%d)", rsc->GetCurCategory(), it.first);\r
+                       rscs_by_category.insert(std::pair<int, int>(rsc->GetCurCategory(), it.first));\r
+               } else {\r
+                       //SERVER_INFO("insert (%d)", it.first);\r
+                       excluded->insert(it.first);\r
+               }\r
+       }\r
+\r
+       for (auto &itn : rscs_by_category) {\r
+               //SERVER_INFO("insert (%d)", itn.second);\r
+               excluded->insert(itn.second);\r
+       }\r
+}\r
diff --git a/src/manager/strategy/CAllocateStrategyProvider.cpp b/src/manager/strategy/CAllocateStrategyProvider.cpp
new file mode 100644 (file)
index 0000000..840a8a2
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include <rms_debug.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CNormalStrategy.h>\r
+#include <CAudioDecoderStrategy.h>\r
+#include <CNDecodingVideoDecoderStrategy.h>\r
+#include <CVideoDecoderStrategy.h>\r
+#include <CScalerStrategy.h>\r
+#include <CExclusiveStrategy.h>\r
+#include <CAllocateStrategyProvider.h>\r
+#include <CVideoEncoderExclusiveStrategy.h>\r
+\r
+CAllocateStrategyProvider *CAllocateStrategyProvider::m_instance = NULL;\r
+\r
+CAllocateStrategyProvider::CAllocateStrategyProvider()\r
+{\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsAudioDecoderCategory(rms_rsc_category_e category)\r
+{\r
+       bool result = false;\r
+\r
+       switch (category) {\r
+               case RMS_CATEGORY_AUDIO_DECODER:\r
+               case RMS_CATEGORY_AUDIO_DECODER_SUB:\r
+               case RMS_CATEGORY_AUDIO_DECODER_PRIMARY:\r
+               case RMS_CATEGORY_AUDIO_DECODER_ANY:\r
+                       result = true;\r
+                       break;\r
+               default:\r
+                       result = false;\r
+                       break;\r
+       }\r
+\r
+       if (category > RMS_CATEGORY_AUDIO_DECODER_OPTION && category < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)\r
+               result = true;\r
+\r
+       return result;\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsVideoDecoderCategory(rms_rsc_category_e category)\r
+{\r
+       bool result = false;\r
+\r
+       switch (category) {\r
+               case RMS_CATEGORY_VIDEO_DECODER:\r
+               case RMS_CATEGORY_VIDEO_DECODER_SUB:\r
+               case RMS_CATEGORY_JPEG_DECODER:\r
+               case RMS_CATEGORY_MJPEG_DECODER:\r
+               case RMS_CATEGORY_JPEG_DECODER_FHD:\r
+               case RMS_CATEGORY_JPEG_DECODER_UHD:\r
+               case RMS_CATEGORY_JPEG_DECODER_8K:\r
+               case RMS_CATEGORY_MJPEG_DECODER_FHD:\r
+               case RMS_CATEGORY_MJPEG_DECODER_UHD:\r
+               case RMS_CATEGORY_MJPEG_DECODER_8K:\r
+               case RMS_CATEGORY_HEIC_DECODER:\r
+                       result = true;\r
+                       break;\r
+               default:\r
+                       result = false;\r
+                       break;\r
+       }\r
+\r
+       if (category > RMS_CATEGORY_VIDEO_DECODER_OPTION && category < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)\r
+               result = true;\r
+\r
+       return result;\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsNDecordingVideoDecoderCategory(int category_class)\r
+{\r
+       return (category_class == RMS_CATEGORY_CLASS_N_DECODING);\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsBGScalerCategory(rms_rsc_category_e category)\r
+{\r
+       return (category == RMS_CATEGORY_SCALER_BG);\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsMultiviewScalerCategory(rms_rsc_category_e category)\r
+{\r
+       return (category == RMS_CATEGORY_SCALER_MULTIVIEW || category == RMS_CATEGORY_SCALER_INTERLACED);\r
+}\r
+\r
+bool CAllocateStrategyProvider::IsSubScalerCategory(rms_rsc_category_e category)\r
+{\r
+       bool result = false;\r
+\r
+       switch (category) {\r
+               case RMS_CATEGORY_SCALER_SUB:\r
+               case RMS_CATEGORY_SCALER_SUB2:\r
+               case RMS_CATEGORY_SCALER_SUB3:\r
+                       result = true;\r
+                       break;\r
+               default:\r
+                       result = false;\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+CAllocateStrategyProvider *CAllocateStrategyProvider::getInstance()\r
+{\r
+       if (!m_instance)\r
+               m_instance = new CAllocateStrategyProvider();\r
+\r
+       return m_instance;\r
+}\r
+\r
+CAllocateStrategyProvider::~CAllocateStrategyProvider()\r
+{\r
+}\r
+\r
+CAllocateStrategy *CAllocateStrategyProvider::GetStrategy(rms_rsc_category_e category, int category_class)\r
+{\r
+       CAllocateStrategy *strategy = NULL;\r
+\r
+       if (IsVideoDecoderCategory(category)) {\r
+               if (IsNDecordingVideoDecoderCategory(category_class))\r
+                       strategy = new CNDecodingVideoDecoderStrategy();\r
+               else\r
+                       strategy = new CVideoDecoderStrategy();\r
+       } else if (IsAudioDecoderCategory(category)) {\r
+               strategy = new CAudioDecoderStrategy();\r
+       } else if (IsBGScalerCategory(category) || IsSubScalerCategory(category)) {\r
+               strategy = new CExclusiveStrategy();\r
+       } else if (IsMultiviewScalerCategory(category)) {\r
+               strategy = new CScalerStrategy();\r
+       } else if (category == RMS_CATEGORY_VIDEO_ENCODER_EXCLUSIVE) {\r
+               strategy = new CVideoEncoderExclusiveStrategy();\r
+       } else {\r
+               strategy = new CNormalStrategy();\r
+       }\r
+\r
+       return strategy;\r
+}\r
diff --git a/src/manager/strategy/CAudioDecoderStrategy.cpp b/src/manager/strategy/CAudioDecoderStrategy.cpp
new file mode 100644 (file)
index 0000000..984ad8e
--- /dev/null
@@ -0,0 +1,146 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <map>\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CAudioDecoderStrategy.h>\r
+#include <CMixingStrategy.h>\r
+#include <CDependencyController.h>\r
+#include <CSysInfo.h>\r
+\r
+CVirtualResource *CAudioDecoderStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource*> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       CRequester *requester = req->getRequester();\r
+       CMixingStrategy *strategy = CMixingStrategy::getInstance();\r
+       bool mixing_supported = CSysInfo::GetInstance()->IsAudioMixingSupported();\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               int device_id = resource->GetDeviceID();\r
+\r
+               SERVER_INFO("vresource id(%d), codec(%s)", vresource->GetVResourceID(), vresource->GetAudioCodec().c_str());\r
+\r
+               rms_error_type_e reason = RMS_ERR_TYPE_NONE;\r
+\r
+               if (mixing_supported) {\r
+                       if (!strategy->isAvailableMixingMode(req->GetMixingMode())) {\r
+                               strategy->updateReasonByMixingMode(vresource, req, reason);\r
+                               continue;\r
+                       }\r
+\r
+                       if (!strategy->isAvailableAudioCodec(vresource->GetAudioCodec(), requester->getHandle(), &reason)) {\r
+                               strategy->updateReasonByAudioCodec(vresource, req, reason);\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               if (resource->IsReserved())\r
+                       continue;\r
+\r
+               if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+                       updateReasonByResourceState(device_id, req);\r
+                       continue;\r
+               }\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CAudioDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateAudioCodec(vrsc->GetAudioCodec());\r
+       rsc->updateMixingMode(req->GetMixingMode());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CAudioDecoderStrategy::GetRetirableConsumers(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CResource *resource = vresource->GetResource();\r
+       CRequester *requester = req->getRequester();\r
+       int cid = requester->getHandle();\r
+       rms_error_type_e err;\r
+\r
+       SERVER_INFO("vresource id(%d), codec(%s)", vresource->GetVResourceID(), vresource->GetAudioCodec().c_str());\r
+\r
+       if (CSysInfo::GetInstance()->IsAudioMixingSupported()) {\r
+               CMixingStrategy *strategy = CMixingStrategy::getInstance();\r
+\r
+               if (!strategy->isAvailableAudioCodec(vresource->GetAudioCodec(), requester->getHandle(), &err)) {\r
+                       if (strategy->getReclaimableAudioCodecConsumers(vresource->GetAudioCodec(), cid, req, retirables, err_type) != RMS_OK)\r
+                               goto error;\r
+               }\r
+\r
+               if (!strategy->isAvailableMixingMode(req->GetMixingMode())) {\r
+                       if (strategy->getReclaimableMixingModeConsumers(req->GetMixingMode(), cid, retirables, err_type) != RMS_OK)\r
+                               goto error;\r
+               }\r
+       }\r
+\r
+       if (!resource->IsFreeState()) {\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), cid, retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       return RMS_OK;\r
+\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+\r
+void CAudioDecoderStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::map<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+\r
+               if (GetRetirableConsumers(vresource, req, retirables, err_type) == RMS_OK)\r
+                       break;\r
+       }\r
+\r
+       for (auto const &it : consumer_list) {\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
diff --git a/src/manager/strategy/CExclusiveStrategy.cpp b/src/manager/strategy/CExclusiveStrategy.cpp
new file mode 100644 (file)
index 0000000..04f9f97
--- /dev/null
@@ -0,0 +1,249 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CResourceDB.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CDependencyController.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CExclusiveStrategy.h>\r
+\r
+void CExclusiveStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+bool CExclusiveStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CResource *resource = vresource->GetResource();\r
+\r
+       if (resource->IsReserved()) {\r
+               SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID());\r
+               return false;\r
+       }\r
+\r
+       if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+               updateReasonByMemCluster(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+               updateReasonByResourceState(resource->GetDeviceID(), req);\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CExclusiveStrategy::isSharableResource(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CResource *resource = vresource->GetResource();\r
+\r
+       if (resource->IsReserved()) {\r
+               SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID());\r
+               return false;\r
+       }\r
+\r
+       if (resource->getSharableCount() <= 0) {\r
+               SERVER_INFO("device id(%d) is not sharable state", resource->GetDeviceID());\r
+               updateReasonBySharableCount(resource->GetDeviceID(), req);\r
+               return false;\r
+       }\r
+\r
+       if (!CDependencyController::getInstance()->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID())) {\r
+               updateReasonByMemCluster(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+               updateReasonByResourceState(resource->GetDeviceID(), req);\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+CVirtualResource *CExclusiveStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource *> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               bool isReservable = (req->GetState() == RMS_STATE_SHARABLE) ? isSharableResource(vresource, req) : isAllocatableResource(vresource, req);\r
+\r
+               SERVER_INFO("is Reservable ? %d", isReservable);\r
+\r
+               if (!isReservable)\r
+                       continue;\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CExclusiveStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CExclusiveStrategy::ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters()))\r
+                       continue;\r
+\r
+               if (!resource->IsFreeState())\r
+                       continue;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+bool CExclusiveStrategy::ContainSharableResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (!dc->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID()))\r
+                       continue;\r
+\r
+               if (!resource->IsSharableState())\r
+                       continue;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+int CExclusiveStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CResource *resource = vresource->GetResource();\r
+\r
+       if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+               if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource->IsFreeState()) {\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       return RMS_OK;\r
+\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+int CExclusiveStrategy::getRetirableConsumersShare(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CResource *resource = vresource->GetResource();\r
+\r
+       if (!dc->isSharableMemClusters(vresource->GetMemClusters(), resource->GetDeviceID())) {\r
+               if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource->IsSharableState()) {\r
+               if (CPriority::getReclaimableConsumersShare(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       return RMS_OK;\r
+\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+\r
+void CExclusiveStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       bool isShareMode = (req->GetState() == RMS_STATE_SHARABLE);\r
+       bool hasAllocatableResource = (isShareMode) ? ContainSharableResource(filtered_vresources) : ContainAvailableResource(filtered_vresources);\r
+\r
+       if (hasAllocatableResource)\r
+               return;\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+\r
+               int result = (isShareMode) ? getRetirableConsumersShare(vresource, req, &consumer_list, err_type) : getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type);\r
+\r
+               if (result == RMS_OK)\r
+                       break;\r
+       }\r
+\r
+       for (auto const &it : consumer_list) {\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
diff --git a/src/manager/strategy/CInvalidModeStrategy.cpp b/src/manager/strategy/CInvalidModeStrategy.cpp
new file mode 100644 (file)
index 0000000..f314e48
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+#include <algorithm>\r
+#include <vector>\r
+#include <rms_debug.h>\r
+#include <rms_type.h>\r
+#include <CRequest.h>\r
+#include <CAllocateModeStrategy.h>\r
+#include <CInvalidModeStrategy.h>\r
+\r
+CInvalidModeStrategy::CInvalidModeStrategy()\r
+{\r
+}\r
+\r
+CInvalidModeStrategy::~CInvalidModeStrategy()\r
+{\r
+}\r
+\r
+bool CInvalidModeStrategy::CanAllocateResources(std::vector<CRequest *> requests, rms_allocate_result_s *result)\r
+{\r
+       result->result = RMS_ERROR;\r
+       result->reason = RMS_ERR_TYPE_INVALID_REQUEST;\r
+\r
+       SERVER_ERR("Invalid request set");\r
+       std::for_each(requests.begin(), requests.end(), [](CRequest *req) { SERVER_ERR("req state(%d)", req->GetState()); });\r
+\r
+       return false;\r
+}\r
+\r
+void CInvalidModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices)\r
+{\r
+       assert(allocated_devices);\r
+\r
+       allocated_devices->result = RMS_ERROR;\r
+       allocated_devices->error_type = RMS_ERR_TYPE_INVALID_REQUEST;\r
+       allocated_devices->resources_num = 0;\r
+}\r
diff --git a/src/manager/strategy/CMixingStrategy.cpp b/src/manager/strategy/CMixingStrategy.cpp
new file mode 100644 (file)
index 0000000..db58961
--- /dev/null
@@ -0,0 +1,267 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+#include <CVirtualResource.h>\r
+#include <CConsumer.h>\r
+#include <CResourceManager.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CMixingMode.h>\r
+#include <CResourceObserver.h>\r
+#include <CDependencyController.h>\r
+#include <CPriority.h>\r
+#include <CAudioCodec.h>\r
+#include <CAudioCodecCollection.h>\r
+#include <CMixingStrategy.h>\r
+\r
+CMixingStrategy *CMixingStrategy::m_instance = NULL;\r
+\r
+CMixingStrategy *CMixingStrategy::getInstance(void)\r
+{\r
+       if (!m_instance)\r
+               m_instance = new CMixingStrategy();\r
+\r
+       return m_instance;\r
+}\r
+\r
+bool CMixingStrategy::isAvailableAudioCodec(std::string name, int consumer_id, rms_error_type_e *reason)\r
+{\r
+       CAudioCodec *audio_codec = CAudioCodecCollection::getInstance()->findAudioCodec(name.c_str());\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+\r
+       if (!audio_codec) {\r
+               SERVER_ERR("not existing audio codec (%s)", name.c_str());\r
+               *reason = RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST;\r
+               return false;\r
+       }\r
+\r
+       if (!audio_codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) {\r
+               SERVER_ERR("mixing not supported (%s)", name.c_str());\r
+               return false;\r
+       }\r
+\r
+       if (!dc->isAvailableAudioCodec(name)) {\r
+               SERVER_ERR("not available audio codec (%s)", name.c_str());\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+int CMixingStrategy::getReclaimableAudioCodecConsumers(std::string codec_name, int consumer_id, CRequest *req, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name);\r
+\r
+       if (!codec)\r
+               return RMS_ERROR;\r
+\r
+       std::map<unsigned long, std::pair<int, int>> acodec_consumers = dc->getAudioCodecConsumers();\r
+\r
+       if (!codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) {\r
+               for (auto const &it : acodec_consumers) {\r
+                       if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, err_type))\r
+                               return RMS_ERROR;\r
+\r
+                       reclaimables->insert(std::pair<int, int>(it.second.first, it.second.second));\r
+               }\r
+\r
+               return RMS_OK;\r
+       }\r
+\r
+       if (!dc->isAvailableAudioCodec(codec_name)) {\r
+               for (auto const &it : acodec_consumers) {\r
+                       CResource *rsc = CResourceDB::getInstance()->FindResource(it.second.first);\r
+                       if (req->IsMainDeviceRequest() && !rsc->IsMainDevice())\r
+                               continue;\r
+                       if (req->IsSubDeviceRequest() && rsc->IsMainDevice())\r
+                               continue;\r
+                       if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, err_type))\r
+                               continue;\r
+\r
+                       reclaimables->insert(std::pair<int, int>(it.second.first, it.second.second));\r
+                       return RMS_OK;\r
+               }\r
+       }\r
+\r
+       return RMS_ERROR;\r
+\r
+}\r
+\r
+bool CMixingStrategy::isAvailableMixingMode(rms_mixing_mode_e mode)\r
+{\r
+       CMixingMode *cur_mode = CDependencyController::getInstance()->getCurMixingMode();\r
+\r
+       if (!cur_mode)\r
+               return true;\r
+\r
+       SERVER_INFO("cur_mode(%d)/requested(%d)", cur_mode->getMode(), mode);\r
+\r
+       return (mode == cur_mode->getMode());\r
+}\r
+\r
+int CMixingStrategy::getReclaimableMixingModeConsumers(rms_mixing_mode_e mode, int consumer_id, std::multimap<int, int>* reclaimables, rms_error_type_e *err_type)\r
+{\r
+       CMixingMode *cur_mode = CDependencyController::getInstance()->getCurMixingMode();\r
+\r
+       if (!cur_mode) {\r
+               SERVER_ERR("there is no mixing mode to reclaim");\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       SERVER_INFO("cur mixing mode (%d), requested codec (%d)", cur_mode->getMode(), mode);\r
+\r
+       std::map<int, int> consumers = cur_mode->GetConsumers();\r
+\r
+       if (consumers.size() == 0) {\r
+               SERVER_ERR("no consumer to reclaim in mixing mode(%d)", cur_mode->getMode());\r
+               return RMS_ERROR;\r
+       }\r
+\r
+       for (auto const &it_consumer : consumers) {\r
+               if (!CPriority::isReclaimableConsumer(it_consumer.second, consumer_id, err_type))\r
+                       return RMS_ERROR;\r
+\r
+               reclaimables->insert(std::pair<int, int>(it_consumer.first, it_consumer.second));\r
+       }\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CMixingStrategy::canReclaimMixingMode(rms_mixing_mode_e mode, CMixingMode *cur_mode, int consumer_id)\r
+{\r
+       std::map<int, int> consumers = cur_mode->GetConsumers();\r
+\r
+       if (consumers.size() == 0) {\r
+               SERVER_ERR("no consumer to reclaim in mixing mode(%d)", cur_mode->getMode());\r
+               return false;\r
+       }\r
+\r
+       for (auto const &it_consumer : consumers) {\r
+               if (!CPriority::isReclaimableConsumer(it_consumer.second, consumer_id, NULL))\r
+                       return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+bool CMixingStrategy::canReclaimMixingMode(rms_mixing_mode_e mode, int consumer_id)\r
+{\r
+       CMixingMode *mixing_mode = CDependencyController::getInstance()->getCurMixingMode();\r
+\r
+       return (mixing_mode != NULL) ? canReclaimMixingMode(mode, mixing_mode, consumer_id) : false;\r
+}\r
+\r
+void CMixingStrategy::updateReasonByMixingMode(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (!needReclaimCheck(cur_reason)) {\r
+               req->SetReason(cur_reason);\r
+               return;\r
+       }\r
+\r
+       if (canReclaimMixingMode(req->GetMixingMode(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+\r
+}\r
+\r
+void CMixingStrategy::updateReasonByAudioCodec(CVirtualResource *vresource, CRequest *req, rms_error_type_e cur_reason)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (!needReclaimCheck(cur_reason)) {\r
+               req->SetReason(cur_reason);\r
+               return;\r
+       }\r
+\r
+       if (canReclaimAudioCodec(vresource->GetAudioCodec(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+bool CMixingStrategy::needReclaimCheck(rms_error_type_e reason)\r
+{\r
+       bool result = false;\r
+\r
+       switch (reason) {\r
+               case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER:\r
+               case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST:\r
+                       SERVER_ERR("erro case : %d", reason);\r
+                       result = false;\r
+                       break;\r
+               default:\r
+                       result = true;\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+bool CMixingStrategy::canReclaimAudioCodec(std::string codec_name, int consumer_id)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CAudioCodec *codec = CAudioCodecCollection::getInstance()->findAudioCodec(codec_name);\r
+\r
+       if (!codec)\r
+               return false;\r
+\r
+       std::map<unsigned long, std::pair<int, int>> acodec_consumers = dc->getAudioCodecConsumers();\r
+       rms_error_type_e err_type;\r
+\r
+       if (!codec->isMixingSupported() && dc->isAudioCodecBeingUsed()) {\r
+               for (auto const &it : acodec_consumers)\r
+               {\r
+                       if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, &err_type))\r
+                               return false;\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+       if (!dc->isAvailableAudioCodec(codec_name)) {\r
+               for (auto const &it : acodec_consumers) {\r
+                       if (!CPriority::isReclaimableConsumer(it.second.second, consumer_id, &err_type))\r
+                               continue;\r
+\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       return false;\r
+\r
+}\r
diff --git a/src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp b/src/manager/strategy/CNDecodingVideoDecoderStrategy.cpp
new file mode 100644 (file)
index 0000000..6291dc6
--- /dev/null
@@ -0,0 +1,448 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CResourceDB.h>\r
+#include <CBandwidth.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CDependencyController.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CNDecodingVideoDecoderStrategy.h>\r
+\r
+void CNDecodingVideoDecoderStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+void CNDecodingVideoDecoderStrategy::updateReasonByBW(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       rms_error_type_e reason = canReclaimRequiredBW(req, vresource->GetBW()) ?\r
+                                                               RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS;\r
+       req->SetReason(reason);\r
+}\r
+\r
+void CNDecodingVideoDecoderStrategy::updateReasonByTripleDecoding(CRequest *req)\r
+{\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       rms_error_type_e reason = canReclaimActiveVideoDecoders(req) ?\r
+                                                               RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS;\r
+       req->SetReason(reason);\r
+}\r
+\r
+bool CNDecodingVideoDecoderStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       int category_class = vresource->GetCategoryClass();\r
+       CResource *resource = vresource->GetResource();\r
+\r
+       if (resource->IsReserved()) {\r
+               SERVER_INFO("device id(%d) is reserved state", resource->GetDeviceID());\r
+               return false;\r
+       }\r
+\r
+       if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType())) {\r
+               updateReasonByMemCluster(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+       if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && (vresource->GetBW() > bandwidth->GetAvail())) {\r
+               SERVER_INFO("insufficient BW required(%d)/avail(%d)", vresource->GetBW(), bandwidth->GetAvail());\r
+               updateReasonByBW(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+               updateReasonByResourceState(resource->GetDeviceID(), req);\r
+               return false;\r
+       }\r
+\r
+       if (!CResourceDB::getInstance()->HasAvailableDecoderNDecoding()) {\r
+               updateReasonByTripleDecoding(req);\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+CVirtualResource *CNDecodingVideoDecoderStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource *> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               if (!isAllocatableResource(vresource, req))\r
+                       continue;\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CNDecodingVideoDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CNDecodingVideoDecoderStrategy::ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               int category_class = vresource->GetCategoryClass();\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType()))\r
+                       continue;\r
+\r
+               if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && (bandwidth->GetAvail() < vresource->GetBW()))\r
+                       continue;\r
+\r
+               if (!resource->IsFreeState())\r
+                       continue;\r
+\r
+               if (!CResourceDB::getInstance()->HasAvailableDecoderNDecoding())\r
+                       continue;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+int CNDecodingVideoDecoderStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CResource *resource = vresource->GetResource();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+       int requester_id = req->getRequester()->getHandle();\r
+       int category_class = vresource->GetCategoryClass();\r
+\r
+       if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), category_class, vresource->GetCategoryType())) {\r
+               if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), requester_id, retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if ((bandwidth->GetNConsumersNDec(vresource->GetCategoryType()) == 0) && ((bandwidth->GetAvail() + GetReclaimedBW(retirables)) < vresource->GetBW())) {\r
+               if (GetConsumerUsingBW(req, vresource->GetBW(), retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource->IsFreeState()) {\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), requester_id, retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource_db->HasAvailableDecoderNDecoding(*retirables)) {\r
+               if (GetReclaimableVideoDecoderConsumers(requester_id, retirables, req, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       return RMS_OK;\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+void CNDecodingVideoDecoderStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+       bool included = false;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       if (ContainAvailableResource(filtered_vresources))\r
+               return;\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               included = false;\r
+               CResource *rsc = vresource->GetResource();\r
+               SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), rsc->GetDeviceID());\r
+               if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK) {\r
+                       for (auto const &it_c : consumer_list) {\r
+                               auto it_r = retirables->find(it_c.first);\r
+                               if (it_r != retirables->end()) {\r
+                                       included = true;\r
+                                       SERVER_INFO("(%d:%d) is already in the list", it_c.first, it_c.second);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if (included)\r
+                               continue;\r
+\r
+                       break;\r
+               }\r
+       }\r
+\r
+       retirables->insert(consumer_list.begin(), consumer_list.end());\r
+}\r
+\r
+bool CNDecodingVideoDecoderStrategy::canReclaimRequiredBW(CRequest *req, unsigned int bw)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+       unsigned int check_available = bandwidth->GetAvail();\r
+       std::map<int, int> bw_consumers = bandwidth->GetConsumers();\r
+\r
+       for (std::map<int, int>::iterator it = bw_consumers.begin(); it != bw_consumers.end(); it++) {\r
+               int device_id = (*it).first;\r
+               int consumer_id = (*it).second;\r
+\r
+               CResource *pRsc = resource_db->FindResource(device_id);\r
+\r
+               if (!pRsc) {\r
+                       SERVER_ERR("cannot find resource using device id");\r
+                       continue;\r
+               }\r
+\r
+               if (requester->getHandle() == consumer_id) {\r
+                       SERVER_INFO("CID[%d] is using BW (%d)", requester->getHandle(), pRsc->GetBW());\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(consumer_id, requester->getHandle()) != HIGH_PRIORITY)\r
+                       continue;\r
+\r
+               check_available += pRsc->GetBW();\r
+\r
+               if (bw <= check_available)\r
+                       break;\r
+\r
+               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);   \r
+\r
+       }\r
+\r
+       SERVER_INFO("required BW(%d) - available (%d)", bw, check_available);\r
+\r
+       return (bw <= check_available);\r
+}\r
+\r
+void CNDecodingVideoDecoderStrategy::SelectDevicesByMainSub(CRequest *req, std::map<int, int> *src, std::map<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto const &it : *src) {\r
+               CResource *rsc = db->FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+               if (req->IsMainDeviceRequest() && !rsc->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && rsc->IsMainDevice())\r
+                       continue;\r
+\r
+               result->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
+\r
+int CNDecodingVideoDecoderStrategy::GetConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap<int, int>* return_ids)\r
+{\r
+       std::map<int, int> candidates;\r
+       std::map<int, int> cur_consumers = CBandwidth::GetInstance()->GetConsumers(); //device id, consumer id\r
+\r
+       SelectDevicesByMainSub(req, &cur_consumers, &candidates);\r
+\r
+       std::multimap<int, int> reclaimed_by_ms;\r
+       unsigned int avail_bw = GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, candidates, &reclaimed_by_ms);\r
+\r
+       if (avail_bw >= bw) {\r
+               return_ids->insert(reclaimed_by_ms.begin(), reclaimed_by_ms.end());\r
+               return RMS_OK;\r
+       }\r
+\r
+       std::multimap<int, int> reclaimed_by_t;\r
+       GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, cur_consumers, &reclaimed_by_t);\r
+       return_ids->insert(reclaimed_by_t.begin(), reclaimed_by_t.end());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CNDecodingVideoDecoderStrategy::GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map<int, int> bw_consumers, std::multimap<int, int>* reclaimed_consumers)\r
+{\r
+       assert(reclaimed_consumers);\r
+\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       SERVER_INFO("candidates using BW : %zu", bw_consumers.size());\r
+       unsigned int reclaimed_bw = bandwidth->GetAvail();\r
+\r
+       std::map<unsigned long, int> consumers_by_t;\r
+       for (auto const &itc : bw_consumers) {\r
+               CResource *rsc = resource_db->FindResource(itc.first);\r
+               if (!rsc)\r
+                       continue;\r
+\r
+               consumers_by_t.insert(std::pair<unsigned long, int>(rsc->GetAllocatedTime(), itc.first));\r
+       }\r
+\r
+       for (auto const &it : consumers_by_t) {\r
+               int device_id = it.second;\r
+               CResource *pRsc = resource_db->FindResource(device_id);\r
+               if (!pRsc)\r
+                       continue;\r
+\r
+               int consumer_id = pRsc->GetFirstConsumer();\r
+               SERVER_INFO("consumer (%d) is using bw for device (%d)", consumer_id, device_id);\r
+\r
+               if (requester_id == consumer_id) {\r
+                       SERVER_INFO("CID[%d] is using BW (%d)", requester_id, pRsc->GetBW());\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(consumer_id, requester_id) != HIGH_PRIORITY)\r
+                       continue;\r
+\r
+               auto ret = reclaimed_consumers->find(device_id);\r
+               if (ret != reclaimed_consumers->end()) {\r
+                       SERVER_INFO("(%d:%d) already inserted", device_id, consumer_id);\r
+                       continue;\r
+               }\r
+\r
+               reclaimed_consumers->insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+               if (pRsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) {\r
+                       std::map<int, int> siblings;\r
+                       bandwidth->GetConsumersNDec(pRsc->GetCurCategory(), &siblings);\r
+                       if (siblings.size() > 0) {\r
+                               SERVER_INFO("insert n-dec siblings(%zu)", siblings.size());\r
+                               reclaimed_consumers->insert(siblings.begin(), siblings.end());\r
+                       }\r
+               }\r
+\r
+               reclaimed_bw += pRsc->GetBW();\r
+\r
+               if (required_bw <= reclaimed_bw)\r
+                       break;\r
+               SERVER_INFO("DevID[%d]/ need more BW! required:(%d)-resource(%d)-reclaimed(%d)", pRsc->GetDeviceID(), required_bw, pRsc->GetBW(), reclaimed_bw);\r
+       }\r
+\r
+       return reclaimed_bw;\r
+}\r
+\r
+bool CNDecodingVideoDecoderStrategy::canReclaimActiveVideoDecoders(CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       std::map<int, int> active_vdecs = resource_db->GetActiveVideoDecoders();\r
+\r
+       for (auto const &it : active_vdecs) {\r
+               int dev_id = it.first;\r
+               int cid = it.second;\r
+\r
+               CResource *rsc = resource_db->FindResource(dev_id);\r
+\r
+               if (!rsc) {\r
+                       SERVER_ERR("can't find resource (%d)", dev_id);\r
+                       continue;\r
+               }\r
+\r
+               if (requester->getHandle() == cid) {\r
+                       SERVER_INFO("CID[%d] is using device (%d)", cid, dev_id);\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(cid, requester->getHandle()) == HIGH_PRIORITY)\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+\r
+}\r
+\r
+int CNDecodingVideoDecoderStrategy::GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap<int, int>* reclaimables, CRequest *req, rms_error_type_e *err_type)\r
+{\r
+       std::map<unsigned long, CResource*> rscs;\r
+       CResource *rsc = NULL;\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       std::map<int, int> active_vdecs = resource_db->GetActiveVideoDecoders();\r
+       bool has_main_vdec = false;\r
+       bool has_sub_vdec = false;\r
+\r
+       for (auto const &it_vdec : active_vdecs) {\r
+               rsc = resource_db->FindResource(it_vdec.first);\r
+               rscs.insert(std::pair<unsigned long, CResource*>(rsc->GetAllocatedTime(), rsc));\r
+\r
+               if (rsc->IsMainDevice())\r
+                       has_main_vdec = true;\r
+               else\r
+                       has_sub_vdec = true;\r
+       }\r
+\r
+       for (auto const &it : rscs)\r
+       {\r
+               rsc = it.second;\r
+\r
+               if (req->IsMainDeviceRequest() && has_main_vdec && !rsc->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && has_sub_vdec && rsc->IsMainDevice())\r
+                       continue;\r
+\r
+               if (CPriority::getReclaimableConsumers(rsc->GetDeviceID(), consumer_id, reclaimables, err_type) == RMS_OK)\r
+                       return RMS_OK;\r
+       }\r
+\r
+       return RMS_ERROR;\r
+}\r
diff --git a/src/manager/strategy/CNormalModeStrategy.cpp b/src/manager/strategy/CNormalModeStrategy.cpp
new file mode 100644 (file)
index 0000000..9295d02
--- /dev/null
@@ -0,0 +1,152 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+#include <algorithm>\r
+\r
+#include <rms_debug.h>\r
+#include <CRequest.h>\r
+#include <CResource.h>\r
+#include <CResourceDB.h>\r
+#include <CResourceCategory.h>\r
+#include <CAllocateModeStrategy.h>\r
+#include <CNormalModeStrategy.h>\r
+\r
+void ReserveCandidate(CRequest *req)\r
+{\r
+       CResourceCategory *resource_category = CResourceDB::getInstance()->FindResourceCategory(req->GetCategory());\r
+\r
+       req->SetResult(RMS_ERROR);\r
+\r
+       if (!resource_category) {\r
+               if (req->GetCategory() == RMS_CATEGORY_NOT_PERMITTED)\r
+                       req->SetReason(RMS_ERR_TYPE_NOT_PERMITTED);\r
+               else\r
+                       req->SetReason(RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST);\r
+\r
+               SERVER_ERR("not existing category(%d)! can't allocate a candidate", req->GetCategory());\r
+               return;\r
+       }\r
+\r
+       CResource *resource = resource_category->ReserveCandidate(req, true);\r
+\r
+       if (!resource)\r
+               return;\r
+\r
+       req->SetResult(RMS_OK);\r
+       req->SetCandidateDevice(resource->GetDeviceID());\r
+}\r
+\r
+void ReleaseReservedResources(CRequest *req)\r
+{\r
+       if (req->GetResult() != RMS_OK)\r
+               return;\r
+\r
+       CResource *resource = CResourceDB::getInstance()->FindResource(req->GetCandidateDevice());\r
+\r
+       resource->CancelReservation((rms_requests_resource_state_e) req->GetState());\r
+}\r
+\r
+rms_return_code_e ToAllocReturnCode(rms_error_type_e error_type)\r
+{\r
+       rms_return_code_e result = RMS_OK;\r
+\r
+       switch (error_type) {\r
+               case RMS_ERR_TYPE_NONE:\r
+                       result = RMS_OK;\r
+                       break;\r
+               case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER:\r
+                       result = RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER;\r
+                       break;\r
+               default:\r
+                       result = RMS_ERROR;\r
+                       break;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+\r
+CNormalModeStrategy::CNormalModeStrategy()\r
+{\r
+}\r
+\r
+CNormalModeStrategy::~CNormalModeStrategy()\r
+{\r
+}\r
+\r
+rms_error_type_e CNormalModeStrategy::GetCandidateFindResult(std::vector<CRequest *> requests)\r
+{\r
+       rms_error_type_e result = RMS_ERR_TYPE_NONE;\r
+\r
+       for (auto& it : requests) {\r
+               CRequest *request = it;\r
+\r
+               if (request->GetResult() == RMS_OK)\r
+                       continue;\r
+\r
+               if (request->GetReason() != RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+                       return request->GetReason();\r
+\r
+               result = RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+bool CNormalModeStrategy::CanAllocateResources(std::vector<CRequest*> requests, rms_allocate_result_s *result)\r
+{\r
+       std::for_each(requests.begin(), requests.end(), ReserveCandidate);\r
+\r
+       result->reason = GetCandidateFindResult(requests);\r
+       result->result = ToAllocReturnCode(result->reason);\r
+\r
+       std::for_each(requests.begin(), requests.end(), ReleaseReservedResources);\r
+\r
+       return (result->result == RMS_OK);\r
+}\r
+\r
+void CNormalModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices)\r
+{\r
+       assert(allocated_devices);\r
+\r
+       allocated_devices->result = alloc_result->result;\r
+       allocated_devices->error_type = alloc_result->reason;\r
+\r
+       if (alloc_result->result != RMS_OK) {\r
+               allocated_devices->resources_num = 0;\r
+               return;\r
+       }\r
+\r
+       allocated_devices->resources_num = requests.size();\r
+       allocated_devices->device_ids = (int*) calloc(requests.size(), sizeof(int));\r
+       assert(allocated_devices->device_ids);\r
+       allocated_devices->devices = (rms_return_device_info_s*) calloc(requests.size(), sizeof(rms_return_device_info_s));\r
+\r
+       int i = 0;\r
+\r
+       for (auto const &it : requests) {\r
+               allocated_devices->device_ids[i] = it->GetAllocatedVirtualDevice();\r
+               allocated_devices->devices[i].device_id = it->GetAllocatedVirtualDevice();\r
+               CResource *resource = CResourceDB::getInstance()->FindResource(it->GetAllocatedDevice());\r
+               assert(resource);\r
+\r
+               const char *path = resource->GetDevicePath();\r
+               allocated_devices->devices[i].device_path = strndup(path, strlen(path));\r
+               resource->SetAllocatedTime();\r
+               i++;\r
+       }\r
+}\r
diff --git a/src/manager/strategy/CNormalStrategy.cpp b/src/manager/strategy/CNormalStrategy.cpp
new file mode 100644 (file)
index 0000000..49846b1
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CResourceDB.h>\r
+#include <CRequest.h>\r
+#include <CPriority.h>\r
+#include <CRequester.h>\r
+#include <CNormalStrategy.h>\r
+\r
+CNormalStrategy::CNormalStrategy()\r
+{\r
+}\r
+\r
+CNormalStrategy::~CNormalStrategy()\r
+{\r
+}\r
+\r
+CVirtualResource *CNormalStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource *> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               int device_id = resource->GetDeviceID();\r
+\r
+               if (resource->IsReserved())\r
+                       continue;\r
+\r
+               if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+                       updateReasonByResourceState(device_id, req);\r
+                       continue;\r
+               }\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CNormalStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CNormalStrategy::ContainFreeResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (resource->IsFreeState())\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CNormalStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       if (ContainFreeResource(filtered_vresources))\r
+               return;\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), &consumer_list, err_type) == RMS_OK)\r
+                       break;\r
+       }\r
+\r
+       for (auto const &it : consumer_list) {\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
diff --git a/src/manager/strategy/CPreferenceModeStrategy.cpp b/src/manager/strategy/CPreferenceModeStrategy.cpp
new file mode 100644 (file)
index 0000000..9bebbe6
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+#include <algorithm>\r
+\r
+#include <rms_type.h>\r
+#include <rms_debug.h>\r
+\r
+#include <CRequest.h>\r
+#include <CResource.h>\r
+#include <CResourceDB.h>\r
+#include <CResourceCategory.h>\r
+#include <CAllocateModeStrategy.h>\r
+#include <CPreferenceModeStrategy.h>\r
+\r
+CPreferenceModeStrategy::CPreferenceModeStrategy()\r
+{\r
+}\r
+\r
+CPreferenceModeStrategy::~CPreferenceModeStrategy()\r
+{\r
+}\r
+\r
+bool CPreferenceModeStrategy::CanAllocateResources(std::vector<CRequest*> requests, rms_allocate_result_s *result)\r
+{\r
+       result->result = RMS_ERROR;\r
+       result->reason = RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE;\r
+\r
+       for (auto const &it : requests) {\r
+               CRequest *req = it;\r
+               CResourceCategory *resource_category = CResourceDB::getInstance()->FindResourceCategory(req->GetCategory());\r
+\r
+               if (!resource_category) {\r
+                       SERVER_ERR("not existing category(%d)! can't allocate a candidate", req->GetCategory());\r
+                       continue;\r
+               }\r
+\r
+               CResource *resource = resource_category->ReserveCandidate(req, false);\r
+\r
+               if (!resource)\r
+                       continue;\r
+\r
+               req->SetResult(RMS_OK);\r
+               req->SetCandidateDevice(resource->GetDeviceID());\r
+               result->result = RMS_OK;\r
+               break;\r
+       }\r
+\r
+       std::for_each(requests.begin(), requests.end(), [](CRequest *req) { if (req->GetResult()!= RMS_OK) return;\r
+                                                                                               CResource *resource = CResourceDB::getInstance()->FindResource(req->GetCandidateDevice());\r
+                                                                                               resource->CancelReservation((rms_requests_resource_state_e) req->GetState()); });\r
+\r
+       return (result->result == RMS_OK);\r
+}\r
+\r
+void CPreferenceModeStrategy::WriteAllocResult(rms_allocate_result_s *alloc_result, std::vector<CRequest *> requests, rms_return_device_s *allocated_devices)\r
+{\r
+       assert(allocated_devices);\r
+\r
+       allocated_devices->result = alloc_result->result;\r
+       allocated_devices->error_type = alloc_result->reason;\r
+\r
+       if (alloc_result->result != RMS_OK) {\r
+               allocated_devices->resources_num = 0;\r
+               return;\r
+       }\r
+\r
+       allocated_devices->resources_num = requests.size();\r
+       allocated_devices->device_ids = (int*) calloc(requests.size(), sizeof(int));\r
+       allocated_devices->devices = (rms_return_device_info_s*) calloc(requests.size(), sizeof(rms_return_device_info_s));\r
+\r
+       int i = 0;\r
+\r
+       for (auto const &it : requests) {\r
+               bool is_allocated = (it->GetResult() == RMS_OK);\r
+               int allocated_device_id = (is_allocated) ? it->GetAllocatedVirtualDevice() : RMS_DEVICE_NONE;\r
+\r
+               allocated_devices->device_ids[i] = allocated_device_id;\r
+               allocated_devices->devices[i].device_id = allocated_device_id;\r
+\r
+               if (!is_allocated) {\r
+                       i++;\r
+                       continue;\r
+               }\r
+\r
+               CResource *resource = CResourceDB::getInstance()->FindResource(it->GetAllocatedDevice());\r
+               assert(resource);\r
+\r
+               const char *path = resource->GetDevicePath();\r
+               allocated_devices->devices[i].device_path = strndup(path, strlen(path));\r
+               resource->SetAllocatedTime();\r
+               i++;\r
+       }\r
+}\r
+\r
diff --git a/src/manager/strategy/CScalerStrategy.cpp b/src/manager/strategy/CScalerStrategy.cpp
new file mode 100644 (file)
index 0000000..5cca781
--- /dev/null
@@ -0,0 +1,273 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CResourceDB.h>\r
+#include <CRequest.h>\r
+#include <CPriority.h>\r
+#include <CRequester.h>\r
+#include <CDependencyController.h>\r
+#include <CScalerStrategy.h>\r
+\r
+CScalerStrategy::CScalerStrategy()\r
+{\r
+}\r
+\r
+CScalerStrategy::~CScalerStrategy()\r
+{\r
+}\r
+\r
+void CScalerStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+CVirtualResource *CScalerStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource *> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               int device_id = resource->GetDeviceID();\r
+\r
+               if (resource->IsReserved())\r
+                       continue;\r
+\r
+               if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+                       updateReasonByMemCluster(vresource, req);\r
+                       continue;\r
+               }\r
+\r
+               if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+                       updateReasonByResourceState(device_id, req);\r
+                       continue;\r
+               }\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CScalerStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID());\r
+       return RMS_OK;\r
+}\r
+\r
+bool CScalerStrategy::ContainFreeResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+       for (auto const &it : vresources)\r
+       {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (resource->IsFreeState())\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+void CScalerStrategy::SelectConsumersByAllocationTime(std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       std::map<unsigned long, int> candidates_by_alloc_t; // allocation time, virtual resource id\r
+\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       candidates_by_alloc_t.insert(std::pair<unsigned long, int>(rsc->GetAllocatedTime(), it.first));\r
+                       SERVER_INFO("vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second);\r
+               }\r
+       }\r
+\r
+       auto itf = candidates_by_alloc_t.begin();\r
+       if (itf == candidates_by_alloc_t.end()) {\r
+               SERVER_ERR("no candidate");\r
+               return;\r
+       }\r
+\r
+       auto const &ite = candidates->find(itf->second);\r
+       std::multimap<int, int> *elected = &ite->second;\r
+\r
+       result->insert(elected->begin(), elected->end());\r
+}\r
+\r
+void CScalerStrategy::SelectConsumersByZoneId(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       if (zone_id <= 0) {\r
+               SERVER_ERR("invalid zone id(%d)", zone_id);\r
+               return;\r
+       }\r
+\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       if (rsc->GetZoneId() == zone_id) {\r
+                               SERVER_INFO("[%d] select (%d) > (%d:%d)", it.first, zone_id, itc.first, itc.second);\r
+                               result->insert(candidate.begin(), candidate.end());\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+bool CScalerStrategy::ContainInterlacedNotSupportedApp(std::map<int, std::multimap<int, int>> *candidates)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       if (rsc->GetCurCategory() != RMS_CATEGORY_SCALER_INTERLACED)\r
+                               return true;\r
+               }\r
+       }\r
+       return false;\r
+}\r
+\r
+int CScalerStrategy::FindScalerInSameZone(int zone_id)\r
+{\r
+       std::map<int, CResource*> scalers;\r
+       CResourceDB::getInstance()->GetScalerList(&scalers);\r
+\r
+       for (auto const &it : scalers) {\r
+               CResource *rsc = it.second;\r
+               if (rsc->GetZoneId() == zone_id) {\r
+                       SERVER_INFO("scaler in same zone(%d:%d:%d) found", zone_id, rsc->GetDeviceID(), rsc->GetVirtualDeviceId());\r
+                       return rsc->GetDeviceID();\r
+               }\r
+       }\r
+       SERVER_INFO("scaler in same zone not found");\r
+       return -1;\r
+}\r
+\r
+int CScalerStrategy::FindScalerUsedByAppInterlacedNotSupported(std::map<int, std::multimap<int, int>> *candidates)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       if (rsc->GetCurCategory() == RMS_CATEGORY_SCALER_INTERLACED)\r
+                               continue;\r
+                       SERVER_INFO("scaler(%d:%d:%d) used by the app interlaced not supported found", rsc->GetCurCategory(), rsc->GetDeviceID(), rsc->GetVirtualDeviceId());\r
+                       return rsc->GetDeviceID();\r
+               }\r
+       }\r
+       SERVER_INFO("scaler used by the app interlaced not supported not found");\r
+       return -1;\r
+}\r
+\r
+void CScalerStrategy::SelectConsumersBySwap(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       if (!ContainInterlacedNotSupportedApp(candidates)) {\r
+               SERVER_INFO("all scalers are being used by apps supporting interlaced");\r
+               return;\r
+       }\r
+\r
+       int scaler_id_sz = FindScalerInSameZone(zone_id);\r
+       if (scaler_id_sz < 0)\r
+               return;\r
+\r
+       int scaler_id_ins = FindScalerUsedByAppInterlacedNotSupported(candidates);\r
+       if (scaler_id_ins < 0)\r
+               return;\r
+\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       CResource *rsc_sz = db->FindResource(scaler_id_sz);\r
+       CResource *rsc_ins = db->FindResource(scaler_id_ins);\r
+\r
+       if (db->SwapScaler(rsc_sz->GetVirtualDeviceId(), rsc_ins->GetVirtualDeviceId()) < 0)\r
+               return;\r
+\r
+       db->UpdateVirtualScalerIds();\r
+\r
+       std::set<int> consumers = rsc_ins->GetConsumers();\r
+       for (auto const &it : consumers) {\r
+               SERVER_INFO("insert (%d:%d)", scaler_id_ins, it);\r
+               result->insert(std::pair<int, int>(scaler_id_ins, it));\r
+       }\r
+}\r
+\r
+void CScalerStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource*> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+       std::map<int, std::multimap<int, int>> candidates; // <vrsc id, <device id, consumer id>>\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+               SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID());\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+                       if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), &consumer_list) != RMS_OK) {\r
+                               SERVER_ERR("failed to find reclaimable consumer vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID());\r
+                       };\r
+               }\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), &consumer_list, err_type) == RMS_OK) {\r
+                       candidates.insert(std::pair<int, std::multimap<int, int>>(vresource->GetVResourceID(), consumer_list));\r
+                       consumer_list.clear();\r
+               }\r
+       }\r
+       SERVER_INFO("zone id : %d, candidates(%zu)", req->GetMultiviewZoneId(), candidates.size());\r
+       if (req->GetMultiviewZoneId() > 0)\r
+               SelectConsumersByZoneId(req->GetMultiviewZoneId(), &candidates, &consumer_list);\r
+\r
+       if (consumer_list.empty() && (req->GetCategory() == RMS_CATEGORY_SCALER_INTERLACED))\r
+               SelectConsumersBySwap(req->GetMultiviewZoneId(), &candidates, &consumer_list);\r
+\r
+       if (consumer_list.empty())\r
+               SelectConsumersByAllocationTime(&candidates, &consumer_list);\r
+\r
+       for (auto const &it : consumer_list)\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+}\r
diff --git a/src/manager/strategy/CVideoDecoderStrategy.cpp b/src/manager/strategy/CVideoDecoderStrategy.cpp
new file mode 100644 (file)
index 0000000..c02f504
--- /dev/null
@@ -0,0 +1,590 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <ri-module-api.h>\r
+#include <rms_debug.h>\r
+#include <CResourceDB.h>\r
+#include <CBandwidth.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CDependencyController.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CVideoDecoderStrategy.h>\r
+\r
+CVideoDecoderStrategy::CVideoDecoderStrategy()\r
+{\r
+       m_reclaim_policy_by_zone_id = ri_get_zone_id_based_reclaim_policy();\r
+}\r
+\r
+void CVideoDecoderStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle())) {\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER)\r
+               return;\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+void CVideoDecoderStrategy::updateReasonByBW(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       rms_error_type_e reason = canReclaimRequiredBW(req, vresource->GetBW()) ?\r
+                                                               RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER:RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS;\r
+       req->SetReason(reason);\r
+}\r
+\r
+void CVideoDecoderStrategy::updateReasonByTripleDecoding(CRequest *req)\r
+{\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       rms_error_type_e reason = canReclaimActiveVideoDecoders(req) ?\r
+                                                               RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER : RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS;\r
+       req->SetReason(reason);\r
+}\r
+\r
+bool CVideoDecoderStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CResource *resource = vresource->GetResource();\r
+       //int cat_id = vresource->GetCategoryType();\r
+       //int vid = vresource->GetVResourceID();\r
+       int device_id = resource->GetDeviceID();\r
+\r
+       //SERVER_INFO("> cat(%d)/vid(%d) device id(%d)", cat_id, vid, device_id);\r
+\r
+       if (resource->IsReserved()) {\r
+               SERVER_INFO("device id(%d) is reserved state", device_id);\r
+               return false;\r
+       }\r
+\r
+       if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+               updateReasonByMemCluster(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       if (vresource->GetBW() > bandwidth->GetAvail()) {\r
+               SERVER_INFO("insufficient BW required(%d)/avail(%d)", vresource->GetBW(), bandwidth->GetAvail());\r
+               updateReasonByBW(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+               updateReasonByResourceState(device_id, req);\r
+               return false;\r
+       }\r
+\r
+       if (!CResourceDB::getInstance()->HasAvailableDecoder()) {\r
+               updateReasonByTripleDecoding(req);\r
+               return false;\r
+       }\r
+\r
+       //SERVER_INFO("> cat(%d)/vid(%d) device id(%d) allocatable", cat_id, vid, device_id);\r
+\r
+       return true;\r
+}\r
+\r
+CVirtualResource *CVideoDecoderStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource*> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+\r
+               if (!isAllocatableResource(vresource, req))\r
+                       continue;\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CVideoDecoderStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID());\r
+       return RMS_OK;\r
+}\r
+\r
+bool CVideoDecoderStrategy::ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters()))\r
+                       continue;\r
+\r
+               if (bandwidth->GetAvail() < vresource->GetBW())\r
+                       continue;\r
+\r
+               if (!resource->IsFreeState())\r
+                       continue;\r
+\r
+               if (!CResourceDB::getInstance()->HasAvailableDecoder())\r
+                       continue;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+int CVideoDecoderStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CResource *resource = vresource->GetResource();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+       int requester_id = req->getRequester()->getHandle();\r
+\r
+       SERVER_INFO(":: Get retirable consumers (%d:%d)", vresource->GetVResourceID(), resource->GetDeviceID());\r
+\r
+       if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) {\r
+               SERVER_INFO("vrsc(%d)/rsc(%d)", vresource->GetVResourceID(), resource->GetDeviceID());\r
+               if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), requester_id, retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if ((bandwidth->GetAvail() + GetReclaimedBW(retirables)) < vresource->GetBW()) {\r
+               if (getConsumerUsingBW(req, vresource->GetBW(), retirables) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource->IsFreeState()) {\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), requester_id, retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource_db->HasAvailableDecoder(*retirables)) {\r
+               if (GetReclaimableVideoDecoderConsumers(requester_id, retirables, req, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       SERVER_WARN("RMS_OK");\r
+       return RMS_OK;\r
+\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+void CVideoDecoderStrategy::SelectInSameCategoryAndZone(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       if ((rsc->GetVirtualResourceID() == it.first) && (rsc->GetZoneId() == zone_id)) {\r
+                               SERVER_INFO("[%d] select (%d) > (%d:%d)", it.first, zone_id, itc.first, itc.second);\r
+                               result->insert(candidate.begin(), candidate.end());\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+int CVideoDecoderStrategy::GetConflictScore(int n_conflicts)\r
+{\r
+       return (10000 - n_conflicts);\r
+}\r
+\r
+void CVideoDecoderStrategy::SelectInSameZone(int zone_id, std::map<int, std::multimap<int, int>> candidates, std::multimap<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       std::map<int, int> candidates_by_score;\r
+\r
+       for (auto const &it : candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       if (rsc->GetZoneId() != zone_id)\r
+                               continue;\r
+\r
+                       int score = GetConflictScore(candidate.size());\r
+                       SERVER_INFO("insert (%d:%d) : score(%d) by (%d)", it.first, zone_id, score, itc.first);\r
+                       candidates_by_score.insert(std::pair<int, int>(score, it.first));\r
+               }\r
+       }\r
+\r
+       if (candidates_by_score.empty())\r
+               return;\r
+\r
+       auto const top = candidates_by_score.rbegin();\r
+       auto const it = candidates.find(top->second);\r
+       if (it == candidates.end())\r
+               return;\r
+\r
+       std::multimap<int, int> selected = it->second;\r
+       SERVER_INFO("select (%d:%d)", top->second, zone_id);\r
+       result->insert(selected.begin(), selected.end());\r
+}\r
+\r
+void CVideoDecoderStrategy::SelectConsumersByZoneId(int zone_id, std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       if (zone_id <= 0) {\r
+               SERVER_ERR("invalid zone id(%d)", zone_id);\r
+               return;\r
+       }\r
+\r
+       SelectInSameCategoryAndZone(zone_id, candidates, result);\r
+\r
+       if (!result->empty())\r
+               return;\r
+\r
+       SelectInSameZone(zone_id, *candidates, result);\r
+}\r
+\r
+void CVideoDecoderStrategy::SelectConsumersByAllocationTime(std::map<int, std::multimap<int, int>> *candidates, std::multimap<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       std::map<unsigned long, int> candidates_by_alloc_t; // allocation time, virtual resource id\r
+\r
+       std::map<int, int> conflicts; //virtual resource id, n conflicts\r
+       int n_conflicts = 0;\r
+       for (auto const &itn : *candidates) {\r
+               std::multimap<int, int> candidate = itn.second;\r
+               n_conflicts = candidate.size();\r
+               if (n_conflicts > 0) {\r
+                       SERVER_INFO("vrsc(%d)/conflicts(%d)", itn.first, n_conflicts);\r
+                       conflicts.insert(std::pair<int, int>(itn.first, n_conflicts));\r
+               }\r
+       }\r
+\r
+       bool inserted = false;\r
+\r
+       for (auto const &it : *candidates) {\r
+               std::multimap<int, int> candidate = it.second;\r
+               n_conflicts = candidate.size();\r
+               for (auto const &itc : candidate) {\r
+                       CResource *rsc = db->FindResource(itc.first);\r
+                       unsigned long alloc_t = rsc->GetAllocatedTime();\r
+                       SERVER_INFO("insert vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second);\r
+                       inserted = candidates_by_alloc_t.insert(std::pair<unsigned long, int>(alloc_t, it.first)).second;\r
+                       if (!inserted) {\r
+                               SERVER_INFO("t:%ld already in it", alloc_t);\r
+                               auto const &cur = candidates_by_alloc_t.find(alloc_t);\r
+                               if (cur == candidates_by_alloc_t.end())\r
+                                       continue;\r
+\r
+                               auto const &n = conflicts.find(cur->second);\r
+                               if (n == conflicts.end())\r
+                                       continue;\r
+\r
+                               int cur_conflicts = n->second;\r
+                               SERVER_INFO("cur_conflicts(%d)/n_conflicts(%d)", cur_conflicts, n_conflicts);\r
+                               if (cur_conflicts > n_conflicts) {\r
+                                       candidates_by_alloc_t.erase(rsc->GetAllocatedTime());\r
+                                       SERVER_INFO("insert vrsc(%d)/dev(%d:%ld)/cid(%d)", it.first, itc.first, rsc->GetAllocatedTime(), itc.second);\r
+                                       candidates_by_alloc_t.insert(std::pair<unsigned long, int>(rsc->GetAllocatedTime(), it.first));\r
+                               }\r
+                       }\r
+\r
+               }\r
+       }\r
+\r
+       auto itf = candidates_by_alloc_t.begin();\r
+       if (itf == candidates_by_alloc_t.end()) {\r
+               SERVER_ERR("no candidate");\r
+               return;\r
+       }\r
+\r
+       auto const &ite = candidates->find(itf->second);\r
+       std::multimap<int, int> *elected = &ite->second;\r
+\r
+       result->insert(elected->begin(), elected->end());\r
+}\r
+\r
+void CVideoDecoderStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+       std::map<int, std::multimap<int, int>> candidates;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       if (ContainAvailableResource(filtered_vresources))\r
+               return;\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+\r
+               if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK) {\r
+                       candidates.insert(std::pair<int, std::multimap<int, int>>(vresource->GetVResourceID(), consumer_list));\r
+                       consumer_list.clear();\r
+               }\r
+       }\r
+\r
+       if (m_reclaim_policy_by_zone_id && req->GetMultiviewZoneId() > 0)\r
+               SelectConsumersByZoneId(req->GetMultiviewZoneId(), &candidates, &consumer_list);\r
+\r
+       if (consumer_list.empty())\r
+               SelectConsumersByAllocationTime(&candidates, &consumer_list);\r
+\r
+       for (auto const &it : consumer_list)\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+}\r
+\r
+bool CVideoDecoderStrategy::canReclaimRequiredBW(CRequest *req, unsigned int bw)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+       unsigned int reclaimed_bw = bandwidth->GetAvail();\r
+       std::map<int, int> bw_consumers = bandwidth->GetConsumers();\r
+\r
+       for (std::map<int, int>::iterator it = bw_consumers.begin(); it != bw_consumers.end(); it++) {\r
+               int device_id = (*it).first;\r
+               int consumer_id = (*it).second;\r
+\r
+               CResource *pRsc = resource_db->FindResource(device_id);\r
+\r
+               if (!pRsc) {\r
+                       SERVER_ERR("cannot find resource using device id");\r
+                       continue;\r
+               }\r
+\r
+               if (requester->getHandle() == consumer_id) {\r
+                       SERVER_INFO("CID[%d] is using BW (%d)", requester->getHandle(), pRsc->GetBW());\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(consumer_id, requester->getHandle()) != HIGH_PRIORITY)\r
+                       continue;\r
+\r
+               reclaimed_bw += pRsc->GetBW();\r
+\r
+               if (bw <= reclaimed_bw)\r
+                       break;\r
+\r
+               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);\r
+       }\r
+\r
+       SERVER_INFO("required BW(%d) - available (%d)", bw, reclaimed_bw);\r
+\r
+       return (bw <= reclaimed_bw);\r
+\r
+}\r
+\r
+void CVideoDecoderStrategy::SelectDevicesByMainSub(CRequest *req, std::map<int, int> *src, std::map<int, int> *result)\r
+{\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+\r
+       for (auto const &it : *src) {\r
+               CResource *rsc = db->FindResource(it.first);\r
+               if (!rsc)\r
+                       continue;\r
+               if (req->IsMainDeviceRequest() && !rsc->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && rsc->IsMainDevice())\r
+                       continue;\r
+\r
+               result->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
+\r
+int CVideoDecoderStrategy::getConsumerUsingBW(CRequest *req, unsigned int bw, std::multimap<int, int> *return_ids)\r
+{\r
+       std::map<int, int> candidates;\r
+       std::map<int, int> cur_consumers = CBandwidth::GetInstance()->GetConsumers(); //device id, consumer id\r
+\r
+       SelectDevicesByMainSub(req, &cur_consumers, &candidates);\r
+\r
+       std::multimap<int, int> reclaimed_by_ms;\r
+       unsigned int avail_bw = GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, candidates, &reclaimed_by_ms);\r
+\r
+       if (avail_bw >= bw) {\r
+               return_ids->insert(reclaimed_by_ms.begin(), reclaimed_by_ms.end());\r
+               return RMS_OK;\r
+       }\r
+\r
+       std::multimap<int, int> reclaimed_by_t;\r
+       GetConsumerUsingBWByAllocationTime(req->getRequester()->getHandle(), bw, cur_consumers, &reclaimed_by_t);\r
+       return_ids->insert(reclaimed_by_t.begin(), reclaimed_by_t.end());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+int CVideoDecoderStrategy::GetConsumerUsingBWByAllocationTime(int requester_id, unsigned int required_bw, std::map<int, int> bw_consumers, std::multimap<int, int> *reclaimed_consumers)\r
+{\r
+       assert(reclaimed_consumers);\r
+\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       CBandwidth *bandwidth = CBandwidth::GetInstance();\r
+\r
+       SERVER_INFO("candidates using BW : %zu", bw_consumers.size());\r
+       unsigned int reclaimed_bw = bandwidth->GetAvail();\r
+\r
+       std::map<unsigned long, int> consumers_by_t;\r
+       for (auto const &itc : bw_consumers) {\r
+               CResource *rsc = resource_db->FindResource(itc.first);\r
+               if (!rsc)\r
+                       continue;\r
+\r
+               consumers_by_t.insert(std::pair<unsigned long, int>(rsc->GetAllocatedTime(), itc.first));\r
+       }\r
+\r
+       for (auto const &it : consumers_by_t) {\r
+               int device_id = it.second;\r
+               CResource *pRsc = resource_db->FindResource(device_id);\r
+               if (!pRsc)\r
+                       continue;\r
+\r
+               int consumer_id = pRsc->GetFirstConsumer();\r
+               SERVER_INFO("consumer (%d) is using bw for device (%d)", consumer_id, device_id);\r
+\r
+               if (requester_id == consumer_id) {\r
+                       SERVER_INFO("CID[%d] is using BW (%d)", requester_id, pRsc->GetBW());\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(consumer_id, requester_id) != HIGH_PRIORITY)\r
+                       continue;\r
+\r
+               auto ret = reclaimed_consumers->find(device_id);\r
+               if (ret != reclaimed_consumers->end()) {\r
+                       SERVER_INFO("(%d:%d) already inserted", device_id, consumer_id);\r
+                       continue;\r
+               }\r
+\r
+               reclaimed_consumers->insert(std::pair<int, int>(device_id, consumer_id));\r
+\r
+               if (pRsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) {\r
+                       std::map<int, int> siblings;\r
+                       bandwidth->GetConsumersNDec(pRsc->GetCurCategory(), &siblings);\r
+                       if (siblings.size() > 0) {\r
+                               SERVER_INFO("insert n-dec siblings(%zu)", siblings.size());\r
+                               reclaimed_consumers->insert(siblings.begin(), siblings.end());\r
+                       }\r
+               }\r
+\r
+               reclaimed_bw += pRsc->GetBW();\r
+\r
+               if (required_bw <= reclaimed_bw)\r
+                       break;\r
+               SERVER_INFO("DevID[%d]/ need more BW! required:(%d)-resource(%d)-reclaimed(%d)", pRsc->GetDeviceID(), required_bw, pRsc->GetBW(), reclaimed_bw);\r
+       }\r
+\r
+       return reclaimed_bw;\r
+}\r
+\r
+bool CVideoDecoderStrategy::canReclaimActiveVideoDecoders(CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+       CResourceDB *resource_db = CResourceDB::getInstance();\r
+       std::map<int, int> active_vdecs = resource_db->GetActiveVideoDecoders();\r
+\r
+       for (auto const &it : active_vdecs) {\r
+               int dev_id = it.first;\r
+               int cid = it.second;\r
+\r
+               CResource *rsc = resource_db->FindResource(dev_id);\r
+\r
+               if (!rsc) {\r
+                       SERVER_ERR("can't find resource (%d)", dev_id);\r
+                       continue;\r
+               }\r
+\r
+               if (requester->getHandle() == cid) {\r
+                       SERVER_INFO("CID[%d] is using device (%d)", cid, dev_id);\r
+                       continue;\r
+               }\r
+\r
+               if (CPriority::compare(cid, requester->getHandle()) == HIGH_PRIORITY)\r
+                       return true;\r
+       }\r
+\r
+       return false;\r
+\r
+}\r
+\r
+int CVideoDecoderStrategy::GetReclaimableVideoDecoderConsumers(int consumer_id, std::multimap<int, int>* reclaimables, CRequest *req, rms_error_type_e *err_type)\r
+{\r
+       std::map<unsigned long, CResource*> rscs;\r
+       CResource *rsc = NULL;\r
+       CResourceDB *db = CResourceDB::getInstance();\r
+       std::map<int, int> active_vdecs = db->GetActiveVideoDecoders();\r
+       bool has_main_vdec = false;\r
+       bool has_sub_vdec = false;\r
+\r
+       for (auto const &it_vdec : active_vdecs) {\r
+               rsc = db->FindResource(it_vdec.first);\r
+               rscs.insert(std::pair<unsigned long, CResource*>(rsc->GetAllocatedTime(), rsc));\r
+\r
+               if (rsc->IsMainDevice())\r
+                       has_main_vdec = true;\r
+               else\r
+                       has_sub_vdec = true;\r
+       }\r
+\r
+       for (auto const &it : rscs) {\r
+               rsc = it.second;\r
+\r
+               if (req->IsMainDeviceRequest() && has_main_vdec && !rsc->IsMainDevice())\r
+                       continue;\r
+               if (req->IsSubDeviceRequest() && has_sub_vdec && rsc->IsMainDevice())\r
+                       continue;\r
+\r
+               if (CPriority::getReclaimableConsumers(rsc->GetDeviceID(), consumer_id, reclaimables, err_type) == RMS_OK) {\r
+                       if (rsc->GetCategoryClass() == RMS_CATEGORY_CLASS_N_DECODING) {\r
+                               std::map<int, int> active_ndecs = db->GetActiveNVideoDecoders();\r
+                               reclaimables->insert(active_ndecs.begin(), active_ndecs.end());\r
+                       }\r
+                       return RMS_OK;\r
+               }\r
+       }\r
+\r
+       return RMS_ERROR;\r
+}\r
diff --git a/src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp b/src/manager/strategy/CVideoEncoderExclusiveStrategy.cpp
new file mode 100644 (file)
index 0000000..3e06691
--- /dev/null
@@ -0,0 +1,180 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <assert.h>\r
+\r
+#include <rms_debug.h>\r
+#include <CResourceDB.h>\r
+#include <CResource.h>\r
+#include <CVirtualResource.h>\r
+#include <CRequest.h>\r
+#include <CRequester.h>\r
+#include <CPriority.h>\r
+#include <CDependencyController.h>\r
+#include <CAllocateStrategy.h>\r
+#include <CVideoEncoderExclusiveStrategy.h>\r
+\r
+void CVideoEncoderExclusiveStrategy::updateReasonByMemCluster(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (req->GetState() == RMS_STATE_EXCLUSIVE_CONDITIONAL) {\r
+               req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+               return;\r
+       }\r
+\r
+       if (CDependencyController::getInstance()->canReclaimMemClusters(vresource->GetMemClusters(), requester->getHandle(), requester->getAppId())) {\r
+               SERVER_ERR("canReclaimMemClusters is failed");\r
+               req->SetReason(RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER);\r
+               return;\r
+       }\r
+\r
+       if (req->GetReason() == RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER) {\r
+               SERVER_ERR("RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER");\r
+               return;\r
+       }\r
+\r
+       req->SetReason(RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS);\r
+}\r
+\r
+bool CVideoEncoderExclusiveStrategy::isAllocatableResource(CVirtualResource *vresource, CRequest *req)\r
+{\r
+       CResource *resource = vresource->GetResource();\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (resource->IsReserved()) {\r
+               SERVER_ERR("device id(%d) is reserved state", resource->GetDeviceID());\r
+               return false;\r
+       }\r
+\r
+       if (!CDependencyController::getInstance()->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId())) {\r
+               SERVER_ERR("isAvailableMemClusters is failed");\r
+               updateReasonByMemCluster(vresource, req);\r
+               return false;\r
+       }\r
+\r
+       if (!resource->IsAllocatableState((rms_requests_resource_state_e) req->GetState())) {\r
+               SERVER_ERR("IsAllocatableState is failed");\r
+               updateReasonByResourceState(resource->GetDeviceID(), req);\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+CVirtualResource *CVideoEncoderExclusiveStrategy::findCandidate(std::map<int, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       std::map<int, CVirtualResource *> filtered_vresources;\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       req->SetResult(RMS_ERROR);\r
+       req->SetReason(RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE);\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               if (!isAllocatableResource(vresource, req))\r
+                       continue;\r
+\r
+               return vresource;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+int CVideoEncoderExclusiveStrategy::reserveResource(CVirtualResource *vrsc, CRequest *req)\r
+{\r
+       CResource *rsc = vrsc->GetResource();\r
+\r
+       if (rsc->Reserve(req->getRequester()->getHandle(), req->GetState()) != RMS_OK)\r
+               return RMS_ERROR;\r
+\r
+       rsc->UpdateProperties(vrsc->GetMemClusters(), vrsc->GetBW(), vrsc->GetCategoryType(), vrsc->GetCategoryClass(), vrsc->GetVResourceID());\r
+\r
+       return RMS_OK;\r
+}\r
+\r
+bool CVideoEncoderExclusiveStrategy::ContainAvailableResource(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CRequester *requester = req->getRequester();\r
+\r
+       for (auto const &it : vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               CResource *resource = vresource->GetResource();\r
+\r
+               if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId()))\r
+                       continue;\r
+\r
+               if (!resource->IsFreeState())\r
+                       continue;\r
+\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+int CVideoEncoderExclusiveStrategy::getRetirableConsumersExclusive(CVirtualResource *vresource, CRequest *req, std::multimap<int, int> *retirables, rms_error_type_e *err_type)\r
+{\r
+       CDependencyController *dc = CDependencyController::getInstance();\r
+       CResource *resource = vresource->GetResource();\r
+       CRequester *requester = req->getRequester();\r
+\r
+       if (!requester) {\r
+               SERVER_ERR("can't find requester");\r
+               goto error;\r
+       }\r
+\r
+       if (!dc->isAvailableMemClusters(vresource->GetMemClusters(), requester->getAppId())) {\r
+               if (dc->getReclaimableMemClusterConsumers(vresource->GetMemClusters(), req->getRequester()->getHandle(), retirables, requester->getAppId()) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       if (!resource->IsFreeState()) {\r
+               if (CPriority::getReclaimableConsumers(resource->GetDeviceID(), req->getRequester()->getHandle(), retirables, err_type) != RMS_OK)\r
+                       goto error;\r
+       }\r
+\r
+       return RMS_OK;\r
+\r
+error:\r
+       if (!retirables->empty())\r
+               retirables->clear();\r
+\r
+       return RMS_ERROR;\r
+}\r
+\r
+void CVideoEncoderExclusiveStrategy::GetRetirableConsumers(std::multimap<unsigned long, CVirtualResource *> vresources, CRequest *req, std::multimap<int, int>* retirables, rms_error_type_e *err_type)\r
+{\r
+       std::multimap<int, int> consumer_list;\r
+       std::multimap<unsigned long, CVirtualResource *> filtered_vresources;\r
+\r
+       ExcludeResources(vresources, &filtered_vresources, req);\r
+\r
+       bool hasAllocatableResource = ContainAvailableResource(filtered_vresources, req);\r
+       if (hasAllocatableResource)\r
+               return;\r
+\r
+       for (auto const &it : filtered_vresources) {\r
+               CVirtualResource *vresource = it.second;\r
+               if (getRetirableConsumersExclusive(vresource, req, &consumer_list, err_type) == RMS_OK)\r
+                       break;\r
+       }\r
+\r
+       for (auto const &it : consumer_list) {\r
+               retirables->insert(std::pair<int, int>(it.first, it.second));\r
+       }\r
+}\r
diff --git a/src/rms_service.cpp b/src/rms_service.cpp
new file mode 100644 (file)
index 0000000..2f73275
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <trace.h>\r
+#include <rms_debug.h>\r
+#include <CResourceService.h>\r
+\r
+#include <iostream>\r
+\r
+int main(void)\r
+{\r
+       SERVER_INFO("RscMgr server main loop\n");\r
+       trace_begin("[RSC_MGR] main start");\r
+       trace_end();\r
+\r
+       GMainLoop *main_loop;\r
+       main_loop = g_main_loop_new(NULL, FALSE);\r
+\r
+       if (!main_loop) {\r
+               SERVER_ERR("failed to create a main loop\n");\r
+               return 0;\r
+       }\r
+\r
+       CResourceService *service = new(std::nothrow) CResourceService;\r
+       service->Init(main_loop);\r
+\r
+       g_main_loop_ref(main_loop);\r
+       g_main_loop_run(main_loop);\r
+\r
+       return 0;\r
+}\r