• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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