1 /*
2 * Copyright (c) 2021 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 "core/common/ace_engine.h"
17
18 #include <csignal>
19 #include <cstdio>
20
21 #include "base/log/dump_log.h"
22 #include "base/log/log.h"
23 #include "base/memory/memory_monitor.h"
24 #include "base/thread/background_task_executor.h"
25 #include "core/common/ace_application_info.h"
26 #include "core/common/ace_page.h"
27 #include "core/image/image_cache.h"
28
29 namespace OHOS::Ace {
30 namespace {
31
32 std::unique_ptr<AceEngine> g_aceEngine;
33
34 }
35
AceEngine()36 AceEngine::AceEngine()
37 {
38 watchDog_ = AceType::MakeRefPtr<WatchDog>();
39 }
40
Get()41 AceEngine& AceEngine::Get()
42 {
43 if (!g_aceEngine) {
44 LOGI("AceEngine initialized in first time");
45 g_aceEngine.reset(new AceEngine());
46 }
47 return *g_aceEngine;
48 }
49
AddContainer(int32_t instanceId,const RefPtr<Container> & container)50 void AceEngine::AddContainer(int32_t instanceId, const RefPtr<Container>& container)
51 {
52 LOGI("AddContainer %{public}d", instanceId);
53 std::lock_guard<std::mutex> lock(mutex_);
54 const auto result = containerMap_.try_emplace(instanceId, container);
55 if (!result.second) {
56 LOGW("already have container of this instance id: %{public}d", instanceId);
57 }
58 }
59
RemoveContainer(int32_t instanceId)60 void AceEngine::RemoveContainer(int32_t instanceId)
61 {
62 LOGI("RemoveContainer %{public}d", instanceId);
63 size_t num = 0;
64 {
65 std::lock_guard<std::mutex> lock(mutex_);
66 num = containerMap_.erase(instanceId);
67 }
68 if (num == 0) {
69 LOGW("container not found with instance id: %{public}d", instanceId);
70 }
71 if (watchDog_) {
72 watchDog_->Unregister(instanceId);
73 }
74 }
75
Dump(const std::vector<std::string> & params) const76 void AceEngine::Dump(const std::vector<std::string>& params) const
77 {
78 std::unordered_map<int32_t, RefPtr<Container>> copied;
79 {
80 std::lock_guard<std::mutex> lock(mutex_);
81 copied = containerMap_;
82 }
83 for (const auto& container : copied) {
84 auto pipelineContext = container.second->GetPipelineContext();
85 if (!pipelineContext) {
86 LOGW("the pipeline context is nullptr, pa container");
87 continue;
88 }
89 pipelineContext->GetTaskExecutor()->PostSyncTask(
90 [params, container = container.second]() { container->Dump(params); }, TaskExecutor::TaskType::UI);
91 }
92 }
93
GetContainer(int32_t instanceId)94 RefPtr<Container> AceEngine::GetContainer(int32_t instanceId)
95 {
96 std::lock_guard<std::mutex> lock(mutex_);
97 auto container = containerMap_.find(instanceId);
98 if (container != containerMap_.end()) {
99 return container->second;
100 } else {
101 return nullptr;
102 }
103 }
104
RegisterToWatchDog(int32_t instanceId,const RefPtr<TaskExecutor> & taskExecutor,bool useUIAsJSThread)105 void AceEngine::RegisterToWatchDog(int32_t instanceId, const RefPtr<TaskExecutor>& taskExecutor, bool useUIAsJSThread)
106 {
107 if (watchDog_) {
108 watchDog_->Register(instanceId, taskExecutor, useUIAsJSThread);
109 }
110 }
111
BuriedBomb(int32_t instanceId,uint64_t bombId)112 void AceEngine::BuriedBomb(int32_t instanceId, uint64_t bombId)
113 {
114 if (watchDog_) {
115 watchDog_->BuriedBomb(instanceId, bombId);
116 }
117 }
118
DefusingBomb(int32_t instanceId)119 void AceEngine::DefusingBomb(int32_t instanceId)
120 {
121 if (watchDog_) {
122 watchDog_->DefusingBomb(instanceId);
123 }
124 }
125
TriggerGarbageCollection()126 void AceEngine::TriggerGarbageCollection()
127 {
128 std::unordered_map<int32_t, RefPtr<Container>> copied;
129 {
130 std::lock_guard<std::mutex> lock(mutex_);
131 if (containerMap_.empty()) {
132 return;
133 }
134 copied = containerMap_;
135 }
136
137 auto taskExecutor = copied.begin()->second->GetTaskExecutor();
138 taskExecutor->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::PLATFORM);
139 #if defined(OHOS_PLATFORM) && defined(ENABLE_NATIVE_VIEW)
140 // GPU and IO thread is shared while enable native view
141 taskExecutor->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::GPU);
142 taskExecutor->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::IO);
143 #endif
144
145 for (const auto& container : copied) {
146 container.second->TriggerGarbageCollection();
147 }
148
149 ImageCache::Purge();
150 BackgroundTaskExecutor::GetInstance().TriggerGarbageCollection();
151 PurgeMallocCache();
152 }
153
NotifyContainers(const std::function<void (const RefPtr<Container> &)> & callback)154 void AceEngine::NotifyContainers(const std::function<void(const RefPtr<Container>&)>& callback)
155 {
156 if (!callback) {
157 return;
158 }
159 std::lock_guard<std::mutex> lock(mutex_);
160 for (const auto& [first, second] : containerMap_) {
161 callback(second);
162 }
163 }
164
165 } // namespace OHOS::Ace
166