• 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     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