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 AVCodecXCollie::GetInstance().Dump(fd);
53
54 std::unordered_multimap<pid_t, std::pair<sptr<IRemoteObject>, InstanceInfo>> codecStubMapTemp;
55 {
56 std::lock_guard<std::shared_mutex> lock(mutex_);
57 codecStubMapTemp = codecStubMap_;
58 }
59
60 constexpr std::string_view dumpStr = "[Codec_Server]\n";
61 write(fd, dumpStr.data(), dumpStr.size());
62
63 int32_t instanceIndex = 0;
64 for (auto iter : codecStubMapTemp) {
65 std::string instanceStr = std::string(" Instance_") + std::to_string(instanceIndex++) + "_Info\n";
66 write(fd, instanceStr.data(), instanceStr.size());
67 (void)iter.second.first->Dump(fd, args);
68 }
69
70 return OHOS::NO_ERROR;
71 }
72
AVCodecServerManager()73 AVCodecServerManager::AVCodecServerManager()
74 {
75 pid_ = getpid();
76 Init();
77 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
78 }
79
~AVCodecServerManager()80 AVCodecServerManager::~AVCodecServerManager()
81 {
82 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
83 }
84
Init()85 void AVCodecServerManager::Init()
86 {
87 void *handle = dlopen(LIB_PATH, RTLD_NOW);
88 CHECK_AND_RETURN_LOG(handle != nullptr, "Load so failed:%{public}s", LIB_PATH);
89 libMemMgrClientHandle_ = std::shared_ptr<void>(handle, dlclose);
90 notifyProcessStatusFunc_ = reinterpret_cast<NotifyProcessStatusFunc>(dlsym(handle, NOTIFY_STATUS_FUNC_NAME));
91 CHECK_AND_RETURN_LOG(notifyProcessStatusFunc_ != nullptr, "Load notifyProcessStatusFunc failed:%{public}s",
92 NOTIFY_STATUS_FUNC_NAME);
93 setCriticalFunc_ = reinterpret_cast<SetCriticalFunc>(dlsym(handle, SET_CRITICAL_FUNC_NAME));
94 CHECK_AND_RETURN_LOG(setCriticalFunc_ != nullptr, "Load setCriticalFunc failed:%{public}s",
95 SET_CRITICAL_FUNC_NAME);
96 return;
97 }
98
CreateStubObject(StubType type,sptr<IRemoteObject> & object)99 int32_t AVCodecServerManager::CreateStubObject(StubType type, sptr<IRemoteObject> &object)
100 {
101 std::lock_guard<std::shared_mutex> lock(mutex_);
102 switch (type) {
103 #ifdef SUPPORT_CODECLIST
104 case CODECLIST: {
105 return CreateCodecListStubObject(object);
106 }
107 #endif
108 #ifdef SUPPORT_CODEC
109 case CODEC: {
110 return CreateCodecStubObject(object);
111 }
112 #endif
113 default: {
114 AVCODEC_LOGE("default case, av_codec server manager failed");
115 return AVCS_ERR_UNSUPPORT;
116 }
117 }
118 }
119
120 #ifdef SUPPORT_CODECLIST
CreateCodecListStubObject(sptr<IRemoteObject> & object)121 int32_t AVCodecServerManager::CreateCodecListStubObject(sptr<IRemoteObject> &object)
122 {
123 sptr<CodecListServiceStub> stub = CodecListServiceStub::Create();
124 CHECK_AND_RETURN_RET_LOG(stub != nullptr, AVCS_ERR_CREATE_CODECLIST_STUB_FAILED,
125 "Failed to create AVCodecListServiceStub");
126 object = stub->AsObject();
127 CHECK_AND_RETURN_RET_LOG(object != nullptr, AVCS_ERR_CREATE_CODECLIST_STUB_FAILED,
128 "Failed to create AVCodecListServiceStub");
129
130 pid_t pid = IPCSkeleton::GetCallingPid();
131 codecListStubMap_[object] = pid;
132 AVCODEC_LOGD("The number of codeclist services(%{public}zu).", codecListStubMap_.size());
133 return AVCS_ERR_OK;
134 }
135 #endif
136 #ifdef SUPPORT_CODEC
CreateCodecStubObject(sptr<IRemoteObject> & object)137 int32_t AVCodecServerManager::CreateCodecStubObject(sptr<IRemoteObject> &object)
138 {
139 static std::atomic<int32_t> instanceId = 0;
140 sptr<CodecServiceStub> stub = CodecServiceStub::Create(instanceId);
141 CHECK_AND_RETURN_RET_LOG(stub != nullptr, AVCS_ERR_CREATE_AVCODEC_STUB_FAILED, "Failed to create CodecServiceStub");
142
143 object = stub->AsObject();
144 CHECK_AND_RETURN_RET_LOG(object != nullptr, AVCS_ERR_CREATE_AVCODEC_STUB_FAILED,
145 "Failed to create CodecServiceStub");
146
147 pid_t pid = IPCSkeleton::GetCallingPid();
148 InstanceInfo instanceInfo = {
149 .instanceId = instanceId,
150 .caller = { .pid = pid },
151 };
152 instanceId++;
153 if (instanceId == INT32_MAX) {
154 instanceId = 0;
155 }
156 codecStubMap_.emplace(pid, std::make_pair(object, instanceInfo));
157
158 SetCritical(true);
159 AVCODEC_LOGD("The number of codec services(%{public}zu).", codecStubMap_.size());
160 return AVCS_ERR_OK;
161 }
162 #endif
163
DestroyStubObject(StubType type,sptr<IRemoteObject> object)164 void AVCodecServerManager::DestroyStubObject(StubType type, sptr<IRemoteObject> object)
165 {
166 std::lock_guard<std::shared_mutex> lock(mutex_);
167 pid_t pid = IPCSkeleton::GetCallingPid();
168 switch (type) {
169 case CODEC: {
170 auto it = find_if(codecStubMap_.begin(), codecStubMap_.end(),
171 [object] (std::pair<pid_t, std::pair<sptr<IRemoteObject>, InstanceInfo>> objectPair) ->
172 bool { return objectPair.second.first == object; });
173 CHECK_AND_BREAK_LOG(it != codecStubMap_.end(), "find codec object failed, pid(%{public}d)", pid);
174
175 AVCODEC_LOGI("destroy codec stub services(%{public}zu) pid(%{public}d)", codecStubMap_.size(), pid);
176 codecStubMap_.erase(it);
177 break;
178 }
179 case CODECLIST: {
180 auto it = find_if(codecListStubMap_.begin(), codecListStubMap_.end(),
181 [object] (std::pair<sptr<IRemoteObject>, pid_t> objectPair) ->
182 bool { return objectPair.first == object; });
183 CHECK_AND_BREAK_LOG(it != codecListStubMap_.end(), "find codeclist object failed, pid(%{public}d)", pid);
184
185 AVCODEC_LOGI("destroy codeclist stub services(%{public}zu) pid(%{public}d)", codecListStubMap_.size(), pid);
186 codecListStubMap_.erase(it);
187 break;
188 }
189 default: {
190 AVCODEC_LOGE("default case, av_codec server manager failed, pid(%{public}d)", pid);
191 break;
192 }
193 }
194 if (codecStubMap_.size() == 0) {
195 SetCritical(false);
196 }
197 }
198
EraseObject(std::map<sptr<IRemoteObject>,pid_t> & stubMap,pid_t pid)199 void AVCodecServerManager::EraseObject(std::map<sptr<IRemoteObject>, pid_t>& stubMap, pid_t pid)
200 {
201 for (auto it = stubMap.begin(); it != stubMap.end();) {
202 if (it->second == pid) {
203 executor_.Commit(it->first);
204 it = stubMap.erase(it);
205 } else {
206 it++;
207 }
208 }
209 return;
210 }
211
EraseCodecObjectByPid(pid_t pid)212 void AVCodecServerManager::EraseCodecObjectByPid(pid_t pid)
213 {
214 for (auto it = codecStubMap_.begin(); it != codecStubMap_.end();) {
215 if (it->first == pid) {
216 executor_.Commit(it->second.first);
217 it = codecStubMap_.erase(it);
218 } else {
219 it++;
220 }
221 }
222 return;
223 }
224
DestroyStubObjectForPid(pid_t pid)225 void AVCodecServerManager::DestroyStubObjectForPid(pid_t pid)
226 {
227 std::lock_guard<std::shared_mutex> lock(mutex_);
228 AVCODEC_LOGI("codec stub services(%{public}zu) pid(%{public}d).", codecStubMap_.size(), pid);
229 EraseCodecObjectByPid(pid);
230 AVCODEC_LOGI("codec stub services(%{public}zu).", codecStubMap_.size());
231
232 AVCODEC_LOGI("codeclist stub services(%{public}zu) pid(%{public}d).", codecListStubMap_.size(), pid);
233 EraseObject(codecListStubMap_, pid);
234 AVCODEC_LOGI("codeclist stub services(%{public}zu).", codecListStubMap_.size());
235 executor_.Clear();
236 if (codecStubMap_.size() == 0) {
237 SetCritical(false);
238 }
239 }
240
NotifyProcessStatus(const int32_t status)241 void AVCodecServerManager::NotifyProcessStatus(const int32_t status)
242 {
243 CHECK_AND_RETURN_LOG(notifyProcessStatusFunc_ != nullptr, "notify memory manager is nullptr, %{public}d.", status);
244 int32_t ret = notifyProcessStatusFunc_(pid_, 1, status, AV_CODEC_SERVICE_ID);
245 if (ret == 0) {
246 AVCODEC_LOGI("notify memory manager to %{public}d success.", status);
247 } else {
248 AVCODEC_LOGW("notify memory manager to %{public}d fail.", status);
249 }
250 }
251
SetMemMgrStatus(const bool isStarted)252 void AVCodecServerManager::SetMemMgrStatus(const bool isStarted)
253 {
254 memMgrStarted_ = isStarted;
255 }
256
SetCritical(const bool isKeyService)257 void AVCodecServerManager::SetCritical(const bool isKeyService)
258 {
259 CHECK_AND_RETURN_LOG(memMgrStarted_, "Memory manager service is not started");
260 CHECK_AND_RETURN_LOG(setCriticalFunc_ != nullptr, "set critical is nullptr, %{public}d.", isKeyService);
261 int32_t ret = setCriticalFunc_(pid_, isKeyService, AV_CODEC_SERVICE_ID);
262 if (ret == 0) {
263 AVCODEC_LOGI("set critical to %{public}d success.", isKeyService);
264 } else {
265 AVCODEC_LOGW("set critical to %{public}d fail.", isKeyService);
266 }
267 }
268
GetInstanceCount()269 uint32_t AVCodecServerManager::GetInstanceCount()
270 {
271 std::shared_lock<std::shared_mutex> lock(mutex_);
272 return codecStubMap_.size() + codecListStubMap_.size();
273 }
274
GetInstanceInfoListByPid(pid_t pid)275 std::vector<CodecInstance> AVCodecServerManager::GetInstanceInfoListByPid(pid_t pid)
276 {
277 std::shared_lock<std::shared_mutex> lock(mutex_);
278 std::vector<CodecInstance> instanceInfoList;
279 auto range = codecStubMap_.equal_range(pid);
280 for (auto iter = range.first; iter != range.second; iter++) {
281 instanceInfoList.emplace_back(iter->second);
282 }
283 return instanceInfoList;
284 }
285
GetInstanceInfoListByActualPid(pid_t pid)286 std::vector<CodecInstance> AVCodecServerManager::GetInstanceInfoListByActualPid(pid_t pid)
287 {
288 std::shared_lock<std::shared_mutex> lock(mutex_);
289 std::vector<CodecInstance> instanceInfoList;
290 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
291 auto forwardCallerPid = iter->second.second.forwardCaller.pid;
292 auto callerPid = iter->second.second.caller.pid;
293 auto actualPid = forwardCallerPid == INVALID_PID ? callerPid : forwardCallerPid;
294 if (pid == actualPid) {
295 instanceInfoList.emplace_back(iter->second);
296 }
297 }
298 return instanceInfoList;
299 }
300
GetInstanceInfoByInstanceId(int32_t instanceId)301 std::optional<InstanceInfo> AVCodecServerManager::GetInstanceInfoByInstanceId(int32_t instanceId)
302 {
303 std::shared_lock<std::shared_mutex> lock(mutex_);
304 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
305 if (iter->second.second.instanceId == instanceId) {
306 return iter->second.second;
307 }
308 }
309 return std::nullopt;
310 }
311
SetInstanceInfoByInstanceId(int32_t instanceId,const InstanceInfo & info)312 void AVCodecServerManager::SetInstanceInfoByInstanceId(int32_t instanceId, const InstanceInfo &info)
313 {
314 std::lock_guard<std::shared_mutex> lock(mutex_);
315 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
316 if (iter->second.second.instanceId == instanceId) {
317 iter->second.second = info;
318 }
319 }
320 }
321
Commit(sptr<IRemoteObject> obj)322 void AVCodecServerManager::AsyncExecutor::Commit(sptr<IRemoteObject> obj)
323 {
324 std::lock_guard<std::mutex> lock(listMutex_);
325 freeList_.push_back(obj);
326 }
327
Clear()328 void AVCodecServerManager::AsyncExecutor::Clear()
329 {
330 std::thread(&AVCodecServerManager::AsyncExecutor::HandleAsyncExecution, this).detach();
331 }
332
HandleAsyncExecution()333 void AVCodecServerManager::AsyncExecutor::HandleAsyncExecution()
334 {
335 std::list<sptr<IRemoteObject>> tempList;
336 {
337 std::lock_guard<std::mutex> lock(listMutex_);
338 freeList_.swap(tempList);
339 }
340 tempList.clear();
341 }
342 } // namespace MediaAVCodec
343 } // namespace OHOS
344