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