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
91 #ifdef SUPPORT_CODEC
CreateCodecService(std::shared_ptr<ICodecService> & codecClient)92 int32_t AVCodecClient::CreateCodecService(std::shared_ptr<ICodecService> &codecClient)
93 {
94 std::lock_guard<std::mutex> lock(mutex_);
95
96 sptr<IRemoteObject> object = nullptr;
97 int32_t ret = CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility::AVCODEC_CODEC, object);
98 CHECK_AND_RETURN_RET_LOG(object != nullptr, ret, "Create codec proxy object failed.");
99
100 sptr<IStandardCodecService> codecProxy = iface_cast<IStandardCodecService>(object);
101 CHECK_AND_RETURN_RET_LOG(codecProxy != nullptr, AVCS_ERR_UNSUPPORT, "Codec proxy is nullptr.");
102
103 ret = CodecClient::Create(codecProxy, codecClient);
104 CHECK_AND_RETURN_RET_LOG(codecClient != nullptr, ret, "Failed to create codec client.");
105
106 codecClientList_.push_back(codecClient);
107 return AVCS_ERR_OK;
108 }
109
DestroyCodecService(std::shared_ptr<ICodecService> codecClient)110 int32_t AVCodecClient::DestroyCodecService(std::shared_ptr<ICodecService> codecClient)
111 {
112 std::lock_guard<std::mutex> lock(mutex_);
113 CHECK_AND_RETURN_RET_LOG(codecClient != nullptr, AVCS_ERR_NO_MEMORY, "codec client is nullptr.");
114 codecClientList_.remove(codecClient);
115 return AVCS_ERR_OK;
116 }
117 #endif
118 #ifdef SUPPORT_CODECLIST
CreateCodecListService()119 std::shared_ptr<ICodecListService> AVCodecClient::CreateCodecListService()
120 {
121 std::lock_guard<std::mutex> lock(mutex_);
122
123 sptr<IRemoteObject> object = nullptr;
124 (void)CreateInstanceAndTryInTimes(IStandardAVCodecService::AVCodecSystemAbility::AVCODEC_CODECLIST, object);
125 CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "Create codeclist proxy object failed.");
126
127 sptr<IStandardCodecListService> codecListProxy = iface_cast<IStandardCodecListService>(object);
128 CHECK_AND_RETURN_RET_LOG(codecListProxy != nullptr, nullptr, "codeclist proxy is nullptr.");
129
130 std::shared_ptr<CodecListClient> codecListClient = CodecListClient::Create(codecListProxy);
131 CHECK_AND_RETURN_RET_LOG(codecListClient != nullptr, nullptr, "failed to create codeclist client.");
132
133 codecListClientList_.push_back(codecListClient);
134 return codecListClient;
135 }
136
DestroyCodecListService(std::shared_ptr<ICodecListService> codecListClient)137 int32_t AVCodecClient::DestroyCodecListService(std::shared_ptr<ICodecListService> codecListClient)
138 {
139 std::lock_guard<std::mutex> lock(mutex_);
140 CHECK_AND_RETURN_RET_LOG(codecListClient != nullptr, AVCS_ERR_NO_MEMORY, "codeclist client is nullptr.");
141 codecListClientList_.remove(codecListClient);
142 return AVCS_ERR_OK;
143 }
144 #endif
145
GetAVCodecProxy()146 sptr<IStandardAVCodecService> AVCodecClient::GetAVCodecProxy()
147 {
148 AVCODEC_LOGI("In");
149 sptr<ISystemAbilityManager> samgr = nullptr;
150 CLIENT_COLLIE_LISTEN(samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(),
151 "AVCodecClient GetAVCodecProxy");
152 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "system ability manager is nullptr.");
153
154 sptr<IRemoteObject> object = nullptr;
155 CLIENT_COLLIE_LISTEN(object = samgr->CheckSystemAbility(OHOS::AV_CODEC_SERVICE_ID),
156 "AVCodecClient GetAVCodecProxy");
157 if (object == nullptr) {
158 CLIENT_COLLIE_LISTEN(object = samgr->LoadSystemAbility(OHOS::AV_CODEC_SERVICE_ID, 30), // 30: timeout
159 "AVCodecClient LoadSystemAbility");
160 CHECK_AND_RETURN_RET_LOG(object != nullptr,
161 nullptr, "AVCodec object is nullptr, maybe avcodec service does not exist");
162 }
163
164 avCodecProxy_ = iface_cast<IStandardAVCodecService>(object);
165 CHECK_AND_RETURN_RET_LOG(avCodecProxy_ != nullptr, nullptr, "AVCodec proxy is nullptr");
166
167 pid_t pid = 0;
168 deathRecipient_ = new (std::nothrow) AVCodecDeathRecipient(pid);
169 CHECK_AND_RETURN_RET_LOG(deathRecipient_ != nullptr, nullptr, "Failed to create AVCodecDeathRecipient");
170
171 deathRecipient_->SetNotifyCb(std::bind(&AVCodecClient::AVCodecServerDied, std::placeholders::_1));
172 bool result = object->AddDeathRecipient(deathRecipient_);
173 CHECK_AND_RETURN_RET_LOG(result, nullptr, "Failed to add deathRecipient");
174
175 listenerStub_ = new (std::nothrow) AVCodecListenerStub();
176 CHECK_AND_RETURN_RET_LOG(listenerStub_ != nullptr, nullptr, "Failed to create AVCodecListenerStub");
177 return avCodecProxy_;
178 }
179
AVCodecServerDied(pid_t pid)180 void AVCodecClient::AVCodecServerDied(pid_t pid)
181 {
182 std::lock_guard<std::mutex> lock(g_avCodecClientMutex);
183 CHECK_AND_RETURN_LOG(!g_isDestructed, "AVCodecClient is destructed");
184
185 AVCODEC_LOGE("AVCodec service is died, pid:%{public}d!", pid);
186 g_avCodecClientInstance.DoAVCodecServerDied();
187 FaultEventWrite(FaultType::FAULT_TYPE_CRASH, "AVCodec service is died", "AVCodecClient");
188 }
189
DoAVCodecServerDied()190 void AVCodecClient::DoAVCodecServerDied()
191 {
192 std::lock_guard<std::mutex> lock(mutex_);
193 if (avCodecProxy_ != nullptr) {
194 (void)avCodecProxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
195 avCodecProxy_ = nullptr;
196 }
197 listenerStub_ = nullptr;
198 deathRecipient_ = nullptr;
199
200 #ifdef SUPPORT_CODEC
201 for (auto &it : codecClientList_) {
202 auto codecClient = std::static_pointer_cast<CodecClient>(it);
203 if (codecClient != nullptr) {
204 codecClient->AVCodecServerDied();
205 }
206 }
207 #endif
208 #ifdef SUPPORT_CODECLIST
209 for (auto &it : codecListClientList_) {
210 auto codecListClient = std::static_pointer_cast<CodecListClient>(it);
211 if (codecListClient != nullptr) {
212 codecListClient->AVCodecServerDied();
213 }
214 }
215 #endif
216 }
217 } // namespace MediaAVCodec
218 } // namespace OHOS
219