1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rs_ui_context_manager.h"
17
18 #include <atomic>
19
20 #include "platform/common/rs_log.h"
21
22 namespace OHOS {
23 namespace Rosen {
24
25 namespace {
26 static std::atomic_bool g_instanceValid = false;
27 }
28
RSUIContextManager()29 RSUIContextManager::RSUIContextManager()
30 {
31 g_instanceValid.store(true);
32 isMultiInstanceOpen_ = RSSystemProperties::GetRSClientMultiInstanceEnabled();
33 RS_LOGI("multi-instance, create RSUIContextManager, isMultiInstanceOpen_ %{public}d", isMultiInstanceOpen_);
34 }
35
~RSUIContextManager()36 RSUIContextManager::~RSUIContextManager() noexcept
37 {
38 std::unique_lock<std::mutex> lock(mutex_);
39 rsUIContextMap_.clear();
40 g_instanceValid.store(false);
41 }
42
MutableInstance()43 RSUIContextManager& RSUIContextManager::MutableInstance()
44 {
45 static RSUIContextManager rsUIContextManager;
46 return rsUIContextManager;
47 }
48
Instance()49 const RSUIContextManager& RSUIContextManager::Instance()
50 {
51 return MutableInstance();
52 }
53
CreateRSUIContext()54 std::shared_ptr<RSUIContext> RSUIContextManager::CreateRSUIContext()
55 {
56 if (!isMultiInstanceOpen_ || !g_instanceValid.load()) {
57 return nullptr;
58 }
59 std::unique_lock<std::mutex> lock(mutex_);
60 int32_t tid = gettid();
61 uint64_t token = GenerateToken(tid);
62 auto iter = rsUIContextMap_.find(token);
63 if (iter != rsUIContextMap_.end()) {
64 ROSEN_LOGW("RSUIContextManager::CreateRSUIContext: context token %{public}" PRIu64 " already exists", token);
65 return iter->second;
66 }
67 auto newContext = std::shared_ptr<RSUIContext>(new RSUIContext(token));
68 rsUIContextMap_[token] = newContext;
69 return newContext;
70 }
71
GetRSUIContext(uint64_t token) const72 const std::shared_ptr<RSUIContext> RSUIContextManager::GetRSUIContext(uint64_t token) const
73 {
74 if (!isMultiInstanceOpen_ || !g_instanceValid.load()) {
75 return nullptr;
76 }
77 std::unique_lock<std::mutex> lock(mutex_);
78 auto iter = rsUIContextMap_.find(token);
79 if (iter == rsUIContextMap_.end()) {
80 return nullptr;
81 }
82 return iter->second;
83 }
84
DestroyContext(uint64_t token)85 void RSUIContextManager::DestroyContext(uint64_t token)
86 {
87 if (!isMultiInstanceOpen_ || !g_instanceValid.load()) {
88 return;
89 }
90 std::unique_lock<std::mutex> lock(mutex_);
91 auto iter = rsUIContextMap_.find(token);
92 if (iter != rsUIContextMap_.end()) {
93 rsUIContextMap_.erase(iter);
94 } else {
95 ROSEN_LOGW("RSUIContextManager::DestroyContext: context token %{public}" PRIu64 " does not exist", token);
96 }
97 }
98
GenerateToken(int32_t tid)99 uint64_t RSUIContextManager::GenerateToken(int32_t tid)
100 {
101 ++instanceIdCounter_;
102 return (static_cast<uint64_t>(tid) << 32) | instanceIdCounter_; // 32 for 64-bit unsignd number shift
103 }
104
GetRandomUITaskRunnerCtx() const105 std::shared_ptr<RSUIContext> RSUIContextManager::GetRandomUITaskRunnerCtx() const
106 {
107 if (!isMultiInstanceOpen_ || !g_instanceValid.load() || rsUIContextMap_.empty()) {
108 return nullptr;
109 }
110 std::unique_lock<std::mutex> lock(mutex_);
111 for (const auto& [_, ctx] : rsUIContextMap_) {
112 if (ctx->HasTaskRunner()) {
113 return ctx;
114 }
115 }
116 return nullptr;
117 }
118
119 } // namespace Rosen
120 } // namespace OHOS