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_client.h"
17 #include <thread>
18 #include "avcodec_xcollie.h"
19 #include "ipc_skeleton.h"
20 #include "iservice_registry.h"
21 #include "system_ability_definition.h"
22 #include "avcodec_trace.h"
23 #include "avcodec_sysevent.h"
24
25 #ifdef SUPPORT_CODEC
26 #include "i_standard_codec_service.h"
27 #endif
28 #ifdef SUPPORT_CODECLIST
29 #include "i_standard_codeclist_service.h"
30 #endif
31
32 #include "avcodec_errors.h"
33 #include "avcodec_log.h"
34
35 namespace {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecClient"};
37 }
38
39 namespace OHOS {
40 namespace MediaAVCodec {
41 static bool g_isDestructed = false;
42 static std::mutex g_avCodecClientMutex;
43 static AVCodecClient g_avCodecClientInstance;
GetInstance()44 IAVCodecService &AVCodecServiceFactory::GetInstance()
45 {
46 return g_avCodecClientInstance;
47 }
48
AVCodecClient()49 AVCodecClient::AVCodecClient() noexcept
50 {
51 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
52 }
53
~AVCodecClient()54 AVCodecClient::~AVCodecClient()
55 {
56 std::lock_guard<std::mutex> lock(g_avCodecClientMutex);
57 g_isDestructed = true;
58 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
59 }
60
IsAlived()61 bool AVCodecClient::IsAlived()
62 {
63 if (avCodecProxy_ == nullptr) {
64 avCodecProxy_ = GetAVCodecProxy();
65 }
66
67 return avCodecProxy_ != nullptr;
68 }
69
CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility subSystemId,sptr<IRemoteObject> & object,uint32_t tryTimes)70 int32_t AVCodecClient::CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility subSystemId,
71 sptr<IRemoteObject> &object,
72 uint32_t tryTimes)
73 {
74 int32_t ret = AVCS_ERR_OK;
75 do {
76 if (!IsAlived()) {
77 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
78 continue;
79 }
80
81 ret = avCodecProxy_->GetSubSystemAbility(subSystemId, listenerStub_->AsObject(), object);
82 if (object != nullptr) {
83 break;
84 }
85 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
86 continue;
87 } while (--tryTimes);
88 return ret;
89 }
90
SuspendFreeze(const std::vector<pid_t> & pidList)91 int32_t AVCodecClient::SuspendFreeze(const std::vector<pid_t> &pidList)
92 {
93 std::lock_guard<std::mutex> lock(mutex_);
94 auto avCodecProxy = GetTemporaryAVCodecProxy();
95 CHECK_AND_RETURN_RET_LOG(avCodecProxy != nullptr, AVCS_ERR_SERVICE_DIED, "AVCodec proxy does not exist");
96 return avCodecProxy->SuspendFreeze(pidList);
97 }
98
SuspendActive(const std::vector<pid_t> & pidList)99 int32_t AVCodecClient::SuspendActive(const std::vector<pid_t> &pidList)
100 {
101 std::lock_guard<std::mutex> lock(mutex_);
102 auto avCodecProxy = GetTemporaryAVCodecProxy();
103 CHECK_AND_RETURN_RET_LOG(avCodecProxy != nullptr, AVCS_ERR_SERVICE_DIED, "AVCodec proxy does not exist");
104 return avCodecProxy->SuspendActive(pidList);
105 }
106
SuspendActiveAll()107 int32_t AVCodecClient::SuspendActiveAll()
108 {
109 std::lock_guard<std::mutex> lock(mutex_);
110 auto avCodecProxy = GetTemporaryAVCodecProxy();
111 CHECK_AND_RETURN_RET_LOG(avCodecProxy != nullptr, AVCS_ERR_SERVICE_DIED, "AVCodec proxy does not exist");
112 return avCodecProxy->SuspendActiveAll();
113 }
114
115 #ifdef SUPPORT_CODEC
CreateCodecService(std::shared_ptr<ICodecService> & codecClient)116 int32_t AVCodecClient::CreateCodecService(std::shared_ptr<ICodecService> &codecClient)
117 {
118 std::lock_guard<std::mutex> lock(mutex_);
119
120 sptr<IRemoteObject> object = nullptr;
121 int32_t ret = CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility::AVCODEC_CODEC, object);
122 CHECK_AND_RETURN_RET_LOG(object != nullptr, ret, "Create codec proxy object failed.");
123
124 sptr<IStandardCodecService> codecProxy = iface_cast<IStandardCodecService>(object);
125 CHECK_AND_RETURN_RET_LOG(codecProxy != nullptr, AVCS_ERR_UNSUPPORT, "Codec proxy is nullptr.");
126
127 ret = CodecClient::Create(codecProxy, codecClient);
128 CHECK_AND_RETURN_RET_LOG(codecClient != nullptr, ret, "Failed to create codec client.");
129
130 codecClientList_.push_back(codecClient);
131 return AVCS_ERR_OK;
132 }
133
DestroyCodecService(std::shared_ptr<ICodecService> codecClient)134 int32_t AVCodecClient::DestroyCodecService(std::shared_ptr<ICodecService> codecClient)
135 {
136 std::lock_guard<std::mutex> lock(mutex_);
137 CHECK_AND_RETURN_RET_LOG(codecClient != nullptr, AVCS_ERR_NO_MEMORY, "codec client is nullptr.");
138 codecClientList_.remove(codecClient);
139 return AVCS_ERR_OK;
140 }
141 #endif
142 #ifdef SUPPORT_CODECLIST
CreateCodecListService()143 std::shared_ptr<ICodecListService> AVCodecClient::CreateCodecListService()
144 {
145 std::lock_guard<std::mutex> lock(mutex_);
146
147 sptr<IRemoteObject> object = nullptr;
148 (void)CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility::AVCODEC_CODECLIST, object);
149 CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "Create codeclist proxy object failed.");
150
151 sptr<IStandardCodecListService> codecListProxy = iface_cast<IStandardCodecListService>(object);
152 CHECK_AND_RETURN_RET_LOG(codecListProxy != nullptr, nullptr, "codeclist proxy is nullptr.");
153
154 std::shared_ptr<CodecListClient> codecListClient = CodecListClient::Create(codecListProxy);
155 CHECK_AND_RETURN_RET_LOG(codecListClient != nullptr, nullptr, "failed to create codeclist client.");
156
157 codecListClientList_.push_back(codecListClient);
158 return codecListClient;
159 }
160
DestroyCodecListService(std::shared_ptr<ICodecListService> codecListClient)161 int32_t AVCodecClient::DestroyCodecListService(std::shared_ptr<ICodecListService> codecListClient)
162 {
163 std::lock_guard<std::mutex> lock(mutex_);
164 CHECK_AND_RETURN_RET_LOG(codecListClient != nullptr, AVCS_ERR_NO_MEMORY, "codeclist client is nullptr.");
165 codecListClientList_.remove(codecListClient);
166 return AVCS_ERR_OK;
167 }
168 #endif
169
GetAVCodecProxy()170 sptr<IStandardAVCodecService> AVCodecClient::GetAVCodecProxy()
171 {
172 AVCODEC_LOGI("In");
173 sptr<ISystemAbilityManager> samgr = nullptr;
174 CLIENT_COLLIE_LISTEN(samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(),
175 "AVCodecClient GetAVCodecProxy");
176 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "system ability manager is nullptr.");
177
178 sptr<IRemoteObject> object = nullptr;
179 CLIENT_COLLIE_LISTEN(object = samgr->CheckSystemAbility(OHOS::AV_CODEC_SERVICE_ID),
180 "AVCodecClient GetAVCodecProxy");
181 if (object == nullptr) {
182 CLIENT_COLLIE_LISTEN(object = samgr->LoadSystemAbility(OHOS::AV_CODEC_SERVICE_ID, 30), // 30: timeout
183 "AVCodecClient LoadSystemAbility");
184 CHECK_AND_RETURN_RET_LOG(object != nullptr,
185 nullptr, "AVCodec object is nullptr, maybe avcodec service does not exist");
186 }
187
188 avCodecProxy_ = iface_cast<IStandardAVCodecService>(object);
189 CHECK_AND_RETURN_RET_LOG(avCodecProxy_ != nullptr, nullptr, "AVCodec proxy is nullptr");
190
191 pid_t pid = 0;
192 deathRecipient_ = new (std::nothrow) AVCodecDeathRecipient(pid);
193 CHECK_AND_RETURN_RET_LOG(deathRecipient_ != nullptr, nullptr, "Failed to create AVCodecDeathRecipient");
194
195 deathRecipient_->SetNotifyCb(std::bind(&AVCodecClient::AVCodecServerDied, std::placeholders::_1));
196 bool result = object->AddDeathRecipient(deathRecipient_);
197 CHECK_AND_RETURN_RET_LOG(result, nullptr, "Failed to add deathRecipient");
198
199 listenerStub_ = new (std::nothrow) AVCodecListenerStub();
200 CHECK_AND_RETURN_RET_LOG(listenerStub_ != nullptr, nullptr, "Failed to create AVCodecListenerStub");
201 return avCodecProxy_;
202 }
203
GetTemporaryAVCodecProxy()204 sptr<IStandardAVCodecService> AVCodecClient::GetTemporaryAVCodecProxy()
205 {
206 AVCODEC_LOGD("In");
207 sptr<ISystemAbilityManager> samgr = nullptr;
208 CLIENT_COLLIE_LISTEN(samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(),
209 "AVCodecClient GetTemporaryAVCodecProxy");
210 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "system ability manager is nullptr.");
211
212 sptr<IRemoteObject> object = nullptr;
213 CLIENT_COLLIE_LISTEN(object = samgr->CheckSystemAbility(OHOS::AV_CODEC_SERVICE_ID),
214 "AVCodec object is nullptr, maybe avcodec service does not exist");
215
216 sptr<IStandardAVCodecService> avCodecProxy = iface_cast<IStandardAVCodecService>(object);
217 CHECK_AND_RETURN_RET_LOG(avCodecProxy != nullptr, nullptr, "AVCodec proxy is nullptr");
218
219 return avCodecProxy;
220 }
221
AVCodecServerDied(pid_t pid)222 void AVCodecClient::AVCodecServerDied(pid_t pid)
223 {
224 std::lock_guard<std::mutex> lock(g_avCodecClientMutex);
225 CHECK_AND_RETURN_LOG(!g_isDestructed, "AVCodecClient is destructed");
226
227 AVCODEC_LOGE("AVCodec service is died, pid:%{public}d!", pid);
228 g_avCodecClientInstance.DoAVCodecServerDied();
229 FaultEventWrite(FaultType::FAULT_TYPE_CRASH, "AVCodec service is died", "AVCodecClient");
230 }
231
DoAVCodecServerDied()232 void AVCodecClient::DoAVCodecServerDied()
233 {
234 std::lock_guard<std::mutex> lock(mutex_);
235 if (avCodecProxy_ != nullptr) {
236 (void)avCodecProxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
237 avCodecProxy_ = nullptr;
238 }
239 listenerStub_ = nullptr;
240 deathRecipient_ = nullptr;
241
242 #ifdef SUPPORT_CODEC
243 for (auto &it : codecClientList_) {
244 auto codecClient = std::static_pointer_cast<CodecClient>(it);
245 if (codecClient != nullptr) {
246 codecClient->AVCodecServerDied();
247 }
248 }
249 #endif
250 #ifdef SUPPORT_CODECLIST
251 for (auto &it : codecListClientList_) {
252 auto codecListClient = std::static_pointer_cast<CodecListClient>(it);
253 if (codecListClient != nullptr) {
254 codecListClient->AVCodecServerDied();
255 }
256 }
257 #endif
258 }
259 } // namespace MediaAVCodec
260 } // namespace OHOS
261