1 /*
2 * Copyright (C) 2023 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 "avcodec_server_manager.h"
17 #include <codecvt>
18 #include <dlfcn.h>
19 #include <locale>
20 #include <thread>
21 #include <unistd.h>
22 #include "avcodec_dump_utils.h"
23 #include "avcodec_errors.h"
24 #include "avcodec_log.h"
25 #include "avcodec_trace.h"
26 #include "avcodec_xcollie.h"
27 #include "system_ability_definition.h"
28 #ifdef SUPPORT_CODEC
29 #include "codec_service_stub.h"
30 #endif
31 #ifdef SUPPORT_CODECLIST
32 #include "codeclist_service_stub.h"
33 #endif
34
35 namespace {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecServerManager"};
37 } // namespace
38
39 namespace OHOS {
40 namespace MediaAVCodec {
GetInstance()41 AVCodecServerManager& AVCodecServerManager::GetInstance()
42 {
43 static AVCodecServerManager instance;
44 return instance;
45 }
46
Dump(int32_t fd,const std::vector<std::u16string> & args)47 int32_t AVCodecServerManager::Dump(int32_t fd, const std::vector<std::u16string>& args)
48 {
49 if (fd < 0) {
50 return OHOS::NO_ERROR;
51 }
52 std::lock_guard<std::mutex> lock(mutex_);
53
54 constexpr std::string_view dumpStr = "[Codec_Server]\n";
55 write(fd, dumpStr.data(), dumpStr.size());
56
57 int32_t instanceIndex = 0;
58 for (auto iter : codecStubMap_) {
59 std::string instanceStr = std::string(" Instance_") + std::to_string(instanceIndex++) + "_Info\n";
60 write(fd, instanceStr.data(), instanceStr.size());
61 (void)iter.first->Dump(fd, args);
62 }
63
64 return OHOS::NO_ERROR;
65 }
66
AVCodecServerManager()67 AVCodecServerManager::AVCodecServerManager()
68 {
69 pid_ = getpid();
70 Init();
71 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
72 }
73
~AVCodecServerManager()74 AVCodecServerManager::~AVCodecServerManager()
75 {
76 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
77 }
78
Init()79 void AVCodecServerManager::Init()
80 {
81 void *handle = dlopen(LIB_PATH, RTLD_NOW);
82 CHECK_AND_RETURN_LOG(handle != nullptr, "Load so failed:%{public}s", LIB_PATH);
83 libMemMgrClientHandle_ = std::shared_ptr<void>(handle, dlclose);
84 notifyProcessStatusFunc_ = reinterpret_cast<NotifyProcessStatusFunc>(dlsym(handle, NOTIFY_STATUS_FUNC_NAME));
85 CHECK_AND_RETURN_LOG(notifyProcessStatusFunc_ != nullptr, "Load notifyProcessStatusFunc failed:%{public}s",
86 NOTIFY_STATUS_FUNC_NAME);
87 setCriticalFunc_ = reinterpret_cast<SetCriticalFunc>(dlsym(handle, SET_CRITICAL_FUNC_NAME));
88 CHECK_AND_RETURN_LOG(setCriticalFunc_ != nullptr, "Load setCriticalFunc failed:%{public}s",
89 SET_CRITICAL_FUNC_NAME);
90 return;
91 }
92
CreateStubObject(StubType type,sptr<IRemoteObject> & object)93 int32_t AVCodecServerManager::CreateStubObject(StubType type, sptr<IRemoteObject> &object)
94 {
95 std::lock_guard<std::mutex> lock(mutex_);
96 switch (type) {
97 #ifdef SUPPORT_CODECLIST
98 case CODECLIST: {
99 return CreateCodecListStubObject(object);
100 }
101 #endif
102 #ifdef SUPPORT_CODEC
103 case CODEC: {
104 return CreateCodecStubObject(object);
105 }
106 #endif
107 default: {
108 AVCODEC_LOGE("default case, av_codec server manager failed");
109 return AVCS_ERR_UNSUPPORT;
110 }
111 }
112 }
113
114 #ifdef SUPPORT_CODECLIST
CreateCodecListStubObject(sptr<IRemoteObject> & object)115 int32_t AVCodecServerManager::CreateCodecListStubObject(sptr<IRemoteObject> &object)
116 {
117 sptr<CodecListServiceStub> stub = CodecListServiceStub::Create();
118 CHECK_AND_RETURN_RET_LOG(stub != nullptr, AVCS_ERR_CREATE_CODECLIST_STUB_FAILED,
119 "Failed to create AVCodecListServiceStub");
120 object = stub->AsObject();
121 CHECK_AND_RETURN_RET_LOG(object != nullptr, AVCS_ERR_CREATE_CODECLIST_STUB_FAILED,
122 "Failed to create AVCodecListServiceStub");
123
124 pid_t pid = IPCSkeleton::GetCallingPid();
125 codecListStubMap_[object] = pid;
126 AVCODEC_LOGD("The number of codeclist services(%{public}zu).", codecListStubMap_.size());
127 return AVCS_ERR_OK;
128 }
129 #endif
130 #ifdef SUPPORT_CODEC
CreateCodecStubObject(sptr<IRemoteObject> & object)131 int32_t AVCodecServerManager::CreateCodecStubObject(sptr<IRemoteObject> &object)
132 {
133 sptr<CodecServiceStub> stub = CodecServiceStub::Create();
134 CHECK_AND_RETURN_RET_LOG(stub != nullptr, AVCS_ERR_CREATE_AVCODEC_STUB_FAILED, "Failed to create CodecServiceStub");
135
136 object = stub->AsObject();
137 CHECK_AND_RETURN_RET_LOG(object != nullptr, AVCS_ERR_CREATE_AVCODEC_STUB_FAILED,
138 "Failed to create CodecServiceStub");
139
140 pid_t pid = IPCSkeleton::GetCallingPid();
141 codecStubMap_[object] = pid;
142
143 SetCritical(true);
144 AVCODEC_LOGD("The number of codec services(%{public}zu).", codecStubMap_.size());
145 return AVCS_ERR_OK;
146 }
147 #endif
148
EraseObject(std::map<sptr<IRemoteObject>,pid_t>::iterator & iter,std::map<sptr<IRemoteObject>,pid_t> & stubMap,pid_t pid,const std::string & stubName)149 void AVCodecServerManager::EraseObject(std::map<sptr<IRemoteObject>, pid_t>::iterator& iter,
150 std::map<sptr<IRemoteObject>, pid_t>& stubMap,
151 pid_t pid,
152 const std::string& stubName)
153 {
154 if (iter != stubMap.end()) {
155 AVCODEC_LOGI("destroy %{public}s stub services(%{public}zu) pid(%{public}d).", stubName.c_str(),
156 stubMap.size(), pid);
157 (void)stubMap.erase(iter);
158 return;
159 }
160 AVCODEC_LOGE("find %{public}s object failed, pid(%{public}d).", stubName.c_str(), pid);
161 return;
162 }
163
DestroyStubObject(StubType type,sptr<IRemoteObject> object)164 void AVCodecServerManager::DestroyStubObject(StubType type, sptr<IRemoteObject> object)
165 {
166 std::lock_guard<std::mutex> lock(mutex_);
167 pid_t pid = IPCSkeleton::GetCallingPid();
168 auto compare_func = [object](std::pair<sptr<IRemoteObject>, pid_t> objectPair) -> bool {
169 return objectPair.first == object;
170 };
171 switch (type) {
172 case CODEC: {
173 auto it = find_if(codecStubMap_.begin(), codecStubMap_.end(), compare_func);
174 EraseObject(it, codecStubMap_, pid, "codec");
175 break;
176 }
177 case CODECLIST: {
178 auto it = find_if(codecListStubMap_.begin(), codecListStubMap_.end(), compare_func);
179 EraseObject(it, codecListStubMap_, pid, "codeclist");
180 break;
181 }
182 default: {
183 AVCODEC_LOGE("default case, av_codec server manager failed, pid(%{public}d).", pid);
184 break;
185 }
186 }
187 if (codecStubMap_.size() == 0) {
188 SetCritical(false);
189 }
190 }
191
EraseObject(std::map<sptr<IRemoteObject>,pid_t> & stubMap,pid_t pid)192 void AVCodecServerManager::EraseObject(std::map<sptr<IRemoteObject>, pid_t>& stubMap, pid_t pid)
193 {
194 for (auto it = stubMap.begin(); it != stubMap.end();) {
195 if (it->second == pid) {
196 executor_.Commit(it->first);
197 it = stubMap.erase(it);
198 } else {
199 it++;
200 }
201 }
202 return;
203 }
204
DestroyStubObjectForPid(pid_t pid)205 void AVCodecServerManager::DestroyStubObjectForPid(pid_t pid)
206 {
207 std::lock_guard<std::mutex> lock(mutex_);
208 AVCODEC_LOGI("codec stub services(%{public}zu) pid(%{public}d).", codecStubMap_.size(), pid);
209 EraseObject(codecStubMap_, pid);
210 AVCODEC_LOGI("codec stub services(%{public}zu).", codecStubMap_.size());
211
212 AVCODEC_LOGI("codeclist stub services(%{public}zu) pid(%{public}d).", codecListStubMap_.size(), pid);
213 EraseObject(codecListStubMap_, pid);
214 AVCODEC_LOGI("codeclist stub services(%{public}zu).", codecListStubMap_.size());
215 executor_.Clear();
216 if (codecStubMap_.size() == 0) {
217 SetCritical(false);
218 }
219 }
220
NotifyProcessStatus(const int32_t status)221 void AVCodecServerManager::NotifyProcessStatus(const int32_t status)
222 {
223 CHECK_AND_RETURN_LOG(notifyProcessStatusFunc_ != nullptr, "notify memory manager is nullptr, %{public}d.", status);
224 int32_t ret = notifyProcessStatusFunc_(pid_, 1, status, AV_CODEC_SERVICE_ID);
225 if (ret == 0) {
226 AVCODEC_LOGI("notify memory manager to %{public}d success.", status);
227 } else {
228 AVCODEC_LOGW("notify memory manager to %{public}d fail.", status);
229 }
230 }
231
SetMemMgrStatus(const bool isStarted)232 void AVCodecServerManager::SetMemMgrStatus(const bool isStarted)
233 {
234 memMgrStarted_ = isStarted;
235 }
236
SetCritical(const bool isKeyService)237 void AVCodecServerManager::SetCritical(const bool isKeyService)
238 {
239 CHECK_AND_RETURN_LOG(memMgrStarted_, "Memory manager service is not started");
240 CHECK_AND_RETURN_LOG(setCriticalFunc_ != nullptr, "set critical is nullptr, %{public}d.", isKeyService);
241 int32_t ret = setCriticalFunc_(pid_, isKeyService, AV_CODEC_SERVICE_ID);
242 if (ret == 0) {
243 AVCODEC_LOGI("set critical to %{public}d success.", isKeyService);
244 } else {
245 AVCODEC_LOGW("set critical to %{public}d fail.", isKeyService);
246 }
247 }
248
Commit(sptr<IRemoteObject> obj)249 void AVCodecServerManager::AsyncExecutor::Commit(sptr<IRemoteObject> obj)
250 {
251 std::lock_guard<std::mutex> lock(listMutex_);
252 freeList_.push_back(obj);
253 }
254
Clear()255 void AVCodecServerManager::AsyncExecutor::Clear()
256 {
257 std::thread(&AVCodecServerManager::AsyncExecutor::HandleAsyncExecution, this).detach();
258 }
259
HandleAsyncExecution()260 void AVCodecServerManager::AsyncExecutor::HandleAsyncExecution()
261 {
262 std::list<sptr<IRemoteObject>> tempList;
263 {
264 std::lock_guard<std::mutex> lock(listMutex_);
265 freeList_.swap(tempList);
266 }
267 tempList.clear();
268 }
269 } // namespace MediaAVCodec
270 } // namespace OHOS
271