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 codecStubMap_.emplace(pid, std::make_pair(object, instanceInfo));
154
155 SetCritical(true);
156 AVCODEC_LOGD("The number of codec services(%{public}zu).", codecStubMap_.size());
157 return AVCS_ERR_OK;
158 }
159 #endif
160
DestroyStubObject(StubType type,sptr<IRemoteObject> object)161 void AVCodecServerManager::DestroyStubObject(StubType type, sptr<IRemoteObject> object)
162 {
163 std::lock_guard<std::shared_mutex> lock(mutex_);
164 pid_t pid = IPCSkeleton::GetCallingPid();
165 switch (type) {
166 case CODEC: {
167 auto it = find_if(codecStubMap_.begin(), codecStubMap_.end(),
168 [object] (std::pair<pid_t, std::pair<sptr<IRemoteObject>, InstanceInfo>> objectPair) ->
169 bool { return objectPair.second.first == object; });
170 CHECK_AND_BREAK_LOG(it != codecStubMap_.end(), "find codec object failed, pid(%{public}d)", pid);
171
172 AVCODEC_LOGI("destroy codec stub services(%{public}zu) pid(%{public}d)", codecStubMap_.size(), pid);
173 codecStubMap_.erase(it);
174 break;
175 }
176 case CODECLIST: {
177 auto it = find_if(codecListStubMap_.begin(), codecListStubMap_.end(),
178 [object] (std::pair<sptr<IRemoteObject>, pid_t> objectPair) ->
179 bool { return objectPair.first == object; });
180 CHECK_AND_BREAK_LOG(it != codecListStubMap_.end(), "find codeclist object failed, pid(%{public}d)", pid);
181
182 AVCODEC_LOGI("destroy codeclist stub services(%{public}zu) pid(%{public}d)", codecListStubMap_.size(), pid);
183 codecListStubMap_.erase(it);
184 break;
185 }
186 default: {
187 AVCODEC_LOGE("default case, av_codec server manager failed, pid(%{public}d)", pid);
188 break;
189 }
190 }
191 if (codecStubMap_.size() == 0) {
192 SetCritical(false);
193 }
194 }
195
EraseObject(std::map<sptr<IRemoteObject>,pid_t> & stubMap,pid_t pid)196 void AVCodecServerManager::EraseObject(std::map<sptr<IRemoteObject>, pid_t>& stubMap, pid_t pid)
197 {
198 for (auto it = stubMap.begin(); it != stubMap.end();) {
199 if (it->second == pid) {
200 executor_.Commit(it->first);
201 it = stubMap.erase(it);
202 } else {
203 it++;
204 }
205 }
206 return;
207 }
208
EraseCodecObjectByPid(pid_t pid)209 void AVCodecServerManager::EraseCodecObjectByPid(pid_t pid)
210 {
211 for (auto it = codecStubMap_.begin(); it != codecStubMap_.end();) {
212 if (it->first == pid) {
213 executor_.Commit(it->second.first);
214 it = codecStubMap_.erase(it);
215 } else {
216 it++;
217 }
218 }
219 return;
220 }
221
DestroyStubObjectForPid(pid_t pid)222 void AVCodecServerManager::DestroyStubObjectForPid(pid_t pid)
223 {
224 std::lock_guard<std::shared_mutex> lock(mutex_);
225 AVCODEC_LOGI("codec stub services(%{public}zu) pid(%{public}d).", codecStubMap_.size(), pid);
226 EraseCodecObjectByPid(pid);
227 AVCODEC_LOGI("codec stub services(%{public}zu).", codecStubMap_.size());
228
229 AVCODEC_LOGI("codeclist stub services(%{public}zu) pid(%{public}d).", codecListStubMap_.size(), pid);
230 EraseObject(codecListStubMap_, pid);
231 AVCODEC_LOGI("codeclist stub services(%{public}zu).", codecListStubMap_.size());
232 executor_.Clear();
233 if (codecStubMap_.size() == 0) {
234 SetCritical(false);
235 }
236 }
237
NotifyProcessStatus(const int32_t status)238 void AVCodecServerManager::NotifyProcessStatus(const int32_t status)
239 {
240 CHECK_AND_RETURN_LOG(notifyProcessStatusFunc_ != nullptr, "notify memory manager is nullptr, %{public}d.", status);
241 int32_t ret = notifyProcessStatusFunc_(pid_, 1, status, AV_CODEC_SERVICE_ID);
242 if (ret == 0) {
243 AVCODEC_LOGI("notify memory manager to %{public}d success.", status);
244 } else {
245 AVCODEC_LOGW("notify memory manager to %{public}d fail.", status);
246 }
247 }
248
SetMemMgrStatus(const bool isStarted)249 void AVCodecServerManager::SetMemMgrStatus(const bool isStarted)
250 {
251 memMgrStarted_ = isStarted;
252 }
253
SetCritical(const bool isKeyService)254 void AVCodecServerManager::SetCritical(const bool isKeyService)
255 {
256 CHECK_AND_RETURN_LOG(memMgrStarted_, "Memory manager service is not started");
257 CHECK_AND_RETURN_LOG(setCriticalFunc_ != nullptr, "set critical is nullptr, %{public}d.", isKeyService);
258 int32_t ret = setCriticalFunc_(pid_, isKeyService, AV_CODEC_SERVICE_ID);
259 if (ret == 0) {
260 AVCODEC_LOGI("set critical to %{public}d success.", isKeyService);
261 } else {
262 AVCODEC_LOGW("set critical to %{public}d fail.", isKeyService);
263 }
264 }
265
GetInstanceInfoListByPid(pid_t pid)266 std::vector<CodecInstance> AVCodecServerManager::GetInstanceInfoListByPid(pid_t pid)
267 {
268 std::shared_lock<std::shared_mutex> lock(mutex_);
269 std::vector<CodecInstance> instanceInfoList;
270 auto range = codecStubMap_.equal_range(pid);
271 for (auto iter = range.first; iter != range.second; iter++) {
272 instanceInfoList.emplace_back(iter->second);
273 }
274 return instanceInfoList;
275 }
276
GetInstanceInfoListByActualPid(pid_t pid)277 std::vector<CodecInstance> AVCodecServerManager::GetInstanceInfoListByActualPid(pid_t pid)
278 {
279 std::shared_lock<std::shared_mutex> lock(mutex_);
280 std::vector<CodecInstance> instanceInfoList;
281 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
282 auto forwardCallerPid = iter->second.second.forwardCaller.pid;
283 auto callerPid = iter->second.second.caller.pid;
284 auto actualPid = forwardCallerPid == INVALID_PID ? callerPid : forwardCallerPid;
285 if (pid == actualPid) {
286 instanceInfoList.emplace_back(iter->second);
287 }
288 }
289 return instanceInfoList;
290 }
291
GetInstanceInfoByInstanceId(int32_t instanceId)292 std::optional<InstanceInfo> AVCodecServerManager::GetInstanceInfoByInstanceId(int32_t instanceId)
293 {
294 std::shared_lock<std::shared_mutex> lock(mutex_);
295 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
296 if (iter->second.second.instanceId == instanceId) {
297 return iter->second.second;
298 }
299 }
300 return std::nullopt;
301 }
302
SetInstanceInfoByInstanceId(int32_t instanceId,const InstanceInfo & info)303 void AVCodecServerManager::SetInstanceInfoByInstanceId(int32_t instanceId, const InstanceInfo &info)
304 {
305 std::lock_guard<std::shared_mutex> lock(mutex_);
306 for (auto iter = codecStubMap_.begin(); iter != codecStubMap_.end(); iter++) {
307 if (iter->second.second.instanceId == instanceId) {
308 iter->second.second = info;
309 }
310 }
311 }
312
Commit(sptr<IRemoteObject> obj)313 void AVCodecServerManager::AsyncExecutor::Commit(sptr<IRemoteObject> obj)
314 {
315 std::lock_guard<std::mutex> lock(listMutex_);
316 freeList_.push_back(obj);
317 }
318
Clear()319 void AVCodecServerManager::AsyncExecutor::Clear()
320 {
321 std::thread(&AVCodecServerManager::AsyncExecutor::HandleAsyncExecution, this).detach();
322 }
323
HandleAsyncExecution()324 void AVCodecServerManager::AsyncExecutor::HandleAsyncExecution()
325 {
326 std::list<sptr<IRemoteObject>> tempList;
327 {
328 std::lock_guard<std::mutex> lock(listMutex_);
329 freeList_.swap(tempList);
330 }
331 tempList.clear();
332 }
333 } // namespace MediaAVCodec
334 } // namespace OHOS
335