blob: 4c2d5d35ef76fc3f0485bfd7345e787429b0889c [file] [log] [blame]
Wonsik Kim5ec480f2023-07-11 14:25:55 -07001/*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
Wonsik Kimf0032642023-07-20 14:42:27 -070018#define LOG_TAG "Codec2-Component-Aidl"
Wonsik Kim5ec480f2023-07-11 14:25:55 -070019#include <android-base/logging.h>
20
Wonsik Kimf0032642023-07-20 14:42:27 -070021#include <codec2/aidl/Component.h>
22#include <codec2/aidl/ComponentStore.h>
23#include <codec2/aidl/InputBufferManager.h>
Wonsik Kim5ec480f2023-07-11 14:25:55 -070024
25#ifndef __ANDROID_APEX__
26#include <FilterWrapper.h>
27#endif
28
Wonsik Kimf0032642023-07-20 14:42:27 -070029#include <android/binder_auto_utils.h>
30#include <android/binder_interface_utils.h>
Wonsik Kim5ec480f2023-07-11 14:25:55 -070031#include <utils/Timers.h>
32
Wonsik Kim5ec480f2023-07-11 14:25:55 -070033#include <C2Debug.h>
34#include <C2PlatformSupport.h>
35
36#include <chrono>
37#include <thread>
38
Wonsik Kimf0032642023-07-20 14:42:27 -070039namespace aidl {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070040namespace android {
41namespace hardware {
42namespace media {
43namespace c2 {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070044namespace utils {
45
Wonsik Kimf0032642023-07-20 14:42:27 -070046using ::aidl::android::hardware::common::NativeHandle;
47using ::aidl::android::hardware::media::bufferpool2::IClientManager;
48using ::ndk::ScopedAStatus;
Wonsik Kim5ec480f2023-07-11 14:25:55 -070049
50// ComponentListener wrapper
51struct Component::Listener : public C2Component::Listener {
52
Wonsik Kimf0032642023-07-20 14:42:27 -070053 Listener(const std::shared_ptr<Component>& component) :
Wonsik Kim5ec480f2023-07-11 14:25:55 -070054 mComponent(component),
55 mListener(component->mListener) {
56 }
57
58 virtual void onError_nb(
59 std::weak_ptr<C2Component> /* c2component */,
60 uint32_t errorCode) override {
Wonsik Kimf0032642023-07-20 14:42:27 -070061 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -070062 if (listener) {
Wonsik Kimf0032642023-07-20 14:42:27 -070063 ScopedAStatus transStatus = listener->onError(Status{Status::OK}, errorCode);
Wonsik Kim5ec480f2023-07-11 14:25:55 -070064 if (!transStatus.isOk()) {
65 LOG(ERROR) << "Component::Listener::onError_nb -- "
66 << "transaction failed.";
67 }
68 }
69 }
70
71 virtual void onTripped_nb(
72 std::weak_ptr<C2Component> /* c2component */,
73 std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
74 ) override {
Wonsik Kimf0032642023-07-20 14:42:27 -070075 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -070076 if (listener) {
Wonsik Kimf0032642023-07-20 14:42:27 -070077 std::vector<SettingResult> settingResults(c2settingResult.size());
Wonsik Kim5ec480f2023-07-11 14:25:55 -070078 size_t ix = 0;
79 for (const std::shared_ptr<C2SettingResult> &c2result :
80 c2settingResult) {
81 if (c2result) {
Wonsik Kimf0032642023-07-20 14:42:27 -070082 if (!ToAidl(&settingResults[ix++], *c2result)) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -070083 break;
84 }
85 }
86 }
87 settingResults.resize(ix);
Wonsik Kimf0032642023-07-20 14:42:27 -070088 ScopedAStatus transStatus = listener->onTripped(settingResults);
Wonsik Kim5ec480f2023-07-11 14:25:55 -070089 if (!transStatus.isOk()) {
90 LOG(ERROR) << "Component::Listener::onTripped_nb -- "
91 << "transaction failed.";
92 }
93 }
94 }
95
96 virtual void onWorkDone_nb(
97 std::weak_ptr<C2Component> /* c2component */,
98 std::list<std::unique_ptr<C2Work>> c2workItems) override {
99 for (const std::unique_ptr<C2Work>& work : c2workItems) {
100 if (work) {
101 if (work->worklets.empty()
102 || !work->worklets.back()
103 || (work->worklets.back()->output.flags &
104 C2FrameData::FLAG_INCOMPLETE) == 0) {
105 InputBufferManager::
106 unregisterFrameData(mListener, work->input);
107 }
108 }
109 }
110
Wonsik Kimf0032642023-07-20 14:42:27 -0700111 std::shared_ptr<IComponentListener> listener = mListener.lock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700112 if (listener) {
113 WorkBundle workBundle;
114
Wonsik Kimf0032642023-07-20 14:42:27 -0700115 std::shared_ptr<Component> strongComponent = mComponent.lock();
Wonsik Kimf0032642023-07-20 14:42:27 -0700116 if (!ToAidl(&workBundle, c2workItems, strongComponent ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700117 &strongComponent->mBufferPoolSender : nullptr)) {
118 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
119 << "received corrupted work items.";
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700120 return;
121 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700122 ScopedAStatus transStatus = listener->onWorkDone(workBundle);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700123 if (!transStatus.isOk()) {
124 LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
125 << "transaction failed.";
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700126 return;
127 }
Sungtak Lee72dfba62023-09-07 23:26:30 +0000128 // If output blocks are originally owned by the client(not by HAL),
129 // return the ownership to the client. (Since the blocks are
130 // transferred to the client here.)
131 ReturnOutputBlocksToClientIfNeeded(c2workItems);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700132 }
133 }
134
135protected:
Wonsik Kimf0032642023-07-20 14:42:27 -0700136 std::weak_ptr<Component> mComponent;
137 std::weak_ptr<IComponentListener> mListener;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700138};
139
Wonsik Kimf0032642023-07-20 14:42:27 -0700140// Component::DeathContext
141struct Component::DeathContext {
142 std::weak_ptr<Component> mWeakComp;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700143};
144
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700145// Component
146Component::Component(
147 const std::shared_ptr<C2Component>& component,
Wonsik Kimf0032642023-07-20 14:42:27 -0700148 const std::shared_ptr<IComponentListener>& listener,
149 const std::shared_ptr<ComponentStore>& store,
150 const std::shared_ptr<IClientManager>& clientPoolManager)
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700151 : mComponent{component},
Wonsik Kimf0032642023-07-20 14:42:27 -0700152 mInterface{SharedRefBase::make<ComponentInterface>(
153 component->intf(), store->getParameterCache())},
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700154 mListener{listener},
155 mStore{store},
Wonsik Kimf0032642023-07-20 14:42:27 -0700156 mBufferPoolSender{clientPoolManager},
157 mDeathContext(nullptr) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700158 // Retrieve supported parameters from store
159 // TODO: We could cache this per component/interface type
160 mInit = mInterface->status();
161}
162
163c2_status_t Component::status() const {
164 return mInit;
165}
166
167// Methods from ::android::hardware::media::c2::V1_1::IComponent
Wonsik Kimf0032642023-07-20 14:42:27 -0700168ScopedAStatus Component::queue(const WorkBundle& workBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700169 std::list<std::unique_ptr<C2Work>> c2works;
170
Wonsik Kimf0032642023-07-20 14:42:27 -0700171 if (!FromAidl(&c2works, workBundle)) {
172 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700173 }
174
175 // Register input buffers.
176 for (const std::unique_ptr<C2Work>& work : c2works) {
177 if (work) {
178 InputBufferManager::
179 registerFrameData(mListener, work->input);
180 }
181 }
182
Wonsik Kimf0032642023-07-20 14:42:27 -0700183 c2_status_t err = mComponent->queue_nb(&c2works);
184 if (err == C2_OK) {
185 return ScopedAStatus::ok();
186 }
187 return ScopedAStatus::fromServiceSpecificError(err);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700188}
189
Wonsik Kimf0032642023-07-20 14:42:27 -0700190ScopedAStatus Component::flush(WorkBundle *flushedWorkBundle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700191 std::list<std::unique_ptr<C2Work>> c2flushedWorks;
192 c2_status_t c2res = mComponent->flush_sm(
193 C2Component::FLUSH_COMPONENT,
194 &c2flushedWorks);
195
196 // Unregister input buffers.
197 for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
198 if (work) {
199 if (work->worklets.empty()
200 || !work->worklets.back()
201 || (work->worklets.back()->output.flags &
202 C2FrameData::FLAG_INCOMPLETE) == 0) {
203 InputBufferManager::
204 unregisterFrameData(mListener, work->input);
205 }
206 }
207 }
208
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700209 if (c2res == C2_OK) {
Wonsik Kimf0032642023-07-20 14:42:27 -0700210 if (!ToAidl(flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
211 c2res = C2_CORRUPTED;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700212 }
213 }
Sungtak Lee72dfba62023-09-07 23:26:30 +0000214 // If output blocks are originally owned by the client(not by HAL),
215 // return the ownership to the client. (Since the blocks are
216 // transferred to the client here.)
217 ReturnOutputBlocksToClientIfNeeded(c2flushedWorks);
Wonsik Kimf0032642023-07-20 14:42:27 -0700218 if (c2res == C2_OK) {
219 return ScopedAStatus::ok();
220 }
221 return ScopedAStatus::fromServiceSpecificError(c2res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700222}
223
Wonsik Kimf0032642023-07-20 14:42:27 -0700224ScopedAStatus Component::drain(bool withEos) {
225 c2_status_t res = mComponent->drain_nb(withEos ?
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700226 C2Component::DRAIN_COMPONENT_WITH_EOS :
Wonsik Kimf0032642023-07-20 14:42:27 -0700227 C2Component::DRAIN_COMPONENT_NO_EOS);
228 if (res == C2_OK) {
229 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700230 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700231 return ScopedAStatus::fromServiceSpecificError(res);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700232}
233
234namespace /* unnamed */ {
235
236struct BlockPoolIntf : public ConfigurableC2Intf {
237 BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
238 : ConfigurableC2Intf{
239 "C2BlockPool:" +
240 (pool ? std::to_string(pool->getLocalId()) : "null"),
241 0},
242 mPool{pool} {
243 }
244
245 virtual c2_status_t config(
246 const std::vector<C2Param*>& params,
247 c2_blocking_t mayBlock,
248 std::vector<std::unique_ptr<C2SettingResult>>* const failures
249 ) override {
250 (void)params;
251 (void)mayBlock;
252 (void)failures;
253 return C2_OK;
254 }
255
256 virtual c2_status_t query(
257 const std::vector<C2Param::Index>& indices,
258 c2_blocking_t mayBlock,
259 std::vector<std::unique_ptr<C2Param>>* const params
260 ) const override {
261 (void)indices;
262 (void)mayBlock;
263 (void)params;
264 return C2_OK;
265 }
266
267 virtual c2_status_t querySupportedParams(
268 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
269 ) const override {
270 (void)params;
271 return C2_OK;
272 }
273
274 virtual c2_status_t querySupportedValues(
275 std::vector<C2FieldSupportedValuesQuery>& fields,
276 c2_blocking_t mayBlock) const override {
277 (void)fields;
278 (void)mayBlock;
279 return C2_OK;
280 }
281
282protected:
283 std::shared_ptr<C2BlockPool> mPool;
284};
285
286} // unnamed namespace
287
Wonsik Kimf0032642023-07-20 14:42:27 -0700288ScopedAStatus Component::createBlockPool(
289 const IComponent::BlockPoolAllocator &allocator,
290 IComponent::BlockPool *blockPool) {
291 std::shared_ptr<C2BlockPool> c2BlockPool;
292 static constexpr IComponent::BlockPoolAllocator::Tag ALLOCATOR_ID =
293 IComponent::BlockPoolAllocator::allocatorId;
294 static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
Sungtak Lee0489c872023-10-28 01:18:46 +0000295 IComponent::BlockPoolAllocator::allocator;
Wonsik Kimf0032642023-07-20 14:42:27 -0700296 c2_status_t status = C2_OK;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000297 ::android::C2PlatformAllocatorDesc allocatorParam;
Wonsik Kimf0032642023-07-20 14:42:27 -0700298 switch (allocator.getTag()) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000299 case ALLOCATOR_ID: {
300 allocatorParam.allocatorId =
301 allocator.get<IComponent::BlockPoolAllocator::allocatorId>();
302 }
303 break;
304 case IGBA: {
305 allocatorParam.allocatorId = ::android::C2PlatformAllocatorStore::IGBA;
306 allocatorParam.igba =
307 allocator.get<IComponent::BlockPoolAllocator::allocator>().igba;
308 allocatorParam.waitableFd.reset(
309 allocator.get<IComponent::BlockPoolAllocator::allocator>()
310 .waitableFd.dup().release());
311 }
312 break;
Wonsik Kimf0032642023-07-20 14:42:27 -0700313 default:
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000314 return ScopedAStatus::fromServiceSpecificError(C2_CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700315 }
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000316#ifdef __ANDROID_APEX__
317 status = ::android::CreateCodec2BlockPool(
318 allocatorParam,
319 mComponent,
320 &c2BlockPool);
321#else
322 status = ComponentStore::GetFilterWrapper()->createBlockPool(
323 allocatorParam,
324 mComponent,
325 &c2BlockPool);
326#endif
327 if (status != C2_OK) {
328 return ScopedAStatus::fromServiceSpecificError(status);
329 }
330 {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700331 mBlockPoolsMutex.lock();
Wonsik Kimf0032642023-07-20 14:42:27 -0700332 mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700333 mBlockPoolsMutex.unlock();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700334 }
335
Wonsik Kimf0032642023-07-20 14:42:27 -0700336 blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
337 blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
338 std::make_unique<BlockPoolIntf>(c2BlockPool));
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000339 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700340}
341
Wonsik Kimf0032642023-07-20 14:42:27 -0700342ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700343 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
Wonsik Kimf0032642023-07-20 14:42:27 -0700344 if (mBlockPools.erase(blockPoolId) == 1) {
345 return ScopedAStatus::ok();
346 }
347 return ScopedAStatus::fromServiceSpecificError(Status::CORRUPTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700348}
349
Wonsik Kimf0032642023-07-20 14:42:27 -0700350ScopedAStatus Component::start() {
351 c2_status_t status = mComponent->start();
352 if (status == C2_OK) {
353 return ScopedAStatus::ok();
354 }
355 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700356}
357
Wonsik Kimf0032642023-07-20 14:42:27 -0700358ScopedAStatus Component::stop() {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700359 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700360 c2_status_t status = mComponent->stop();
361 if (status == C2_OK) {
362 return ScopedAStatus::ok();
363 }
364 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700365}
366
Wonsik Kimf0032642023-07-20 14:42:27 -0700367ScopedAStatus Component::reset() {
368 c2_status_t status = mComponent->reset();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700369 {
370 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
371 mBlockPools.clear();
372 }
373 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700374 if (status == C2_OK) {
375 return ScopedAStatus::ok();
376 }
377 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700378}
379
Wonsik Kimf0032642023-07-20 14:42:27 -0700380ScopedAStatus Component::release() {
381 c2_status_t status = mComponent->release();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700382 {
383 std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
384 mBlockPools.clear();
385 }
386 InputBufferManager::unregisterFrameData(mListener);
Wonsik Kimf0032642023-07-20 14:42:27 -0700387 if (status == C2_OK) {
388 return ScopedAStatus::ok();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700389 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700390 return ScopedAStatus::fromServiceSpecificError(status);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700391}
392
Wonsik Kimf0032642023-07-20 14:42:27 -0700393ScopedAStatus Component::getInterface(
394 std::shared_ptr<IComponentInterface> *intf) {
395 *intf = mInterface;
396 return ScopedAStatus::ok();
397}
398
399ScopedAStatus Component::configureVideoTunnel(
400 int32_t avSyncHwId, NativeHandle *handle) {
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700401 (void)avSyncHwId;
Wonsik Kimf0032642023-07-20 14:42:27 -0700402 (void)handle;
403 return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700404}
405
Sungtak Lee95fa0872024-01-04 10:24:12 +0000406ScopedAStatus Component::connectToInputSurface(
407 const std::shared_ptr<IInputSurface>& inputSurface,
408 std::shared_ptr<IInputSurfaceConnection> *connection) {
409 // TODO
410 (void)inputSurface;
411 (void)connection;
412 return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
413}
414
415ScopedAStatus Component::asInputSink(
416 std::shared_ptr<IInputSink> *sink) {
417 // TODO
418 (void)sink;
419 return ScopedAStatus::fromServiceSpecificError(Status::OMITTED);
420}
421
Wonsik Kimf0032642023-07-20 14:42:27 -0700422void Component::initListener(const std::shared_ptr<Component>& self) {
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700423 if (__builtin_available(android __ANDROID_API_T__, *)) {
424 std::shared_ptr<C2Component::Listener> c2listener =
425 std::make_shared<Listener>(self);
426 c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
427 if (res != C2_OK) {
428 mInit = res;
429 }
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700430
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700431 mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
432 AIBinder_DeathRecipient_new(OnBinderDied));
Wonsik Kim8e35c062023-10-17 13:40:56 -0700433 mDeathContext = new DeathContext{ref<Component>()};
Wonsik Kim8e2a19f2023-08-30 11:05:45 -0700434 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), OnBinderUnlinked);
435 AIBinder_linkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
436 } else {
437 mInit = C2_NO_INIT;
438 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700439}
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700440
Wonsik Kimf0032642023-07-20 14:42:27 -0700441// static
442void Component::OnBinderDied(void *cookie) {
443 DeathContext *context = (DeathContext *)cookie;
444 std::shared_ptr<Component> comp = context->mWeakComp.lock();
445 if (comp) {
446 comp->release();
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700447 }
Wonsik Kimf0032642023-07-20 14:42:27 -0700448}
449
450// static
451void Component::OnBinderUnlinked(void *cookie) {
452 delete (DeathContext *)cookie;
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700453}
454
455Component::~Component() {
456 InputBufferManager::unregisterFrameData(mListener);
457 mStore->reportComponentDeath(this);
Wonsik Kimf0032642023-07-20 14:42:27 -0700458 if (mDeathRecipient.get()) {
459 AIBinder_unlinkToDeath(mListener->asBinder().get(), mDeathRecipient.get(), mDeathContext);
460 }
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700461}
462
463} // namespace utils
Wonsik Kim5ec480f2023-07-11 14:25:55 -0700464} // namespace c2
465} // namespace media
466} // namespace hardware
467} // namespace android
Wonsik Kimf0032642023-07-20 14:42:27 -0700468} // namespace aidl