blob: 2d19ecc52230ec05ce0898392122aa1b78f60cb9 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002 * Copyright 2018 The Android Open Source Project
Pawin Vongmasa36653902018-11-15 00:10:25 -08003 *
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
18#define LOG_TAG "Codec2Client"
Arun Johnson7ba67072023-11-06 22:23:04 +000019#define ATRACE_TAG ATRACE_TAG_VIDEO
Pawin Vongmasa1c75a232019-01-09 04:41:52 -080020#include <android-base/logging.h>
Arun Johnson7ba67072023-11-06 22:23:04 +000021#include <utils/Trace.h>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000022
23#include <codec2/aidl/GraphicBufferAllocator.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080024#include <codec2/hidl/client.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070025#include <C2Debug.h>
26#include <C2BufferPriv.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080027#include <C2Config.h> // for C2StreamUsageTuning
Pawin Vongmasabf69de92019-10-29 06:21:27 -070028#include <C2PlatformSupport.h>
29
30#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
31#include <android/hardware/media/c2/1.0/IComponent.h>
32#include <android/hardware/media/c2/1.0/IComponentInterface.h>
33#include <android/hardware/media/c2/1.0/IComponentListener.h>
34#include <android/hardware/media/c2/1.0/IComponentStore.h>
35#include <android/hardware/media/c2/1.0/IConfigurable.h>
36#include <android/hidl/manager/1.2/IServiceManager.h>
37
Wonsik Kime8e98152022-12-16 16:04:17 -080038#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
39#include <aidl/android/hardware/media/c2/BnComponentListener.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080040#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
41#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
42#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
43#include <aidl/android/hardware/media/c2/IComponent.h>
44#include <aidl/android/hardware/media/c2/IComponentInterface.h>
45#include <aidl/android/hardware/media/c2/IComponentStore.h>
46#include <aidl/android/hardware/media/c2/IConfigurable.h>
47#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080048#include <aidl/android/hardware/media/c2/StructDescriptor.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080049
Wonsik Kime8e98152022-12-16 16:04:17 -080050#include <aidlcommonsupport/NativeHandle.h>
Wonsik Kim138db0d2023-11-02 16:02:01 -070051#include <android/api-level.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080052#include <android/binder_auto_utils.h>
53#include <android/binder_ibinder.h>
54#include <android/binder_manager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070055#include <android-base/properties.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080056#include <android-base/stringprintf.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070057#include <bufferpool/ClientManager.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080058#include <bufferpool2/ClientManager.h>
59#include <codec2/aidl/BufferTypes.h>
Wonsik Kim1caded02022-12-09 13:03:11 -080060#include <codec2/aidl/ParamTypes.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070061#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070062#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080063#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070064#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070065
66#include <cutils/native_handle.h>
67#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
68#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080069#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070070#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080071#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
72#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080073
74#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070075#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080076#include <limits>
77#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070078#include <mutex>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000079#include <optional>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070080#include <sstream>
81#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080082#include <type_traits>
83#include <vector>
84
Pawin Vongmasa36653902018-11-15 00:10:25 -080085namespace android {
86
87using ::android::hardware::hidl_vec;
88using ::android::hardware::hidl_string;
89using ::android::hardware::Return;
90using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080091
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080092using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
93 V1_0::IGraphicBufferProducer;
94using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
95 V2_0::IGraphicBufferProducer;
96using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
97 V2_0::utils::B2HGraphicBufferProducer;
98using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
99 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -0700100using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -0800101
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000102using AidlGraphicBufferAllocator = ::aidl::android::hardware::media::c2::
103 implementation::GraphicBufferAllocator;
104
Wonsik Kime8e98152022-12-16 16:04:17 -0800105namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800106namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
107namespace c2_aidl = ::aidl::android::hardware::media::c2;
108namespace c2_hidl_base = ::android::hardware::media::c2;
109namespace c2_hidl = ::android::hardware::media::c2::V1_2;
110
111using c2_hidl::utils::operator<<;
112
Pawin Vongmasa36653902018-11-15 00:10:25 -0800113namespace /* unnamed */ {
114
115// c2_status_t value that corresponds to hwbinder transaction failure.
116constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
117
Lajos Molnar78aa7c92021-02-18 21:39:01 -0800118// By default prepare buffer to be displayed on any of the common surfaces
119constexpr uint64_t kDefaultConsumerUsage =
120 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
121
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700122// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700123// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700124// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700125size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700126 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700127 size_t i = 0;
128 for (; i < names.size(); ++i) {
129 if (name == names[i]) {
130 break;
131 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800132 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700133 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800134}
135
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800136class Client2Store : public C2ComponentStore {
137 std::shared_ptr<Codec2Client> mClient;
138
139public:
140 Client2Store(std::shared_ptr<Codec2Client> const& client)
141 : mClient(client) { }
142
143 virtual ~Client2Store() = default;
144
145 virtual c2_status_t config_sm(
146 std::vector<C2Param*> const &params,
147 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
148 return mClient->config(params, C2_MAY_BLOCK, failures);
149 };
150
151 virtual c2_status_t copyBuffer(
152 std::shared_ptr<C2GraphicBuffer>,
153 std::shared_ptr<C2GraphicBuffer>) {
154 return C2_OMITTED;
155 }
156
157 virtual c2_status_t createComponent(
158 C2String, std::shared_ptr<C2Component>* const component) {
159 component->reset();
160 return C2_OMITTED;
161 }
162
163 virtual c2_status_t createInterface(
164 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
165 interface->reset();
166 return C2_OMITTED;
167 }
168
169 virtual c2_status_t query_sm(
170 std::vector<C2Param*> const& stackParams,
171 std::vector<C2Param::Index> const& heapParamIndices,
172 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
173 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
174 }
175
176 virtual c2_status_t querySupportedParams_nb(
177 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
178 return mClient->querySupportedParams(params);
179 }
180
181 virtual c2_status_t querySupportedValues_sm(
182 std::vector<C2FieldSupportedValuesQuery>& fields) const {
183 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
184 }
185
186 virtual C2String getName() const {
187 return mClient->getName();
188 }
189
190 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
191 return mClient->getParamReflector();
192 }
193
194 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
195 return std::vector<std::shared_ptr<C2Component::Traits const>>();
196 }
197};
198
Wonsik Kime8e98152022-12-16 16:04:17 -0800199c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
200 if (!transStatus.isOk()) {
201 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
202 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
203 LOG(DEBUG) << method << " -- call failed: " << status << ".";
204 return status;
205 } else {
206 LOG(ERROR) << method << " -- transaction failed.";
207 return C2_TRANSACTION_FAILED;
208 }
209 }
210 return C2_OK;
211}
212
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700213} // unnamed namespace
214
215// This class caches a Codec2Client object and its component traits. The client
216// will be created the first time it is needed, and it can be refreshed if the
217// service dies (by calling invalidate()). The first time listComponents() is
218// called from the client, the result will be cached.
219class Codec2Client::Cache {
220 // Cached client
221 std::shared_ptr<Codec2Client> mClient;
222 mutable std::mutex mClientMutex;
223
224 // Cached component traits
225 std::vector<C2Component::Traits> mTraits;
226 std::once_flag mTraitsInitializationFlag;
227
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700228 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700229 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700230 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700231 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700232 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700233 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700234 void init(size_t index) {
235 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700236 }
237
238public:
239 Cache() = default;
240
241 // Initializes mClient if needed, then returns mClient.
242 // If the service is unavailable but listed in the manifest, this function
243 // will block indefinitely.
244 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700245 std::scoped_lock lock{mClientMutex};
246 if (!mClient) {
247 mClient = Codec2Client::_CreateFromIndex(mIndex);
248 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700249 CHECK(mClient) << "Failed to create Codec2Client to service \""
250 << GetServiceNames()[mIndex] << "\". (Index = "
251 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700252 return mClient;
253 }
254
255 // Causes a subsequent call to getClient() to create a new client. This
256 // function should be called after the service dies.
257 //
258 // Note: This function is called only by ForAllServices().
259 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700260 std::scoped_lock lock{mClientMutex};
261 mClient = nullptr;
262 }
263
264 // Returns a list of traits for components supported by the service. This
265 // list is cached.
266 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700267 std::call_once(mTraitsInitializationFlag, [this]() {
268 bool success{false};
269 // Spin until _listComponents() is successful.
270 while (true) {
271 std::shared_ptr<Codec2Client> client = getClient();
272 mTraits = client->_listComponents(&success);
273 if (success) {
274 break;
275 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700276 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700277 using namespace std::chrono_literals;
278 static constexpr auto kServiceRetryPeriod = 5s;
279 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700280 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700281 "Retrying...";
282 std::this_thread::sleep_for(kServiceRetryPeriod);
283 }
284 });
285 return mTraits;
286 }
287
288 // List() returns the list of all caches.
289 static std::vector<Cache>& List() {
290 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700291 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700292 std::vector<Cache> caches(numServices);
293 for (size_t i = 0; i < numServices; ++i) {
294 caches[i].init(i);
295 }
296 return caches;
297 }()};
298 return sCaches;
299 }
300};
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800301// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800302
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800303struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
304 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800305
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800306 // base cannot be null.
307 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800308
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800309 const C2String& getName() const override {
310 return mName;
311 }
312
313 c2_status_t query(
314 const std::vector<C2Param*>& stackParams,
315 const std::vector<C2Param::Index> &heapParamIndices,
316 c2_blocking_t mayBlock,
317 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
318
319 c2_status_t config(
320 const std::vector<C2Param*> &params,
321 c2_blocking_t mayBlock,
322 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
323
324 c2_status_t querySupportedParams(
325 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
326 ) const override;
327
328 c2_status_t querySupportedValues(
329 std::vector<C2FieldSupportedValuesQuery>& fields,
330 c2_blocking_t mayBlock) const override;
331
332private:
333 sp<Base> mBase;
334 const C2String mName;
335};
336
337Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800338 : mBase{base},
339 mName{[base]() -> C2String {
340 C2String outName;
341 Return<void> transStatus = base->getName(
342 [&outName](const hidl_string& name) {
343 outName = name.c_str();
344 });
345 return transStatus.isOk() ? outName : "";
346 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800347}
348
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800349c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 const std::vector<C2Param*> &stackParams,
351 const std::vector<C2Param::Index> &heapParamIndices,
352 c2_blocking_t mayBlock,
353 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800354 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800355 stackParams.size() + heapParamIndices.size());
356 size_t numIndices = 0;
357 for (C2Param* const& stackParam : stackParams) {
358 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800359 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800360 continue;
361 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800362 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800363 }
364 size_t numStackIndices = numIndices;
365 for (const C2Param::Index& index : heapParamIndices) {
366 indices[numIndices++] =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800367 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800368 }
369 indices.resize(numIndices);
370 if (heapParams) {
371 heapParams->reserve(heapParams->size() + numIndices);
372 }
373 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800374 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800375 indices,
376 mayBlock == C2_MAY_BLOCK,
377 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800378 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800379 status = static_cast<c2_status_t>(s);
380 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800381 LOG(DEBUG) << "query -- call failed: "
382 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800383 return;
384 }
385 std::vector<C2Param*> paramPointers;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800386 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800387 LOG(ERROR) << "query -- error while parsing params.";
388 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800389 return;
390 }
391 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800392 for (auto it = paramPointers.begin();
393 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800394 C2Param* paramPointer = *it;
395 if (numStackIndices > 0) {
396 --numStackIndices;
397 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800398 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800399 ++it;
400 continue;
401 }
402 for (; i < stackParams.size() && !stackParams[i]; ) {
403 ++i;
404 }
405 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800406 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800407 status = C2_CORRUPTED;
408 return;
409 }
410 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800411 LOG(WARNING) << "query -- param skipped: "
412 "index = "
413 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800414 stackParams[i++]->invalidate();
415 continue;
416 }
417 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800418 LOG(WARNING) << "query -- param update failed: "
419 "index = "
420 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800421 }
422 } else {
423 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800424 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800425 ++it;
426 continue;
427 }
428 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800429 LOG(WARNING) << "query -- "
430 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800432 heapParams->emplace_back(
433 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800434 }
435 }
436 ++it;
437 }
438 });
439 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800440 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800441 return C2_TRANSACTION_FAILED;
442 }
443 return status;
444}
445
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800446c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447 const std::vector<C2Param*> &params,
448 c2_blocking_t mayBlock,
449 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800450 c2_hidl::Params hidlParams;
451 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800452 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 return C2_TRANSACTION_FAILED;
454 }
455 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800456 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457 hidlParams,
458 mayBlock == C2_MAY_BLOCK,
459 [&status, &params, failures](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800460 c2_hidl::Status s,
461 const hidl_vec<c2_hidl::SettingResult> f,
462 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800463 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800464 if (status != C2_OK && status != C2_BAD_INDEX) {
465 LOG(DEBUG) << "config -- call failed: "
466 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800467 }
468 size_t i = failures->size();
469 failures->resize(i + f.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800470 for (const c2_hidl::SettingResult& sf : f) {
471 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800472 LOG(ERROR) << "config -- "
473 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800474 return;
475 }
476 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800477 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 LOG(ERROR) << "config -- "
479 << "failed to parse returned params.";
480 status = C2_CORRUPTED;
481 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800482 });
483 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800484 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800485 return C2_TRANSACTION_FAILED;
486 }
487 return status;
488}
489
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800490c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800491 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
492 // TODO: Cache and query properly!
493 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800494 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800495 std::numeric_limits<uint32_t>::min(),
496 std::numeric_limits<uint32_t>::max(),
497 [&status, params](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800498 c2_hidl::Status s,
499 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800500 status = static_cast<c2_status_t>(s);
501 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800502 LOG(DEBUG) << "querySupportedParams -- call failed: "
503 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800504 return;
505 }
506 size_t i = params->size();
507 params->resize(i + p.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800508 for (const c2_hidl::ParamDescriptor& sp : p) {
509 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800510 LOG(ERROR) << "querySupportedParams -- "
511 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800512 return;
513 }
514 }
515 });
516 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800517 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800518 return C2_TRANSACTION_FAILED;
519 }
520 return status;
521}
522
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800523c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800524 std::vector<C2FieldSupportedValuesQuery>& fields,
525 c2_blocking_t mayBlock) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800526 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800528 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800529 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800530 return C2_TRANSACTION_FAILED;
531 }
532 }
533
534 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800535 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800536 inFields,
537 mayBlock == C2_MAY_BLOCK,
538 [&status, &inFields, &fields](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800539 c2_hidl::Status s,
540 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800541 status = static_cast<c2_status_t>(s);
542 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800543 LOG(DEBUG) << "querySupportedValues -- call failed: "
544 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800545 return;
546 }
547 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800548 LOG(ERROR) << "querySupportedValues -- "
549 "input and output lists "
550 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 status = C2_CORRUPTED;
552 return;
553 }
554 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800555 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800556 LOG(ERROR) << "querySupportedValues -- "
557 "invalid returned value.";
558 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800559 return;
560 }
561 }
562 });
563 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800564 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800565 return C2_TRANSACTION_FAILED;
566 }
567 return status;
568}
569
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800570// Codec2ConfigurableClient::AidlImpl
571
572struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
573 typedef c2_aidl::IConfigurable Base;
574
575 // base cannot be null.
576 explicit AidlImpl(const std::shared_ptr<Base>& base);
577
578 const C2String& getName() const override {
579 return mName;
580 }
581
582 c2_status_t query(
583 const std::vector<C2Param*>& stackParams,
584 const std::vector<C2Param::Index> &heapParamIndices,
585 c2_blocking_t mayBlock,
586 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
587
588 c2_status_t config(
589 const std::vector<C2Param*> &params,
590 c2_blocking_t mayBlock,
591 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
592
593 c2_status_t querySupportedParams(
594 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
595 ) const override;
596
597 c2_status_t querySupportedValues(
598 std::vector<C2FieldSupportedValuesQuery>& fields,
599 c2_blocking_t mayBlock) const override;
600
601private:
602 std::shared_ptr<Base> mBase;
603 const C2String mName;
604};
605
606Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
607 : mBase{base},
608 mName{[base]() -> C2String {
609 std::string outName;
610 ndk::ScopedAStatus status = base->getName(&outName);
611 return status.isOk() ? outName : "";
612 }()} {
613}
614
615c2_status_t Codec2ConfigurableClient::AidlImpl::query(
616 const std::vector<C2Param*> &stackParams,
617 const std::vector<C2Param::Index> &heapParamIndices,
618 c2_blocking_t mayBlock,
619 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800620 std::vector<int> indices(
621 stackParams.size() + heapParamIndices.size());
622 size_t numIndices = 0;
623 for (C2Param* const& stackParam : stackParams) {
624 if (!stackParam) {
625 LOG(WARNING) << "query -- null stack param encountered.";
626 continue;
627 }
628 indices[numIndices++] = int(stackParam->index());
629 }
630 size_t numStackIndices = numIndices;
631 for (const C2Param::Index& index : heapParamIndices) {
632 indices[numIndices++] = int(static_cast<uint32_t>(index));
633 }
634 indices.resize(numIndices);
635 if (heapParams) {
636 heapParams->reserve(heapParams->size() + numIndices);
637 }
638 c2_aidl::Params result;
639 ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800640 c2_status_t status = GetC2Status(transStatus, "query");
641 if (status != C2_OK) {
642 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800643 }
644
Wonsik Kim1caded02022-12-09 13:03:11 -0800645 std::vector<C2Param*> paramPointers;
646 if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result)) {
647 LOG(ERROR) << "query -- error while parsing params.";
648 return C2_CORRUPTED;
649 }
650 size_t i = 0;
651 for (auto it = paramPointers.begin();
652 it != paramPointers.end(); ) {
653 C2Param* paramPointer = *it;
654 if (numStackIndices > 0) {
655 --numStackIndices;
656 if (!paramPointer) {
657 LOG(DEBUG) << "query -- null stack param.";
658 ++it;
659 continue;
660 }
661 for (; i < stackParams.size() && !stackParams[i]; ) {
662 ++i;
663 }
664 if (i >= stackParams.size()) {
665 LOG(ERROR) << "query -- unexpected error.";
666 status = C2_CORRUPTED;
667 break;
668 }
669 if (stackParams[i]->index() != paramPointer->index()) {
670 LOG(DEBUG) << "query -- param skipped: "
671 "index = "
672 << stackParams[i]->index() << ".";
673 stackParams[i++]->invalidate();
674 // this means that the param could not be queried.
675 // signalling C2_BAD_INDEX to the client.
676 status = C2_BAD_INDEX;
677 continue;
678 }
679 if (!stackParams[i++]->updateFrom(*paramPointer)) {
680 LOG(WARNING) << "query -- param update failed: "
681 "index = "
682 << paramPointer->index() << ".";
683 }
684 } else {
685 if (!paramPointer) {
686 LOG(DEBUG) << "query -- null heap param.";
687 ++it;
688 continue;
689 }
690 if (!heapParams) {
691 LOG(WARNING) << "query -- "
692 "unexpected extra stack param.";
693 } else {
694 heapParams->emplace_back(C2Param::Copy(*paramPointer));
695 }
696 }
697 ++it;
698 }
699 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800700}
701
702c2_status_t Codec2ConfigurableClient::AidlImpl::config(
703 const std::vector<C2Param*> &params,
704 c2_blocking_t mayBlock,
705 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800706 c2_aidl::Params aidlParams;
707 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
708 LOG(ERROR) << "config -- bad input.";
709 return C2_TRANSACTION_FAILED;
710 }
711 c2_aidl::IConfigurable::ConfigResult result;
712 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800713 c2_status_t status = GetC2Status(transStatus, "config");
714 if (status != C2_OK) {
715 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800716 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800717 size_t i = failures->size();
718 failures->resize(i + result.failures.size());
719 for (const c2_aidl::SettingResult& sf : result.failures) {
720 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
721 LOG(ERROR) << "config -- invalid SettingResult returned.";
722 return C2_CORRUPTED;
723 }
724 }
725 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
726 LOG(ERROR) << "config -- "
727 << "failed to parse returned params.";
728 status = C2_CORRUPTED;
729 }
730 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800731}
732
733c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
734 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800735 // TODO: Cache and query properly!
736 std::vector<c2_aidl::ParamDescriptor> result;
737 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
738 std::numeric_limits<uint32_t>::min(),
739 std::numeric_limits<uint32_t>::max(),
740 &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800741 c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
742 if (status != C2_OK) {
743 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800744 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800745 size_t i = params->size();
746 params->resize(i + result.size());
747 for (const c2_aidl::ParamDescriptor& sp : result) {
748 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
749 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
750 return C2_CORRUPTED;
751 }
752 }
753 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800754}
755
756c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
757 std::vector<C2FieldSupportedValuesQuery>& fields,
758 c2_blocking_t mayBlock) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800759 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
760 for (size_t i = 0; i < fields.size(); ++i) {
761 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
762 LOG(ERROR) << "querySupportedValues -- bad input";
763 return C2_TRANSACTION_FAILED;
764 }
765 }
766
767 std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
768 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
769 inFields, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800770 c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
771 if (status != C2_OK) {
772 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800773 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800774 if (result.size() != fields.size()) {
775 LOG(ERROR) << "querySupportedValues -- "
776 "input and output lists "
777 "have different sizes.";
778 return C2_CORRUPTED;
779 }
780 for (size_t i = 0; i < fields.size(); ++i) {
781 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result[i])) {
782 LOG(ERROR) << "querySupportedValues -- "
783 "invalid returned value.";
784 return C2_CORRUPTED;
785 }
786 }
787 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800788}
789
790// Codec2ConfigurableClient
791
792Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
793 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
794}
795
796Codec2ConfigurableClient::Codec2ConfigurableClient(
797 const std::shared_ptr<AidlBase> &aidlBase)
798 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
799}
800
801const C2String& Codec2ConfigurableClient::getName() const {
802 return mImpl->getName();
803}
804
805c2_status_t Codec2ConfigurableClient::query(
806 const std::vector<C2Param*>& stackParams,
807 const std::vector<C2Param::Index> &heapParamIndices,
808 c2_blocking_t mayBlock,
809 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
810 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
811}
812
813c2_status_t Codec2ConfigurableClient::config(
814 const std::vector<C2Param*> &params,
815 c2_blocking_t mayBlock,
816 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
817 return mImpl->config(params, mayBlock, failures);
818}
819
820c2_status_t Codec2ConfigurableClient::querySupportedParams(
821 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
822 return mImpl->querySupportedParams(params);
823}
824
825c2_status_t Codec2ConfigurableClient::querySupportedValues(
826 std::vector<C2FieldSupportedValuesQuery>& fields,
827 c2_blocking_t mayBlock) const {
828 return mImpl->querySupportedValues(fields, mayBlock);
829}
830
831
Pawin Vongmasa36653902018-11-15 00:10:25 -0800832// Codec2Client::Component::HidlListener
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800833struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834 std::weak_ptr<Component> component;
835 std::weak_ptr<Listener> base;
836
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800837 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800838 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800839 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800840 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800841 return Void();
842 }
843 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800844 std::shared_ptr<Codec2Client::Component> strongComponent =
845 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800846 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800847 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800848 }
849 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800850 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800851 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800852 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800853 }
854 return Void();
855 }
856
857 virtual Return<void> onTripped(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800858 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800859 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
860 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861 for (size_t i = 0; i < settingResults.size(); ++i) {
862 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800863 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800864 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800865 return Void();
866 }
867 c2SettingResults[i] = std::move(c2SettingResult);
868 }
869 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
870 listener->onTripped(component, c2SettingResults);
871 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800872 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800873 }
874 return Void();
875 }
876
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800877 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800878 LOG(DEBUG) << "onError --"
879 << " status = " << s
880 << ", errorCode = " << errorCode
881 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800882 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800883 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800884 errorCode : static_cast<c2_status_t>(s));
885 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800886 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800887 }
888 return Void();
889 }
890
891 virtual Return<void> onFramesRendered(
892 const hidl_vec<RenderedFrame>& renderedFrames) override {
893 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800894 if (!listener) {
895 LOG(DEBUG) << "onFramesRendered -- listener died.";
896 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800898 for (const RenderedFrame& renderedFrame : renderedFrames) {
899 listener->onFrameRendered(
900 renderedFrame.bufferQueueId,
901 renderedFrame.slotId,
902 renderedFrame.timestampNs);
903 }
904 return Void();
905 }
906
907 virtual Return<void> onInputBuffersReleased(
908 const hidl_vec<InputBuffer>& inputBuffers) override {
909 std::shared_ptr<Listener> listener = base.lock();
910 if (!listener) {
911 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
912 return Void();
913 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800914 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800915 LOG(VERBOSE) << "onInputBuffersReleased --"
916 " received death notification of"
917 " input buffer:"
918 " frameIndex = " << inputBuffer.frameIndex
919 << ", bufferIndex = " << inputBuffer.arrayIndex
920 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800921 listener->onInputBufferDone(
922 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800923 }
924 return Void();
925 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800926
Pawin Vongmasa36653902018-11-15 00:10:25 -0800927};
928
Wonsik Kime8e98152022-12-16 16:04:17 -0800929// Codec2Client::Component::AidlListener
930struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
931 std::weak_ptr<Component> component;
932 std::weak_ptr<Listener> base;
933
934 virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
935 std::list<std::unique_ptr<C2Work>> workItems;
936 if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
937 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
938 return ::ndk::ScopedAStatus::ok();
939 }
940 // release input buffers potentially held by the component from queue
941 std::shared_ptr<Codec2Client::Component> strongComponent =
942 component.lock();
943 if (strongComponent) {
944 strongComponent->handleOnWorkDone(workItems);
945 }
946 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
947 listener->onWorkDone(component, workItems);
948 } else {
949 LOG(DEBUG) << "onWorkDone -- listener died.";
950 }
951 return ::ndk::ScopedAStatus::ok();
952 }
953
954 virtual ::ndk::ScopedAStatus onTripped(
955 const std::vector<c2_aidl::SettingResult>& settingResults) override {
956 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
957 settingResults.size());
958 for (size_t i = 0; i < settingResults.size(); ++i) {
959 std::unique_ptr<C2SettingResult> c2SettingResult;
960 if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
961 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
962 return ::ndk::ScopedAStatus::ok();
963 }
964 c2SettingResults[i] = std::move(c2SettingResult);
965 }
966 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
967 listener->onTripped(component, c2SettingResults);
968 } else {
969 LOG(DEBUG) << "onTripped -- listener died.";
970 }
971 return ::ndk::ScopedAStatus::ok();
972 }
973
974 virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
975 LOG(DEBUG) << "onError --"
976 << " status = " << s.status
977 << ", errorCode = " << errorCode
978 << ".";
979 if (std::shared_ptr<Listener> listener = base.lock()) {
980 listener->onError(component, s.status == c2_aidl::Status::OK ?
981 errorCode : static_cast<c2_status_t>(s.status));
982 } else {
983 LOG(DEBUG) << "onError -- listener died.";
984 }
985 return ::ndk::ScopedAStatus::ok();
986 }
987
988 virtual ::ndk::ScopedAStatus onFramesRendered(
989 const std::vector<RenderedFrame>& renderedFrames) override {
990 std::shared_ptr<Listener> listener = base.lock();
991 if (!listener) {
992 LOG(DEBUG) << "onFramesRendered -- listener died.";
993 return ::ndk::ScopedAStatus::ok();
994 }
995 for (const RenderedFrame& renderedFrame : renderedFrames) {
996 listener->onFrameRendered(
997 renderedFrame.bufferQueueId,
998 renderedFrame.slotId,
999 renderedFrame.timestampNs);
1000 }
1001 return ::ndk::ScopedAStatus::ok();
1002 }
1003
1004 virtual ::ndk::ScopedAStatus onInputBuffersReleased(
1005 const std::vector<InputBuffer>& inputBuffers) override {
1006 std::shared_ptr<Listener> listener = base.lock();
1007 if (!listener) {
1008 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1009 return ::ndk::ScopedAStatus::ok();
1010 }
1011 for (const InputBuffer& inputBuffer : inputBuffers) {
1012 LOG(VERBOSE) << "onInputBuffersReleased --"
1013 " received death notification of"
1014 " input buffer:"
1015 " frameIndex = " << inputBuffer.frameIndex
1016 << ", bufferIndex = " << inputBuffer.arrayIndex
1017 << ".";
1018 listener->onInputBufferDone(
1019 inputBuffer.frameIndex, inputBuffer.arrayIndex);
1020 }
1021 return ::ndk::ScopedAStatus::ok();
1022 }
1023
1024};
1025
1026// Codec2Client::Component::HidlBufferPoolSender
1027struct Codec2Client::Component::HidlBufferPoolSender :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001028 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
Wonsik Kime8e98152022-12-16 16:04:17 -08001029 HidlBufferPoolSender()
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001030 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
1031 }
1032};
1033
Wonsik Kime8e98152022-12-16 16:04:17 -08001034// Codec2Client::Component::AidlBufferPoolSender
1035struct Codec2Client::Component::AidlBufferPoolSender :
1036 c2_aidl::utils::DefaultBufferPoolSender {
1037 AidlBufferPoolSender()
1038 : c2_aidl::utils::DefaultBufferPoolSender() {
1039 }
1040};
1041
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001042// Codec2Client::Component::OutputBufferQueue
1043struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -07001044 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001045 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -07001046 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001047 }
1048};
1049
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001050// The class holds GraphicBufferAllocator and the associated id of
1051// HAL side BlockPool.
1052// This is tightly coupled with BlockPool creation and destruction.
1053// The life cycle inside class will be as follows.
1054//
1055// On createBlockPool client request.
1056// 1. this::create() creates a GraphicBufferAllocator and set it as
1057// the current.
1058// 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
1059// the GraphicBufferAllocator created in #1.
1060// 3. this::setCurrentId() associates the id returned in #2 to the current
1061//
1062// On destroyBlockPool cliet request
1063// 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
1064// from HAL process.
1065// 2. this::remove() destroys GraphicBufferAllocator which is associatted
1066// with the C2BlockPool in #1.
1067//
1068struct Codec2Client::Component::GraphicBufferAllocators {
1069private:
1070 std::optional<C2BlockPool::local_id_t> mCurrentId;
1071 std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
1072
1073 // A new BlockPool is created before the old BlockPool is destroyed.
1074 // This holds the reference of the old BlockPool when a new BlockPool is
1075 // created until the old BlockPool is explicitly requested for destruction.
1076 std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
1077 std::mutex mMutex;
1078
1079public:
1080 // Creates a GraphicBufferAllocator which will be passed to HAL
1081 // for creating C2BlockPool. And the created GraphicBufferAllocator
1082 // will be used afterwards by current().
1083 std::shared_ptr<AidlGraphicBufferAllocator> create() {
1084 std::unique_lock<std::mutex> l(mMutex);
1085 if (mCurrent) {
1086 // If this is not stopped.
1087 mCurrent->reset();
1088 if (mCurrentId.has_value()) {
1089 mOlds.emplace(mCurrentId.value(), mCurrent);
1090 }
1091 mCurrentId.reset();
1092 mCurrent.reset();
1093 }
1094 // TODO: integrate initial value with CCodec/CCodecBufferChannel
1095 mCurrent =
1096 AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
1097 ALOGD("GraphicBufferAllocator created");
1098 return mCurrent;
1099 }
1100
1101 // Associates the blockpool Id returned from HAL to the
1102 // current GraphicBufferAllocator.
1103 void setCurrentId(C2BlockPool::local_id_t id) {
1104 std::unique_lock<std::mutex> l(mMutex);
1105 CHECK(!mCurrentId.has_value());
1106 mCurrentId = id;
1107 }
1108
1109 // Returns the current GraphicBufferAllocator.
1110 std::shared_ptr<AidlGraphicBufferAllocator> current() {
1111 std::unique_lock<std::mutex> l(mMutex);
1112 return mCurrent;
1113 }
1114
1115 // Removes the GraphicBufferAllocator associated with given \p id.
1116 void remove(C2BlockPool::local_id_t id) {
1117 std::unique_lock<std::mutex> l(mMutex);
1118 mOlds.erase(id);
1119 if (mCurrentId == id) {
1120 if (mCurrent) {
1121 mCurrent->reset();
1122 mCurrent.reset();
1123 }
1124 mCurrentId.reset();
1125 }
1126 }
1127};
1128
Pawin Vongmasa36653902018-11-15 00:10:25 -08001129// Codec2Client
Wonsik Kime8e98152022-12-16 16:04:17 -08001130Codec2Client::Codec2Client(sp<HidlBase> const& base,
Sungtak Leef4b39512023-05-10 07:17:22 +00001131 sp<c2_hidl::IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001132 size_t serviceIndex)
Sungtak Leef4b39512023-05-10 07:17:22 +00001133 : Configurable{configurable},
Wonsik Kime8e98152022-12-16 16:04:17 -08001134 mHidlBase1_0{base},
1135 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1136 mHidlBase1_2{HidlBase1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001137 mServiceIndex{serviceIndex} {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001138 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001139 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001140 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001141 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08001142 mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001143 }
1144}
1145
Wonsik Kime8e98152022-12-16 16:04:17 -08001146Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
1147 std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
1148 size_t serviceIndex)
1149 : Configurable{configurable},
1150 mAidlBase{base},
1151 mServiceIndex{serviceIndex} {
1152 ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
1153 if (!transStatus.isOk()) {
1154 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1155 mAidlHostPoolManager.reset();
1156 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001157}
1158
Wonsik Kime8e98152022-12-16 16:04:17 -08001159sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
1160 return mHidlBase1_0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001161}
1162
Wonsik Kime8e98152022-12-16 16:04:17 -08001163sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
1164 return mHidlBase1_0;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001165}
1166
Wonsik Kime8e98152022-12-16 16:04:17 -08001167sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
1168 return mHidlBase1_1;
1169}
1170
1171sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
1172 return mHidlBase1_2;
1173}
1174
1175::ndk::SpAIBinder Codec2Client::getAidlBase() const {
1176 return mAidlBase ? mAidlBase->asBinder() : nullptr;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001177}
1178
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001179std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001180 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001181}
1182
Pawin Vongmasa36653902018-11-15 00:10:25 -08001183c2_status_t Codec2Client::createComponent(
1184 const C2String& name,
1185 const std::shared_ptr<Codec2Client::Listener>& listener,
1186 std::shared_ptr<Codec2Client::Component>* const component) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001187 if (mAidlBase) {
1188 std::shared_ptr<Component::AidlListener> aidlListener =
1189 Component::AidlListener::make<Component::AidlListener>();
1190 aidlListener->base = listener;
1191 std::shared_ptr<c2_aidl::IComponent> aidlComponent;
1192 ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
1193 name,
1194 aidlListener,
1195 bufferpool2_aidl::implementation::ClientManager::getInstance(),
1196 &aidlComponent);
1197 c2_status_t status = GetC2Status(transStatus, "createComponent");
1198 if (status != C2_OK) {
1199 return status;
1200 } else if (!aidlComponent) {
1201 LOG(ERROR) << "createComponent(" << name.c_str()
1202 << ") -- null component.";
1203 return C2_CORRUPTED;
1204 }
1205 *component = std::make_shared<Codec2Client::Component>(aidlComponent);
1206 status = (*component)->setDeathListener((*component), listener);
1207 if (status != C2_OK) {
1208 LOG(ERROR) << "createComponent(" << name.c_str()
1209 << ") -- failed to set up death listener: "
1210 << status << ".";
1211 }
1212 (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001213 aidlListener->component = *component;
Wonsik Kime8e98152022-12-16 16:04:17 -08001214 return status;
1215 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001216
Pawin Vongmasa36653902018-11-15 00:10:25 -08001217 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001218 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001219 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001220 Return<void> transStatus;
Wonsik Kime8e98152022-12-16 16:04:17 -08001221 if (mHidlBase1_2) {
1222 transStatus = mHidlBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001223 name,
1224 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001225 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001226 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001227 c2_hidl::Status s,
1228 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001229 status = static_cast<c2_status_t>(s);
1230 if (status != C2_OK) {
1231 return;
1232 }
1233 *component = std::make_shared<Codec2Client::Component>(c);
1234 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001235 });
1236 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001237 else if (mHidlBase1_1) {
1238 transStatus = mHidlBase1_1->createComponent_1_1(
Sungtak Lee8577dab2021-03-12 02:25:50 -08001239 name,
1240 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001241 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -08001242 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001243 c2_hidl::Status s,
1244 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -08001245 status = static_cast<c2_status_t>(s);
1246 if (status != C2_OK) {
1247 return;
1248 }
1249 *component = std::make_shared<Codec2Client::Component>(c);
1250 hidlListener->component = *component;
1251 });
Wonsik Kime8e98152022-12-16 16:04:17 -08001252 } else if (mHidlBase1_0) { // ver1_0
1253 transStatus = mHidlBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001254 name,
1255 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001256 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001257 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001258 c2_hidl::Status s,
1259 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001260 status = static_cast<c2_status_t>(s);
1261 if (status != C2_OK) {
1262 return;
1263 }
1264 *component = std::make_shared<Codec2Client::Component>(c);
1265 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001266 });
Sungtak Lee8577dab2021-03-12 02:25:50 -08001267 } else {
1268 status = C2_CORRUPTED;
1269 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001270 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001271 LOG(ERROR) << "createComponent(" << name.c_str()
1272 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001273 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001274 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001275 if (status == C2_NOT_FOUND) {
1276 LOG(VERBOSE) << "createComponent(" << name.c_str()
1277 << ") -- component not found.";
1278 } else {
1279 LOG(ERROR) << "createComponent(" << name.c_str()
1280 << ") -- call failed: " << status << ".";
1281 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001282 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001283 } else if (!*component) {
1284 LOG(ERROR) << "createComponent(" << name.c_str()
1285 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 return C2_CORRUPTED;
1287 }
1288
1289 status = (*component)->setDeathListener(*component, listener);
1290 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001291 LOG(ERROR) << "createComponent(" << name.c_str()
1292 << ") -- failed to set up death listener: "
1293 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 }
1295
Wonsik Kime8e98152022-12-16 16:04:17 -08001296 (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001297 return status;
1298}
1299
1300c2_status_t Codec2Client::createInterface(
1301 const C2String& name,
1302 std::shared_ptr<Codec2Client::Interface>* const interface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001303 if (mAidlBase) {
1304 std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
1305 ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
1306 name,
1307 &aidlInterface);
1308 c2_status_t status = GetC2Status(transStatus, "createInterface");
1309 if (status != C2_OK) {
1310 return status;
1311 } else if (!aidlInterface) {
1312 LOG(ERROR) << "createInterface(" << name.c_str()
1313 << ") -- null interface.";
1314 return C2_CORRUPTED;
1315 }
1316 interface->reset(new Codec2Client::Interface(aidlInterface));
1317 return C2_OK;
1318 }
1319
Pawin Vongmasa36653902018-11-15 00:10:25 -08001320 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001321 Return<void> transStatus = mHidlBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001322 name,
1323 [&status, interface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001324 c2_hidl::Status s,
1325 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001326 status = static_cast<c2_status_t>(s);
1327 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001328 return;
1329 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001330 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001331 });
1332 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001333 LOG(ERROR) << "createInterface(" << name.c_str()
1334 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001335 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001336 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001337 if (status == C2_NOT_FOUND) {
1338 LOG(VERBOSE) << "createInterface(" << name.c_str()
1339 << ") -- component not found.";
1340 } else {
1341 LOG(ERROR) << "createInterface(" << name.c_str()
1342 << ") -- call failed: " << status << ".";
1343 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001344 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001345 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001346
Pawin Vongmasa36653902018-11-15 00:10:25 -08001347 return status;
1348}
1349
1350c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001351 std::shared_ptr<InputSurface>* const inputSurface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001352 if (mAidlBase) {
1353 // FIXME
1354 return C2_OMITTED;
1355 }
1356
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001357 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001358 Return<void> transStatus = mHidlBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001359 [&status, inputSurface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001360 c2_hidl::Status s,
1361 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001362 status = static_cast<c2_status_t>(s);
1363 if (status != C2_OK) {
1364 return;
1365 }
1366 *inputSurface = std::make_shared<InputSurface>(i);
1367 });
1368 if (!transStatus.isOk()) {
1369 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001370 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001371 } else if (status != C2_OK) {
1372 LOG(DEBUG) << "createInputSurface -- call failed: "
1373 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001374 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001375 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001376}
1377
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001378std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
1379 return Cache::List()[mServiceIndex].getTraits();
1380}
1381
1382std::vector<C2Component::Traits> Codec2Client::_listComponents(
1383 bool* success) const {
1384 std::vector<C2Component::Traits> traits;
1385 std::string const& serviceName = getServiceName();
Wonsik Kime8e98152022-12-16 16:04:17 -08001386
1387 if (mAidlBase) {
1388 std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
1389 ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
1390 if (!transStatus.isOk()) {
1391 LOG(ERROR) << "_listComponents -- transaction failed.";
1392 *success = false;
1393 } else {
1394 traits.resize(aidlTraits.size());
1395 *success = true;
1396 for (size_t i = 0; i < aidlTraits.size(); ++i) {
1397 if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
1398 LOG(ERROR) << "_listComponents -- corrupted output.";
1399 *success = false;
1400 traits.clear();
1401 break;
1402 }
1403 traits[i].owner = serviceName;
1404 }
1405 }
1406 return traits;
1407 }
1408 Return<void> transStatus = mHidlBase1_0->listComponents(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001409 [&traits, &serviceName](c2_hidl::Status s,
1410 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
1411 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001412 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001413 << static_cast<c2_status_t>(s) << ".";
1414 return;
1415 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001416 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001417 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001418 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001419 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001420 return;
1421 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001422 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001423 }
1424 });
1425 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001426 LOG(ERROR) << "_listComponents -- transaction failed.";
1427 *success = false;
1428 } else {
1429 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001430 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001431 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432}
1433
1434c2_status_t Codec2Client::copyBuffer(
1435 const std::shared_ptr<C2Buffer>& src,
1436 const std::shared_ptr<C2Buffer>& dst) {
1437 // TODO: Implement?
1438 (void)src;
1439 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001440 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001441 return C2_OMITTED;
1442}
1443
Wonsik Kime8e98152022-12-16 16:04:17 -08001444std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001445 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1446 // should reflect the HAL API.
Wonsik Kime8e98152022-12-16 16:04:17 -08001447 struct HidlSimpleParamReflector : public C2ParamReflector {
1448 std::unique_ptr<C2StructDescriptor> describe(
1449 C2Param::CoreIndex coreIndex) const override {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001450 hidl_vec<c2_hidl::ParamIndex> indices(1);
1451 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001452 std::unique_ptr<C2StructDescriptor> descriptor;
1453 Return<void> transStatus = mBase->getStructDescriptors(
1454 indices,
1455 [&descriptor](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001456 c2_hidl::Status s,
1457 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001458 c2_status_t status = static_cast<c2_status_t>(s);
1459 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001460 LOG(DEBUG) << "SimpleParamReflector -- "
1461 "getStructDescriptors() failed: "
1462 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001463 descriptor.reset();
1464 return;
1465 }
1466 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001467 LOG(DEBUG) << "SimpleParamReflector -- "
1468 "getStructDescriptors() "
1469 "returned vector of size "
1470 << sd.size() << ". "
1471 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001472 descriptor.reset();
1473 return;
1474 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001475 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001476 LOG(DEBUG) << "SimpleParamReflector -- "
1477 "getStructDescriptors() returned "
1478 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001479 descriptor.reset();
1480 return;
1481 }
1482 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001483 if (!transStatus.isOk()) {
1484 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1485 << transStatus.description();
1486 descriptor.reset();
1487 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001488 return descriptor;
1489 }
1490
Wonsik Kime8e98152022-12-16 16:04:17 -08001491 HidlSimpleParamReflector(sp<HidlBase> base)
Pawin Vongmasa36653902018-11-15 00:10:25 -08001492 : mBase(base) { }
1493
Wonsik Kime8e98152022-12-16 16:04:17 -08001494 sp<HidlBase> mBase;
1495 };
1496 struct AidlSimpleParamReflector : public C2ParamReflector {
1497 std::unique_ptr<C2StructDescriptor> describe(
1498 C2Param::CoreIndex coreIndex) const override {
1499 std::vector<c2_aidl::StructDescriptor> aidlDesc;
1500 std::unique_ptr<C2StructDescriptor> descriptor;
1501 ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
1502 {int32_t(coreIndex.coreIndex())},
1503 &aidlDesc);
1504 c2_status_t status = GetC2Status(transStatus, "describe");
1505 if (status != C2_OK) {
1506 descriptor.reset();
1507 } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
1508 LOG(ERROR) << "describe -- conversion failed.";
1509 descriptor.reset();
1510 }
1511 return descriptor;
1512 }
1513
1514 AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
1515 : mBase(base) { }
1516
1517 std::shared_ptr<AidlBase> mBase;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001518 };
1519
Wonsik Kime8e98152022-12-16 16:04:17 -08001520 if (mAidlBase) {
1521 return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
1522 }
1523 return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001524};
1525
Wonsik Kime8e98152022-12-16 16:04:17 -08001526std::vector<std::string> Codec2Client::CacheServiceNames() {
1527 std::vector<std::string> names;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001528
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001529 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001530 if (__builtin_available(android __ANDROID_API_S__, *)) {
1531 // Get AIDL service names
1532 AServiceManager_forEachDeclaredInstance(
1533 AidlBase::descriptor, &names, [](const char *name, void *context) {
1534 std::vector<std::string> *names = (std::vector<std::string> *)context;
1535 names->emplace_back(name);
1536 });
1537 } else {
1538 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
1539 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001540 } else {
1541 // Get HIDL service names
1542 using ::android::hardware::media::c2::V1_0::IComponentStore;
1543 using ::android::hidl::manager::V1_2::IServiceManager;
1544 while (true) {
1545 sp<IServiceManager> serviceManager = IServiceManager::getService();
1546 CHECK(serviceManager) << "Hardware service manager is not running.";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001547
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001548 Return<void> transResult;
1549 transResult = serviceManager->listManifestByInterface(
1550 IComponentStore::descriptor,
1551 [&names](
1552 hidl_vec<hidl_string> const& instanceNames) {
1553 names.insert(names.end(), instanceNames.begin(), instanceNames.end());
1554 });
1555 if (transResult.isOk()) {
1556 break;
1557 }
1558 LOG(ERROR) << "Could not retrieve the list of service instances of "
1559 << IComponentStore::descriptor
1560 << ". Retrying...";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001561 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001562 }
1563 // Sort service names in each category.
1564 std::stable_sort(
1565 names.begin(), names.end(),
1566 [](const std::string &a, const std::string &b) {
1567 // First compare by prefix: default -> vendor -> {everything else}
1568 constexpr int DEFAULT = 1;
1569 constexpr int VENDOR = 2;
1570 constexpr int OTHER = 3;
1571 int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
1572 (a.compare(0, 6, "vendor") == 0) ? VENDOR :
1573 OTHER);
1574 int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
1575 (b.compare(0, 6, "vendor") == 0) ? VENDOR :
1576 OTHER);
1577 if (aPrefix != bPrefix) {
1578 return aPrefix < bPrefix;
1579 }
1580 // If the prefix is the same, compare alphabetically
1581 return a < b;
1582 });
1583
1584 // Summarize to logcat.
1585 if (names.empty()) {
1586 LOG(INFO) << "No Codec2 services declared in the manifest.";
1587 } else {
1588 std::stringstream stringOutput;
1589 stringOutput << "Available Codec2 services:";
1590 for (std::string const& name : names) {
1591 stringOutput << " \"" << name << "\"";
1592 }
1593 LOG(INFO) << stringOutput.str();
1594 }
1595
1596 return names;
1597}
1598
1599std::vector<std::string> const& Codec2Client::GetServiceNames() {
1600 static std::vector<std::string> sServiceNames = CacheServiceNames();
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001601 return sServiceNames;
1602}
1603
Pawin Vongmasa36653902018-11-15 00:10:25 -08001604std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001605 const char* name,
1606 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001607 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001608 if (index == GetServiceNames().size()) {
1609 if (setAsPreferredCodec2ComponentStore) {
1610 LOG(WARNING) << "CreateFromService(" << name
1611 << ") -- preferred C2ComponentStore not set.";
1612 }
1613 return nullptr;
1614 }
1615 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1616 if (setAsPreferredCodec2ComponentStore) {
1617 SetPreferredCodec2ComponentStore(
1618 std::make_shared<Client2Store>(client));
1619 LOG(INFO) << "CreateFromService(" << name
1620 << ") -- service set as preferred C2ComponentStore.";
1621 }
1622 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001623}
1624
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001625std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1626 CreateFromAllServices() {
1627 std::vector<std::shared_ptr<Codec2Client>> clients(
1628 GetServiceNames().size());
1629 for (size_t i = GetServiceNames().size(); i > 0; ) {
1630 --i;
1631 clients[i] = _CreateFromIndex(i);
1632 }
1633 return clients;
1634}
1635
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001636std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001637 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001638 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Wonsik Kime8e98152022-12-16 16:04:17 -08001639
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001640 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001641 if (__builtin_available(android __ANDROID_API_S__, *)) {
1642 std::string instanceName =
1643 ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
1644 if (AServiceManager_isDeclared(instanceName.c_str())) {
1645 std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
1646 ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
1647 CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
1648 " inaccessible for unknown reasons.";
1649 LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
1650 std::shared_ptr<c2_aidl::IConfigurable> configurable;
1651 ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
1652 CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
1653 "does not have IConfigurable.";
1654 return std::make_shared<Codec2Client>(baseStore, configurable, index);
1655 } else {
1656 LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
1657 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001658 } else {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001659 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
Wonsik Kime8e98152022-12-16 16:04:17 -08001660 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001661 } else {
1662 std::string instanceName = "android.hardware.media.c2/" + name;
1663 sp<HidlBase> baseStore = HidlBase::getService(name);
1664 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1665 " inaccessible for unknown reasons.";
1666 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
1667 Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
1668 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1669 "does not have IConfigurable.";
1670 sp<c2_hidl::IConfigurable> configurable =
1671 static_cast<sp<c2_hidl::IConfigurable>>(transResult);
1672 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Wonsik Kime8e98152022-12-16 16:04:17 -08001673 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001674 return nullptr;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001675}
1676
1677c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001678 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001679 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001680 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1681 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001682 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1683
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001684 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001685 static std::mutex key2IndexMutex;
1686 static std::map<std::string, size_t> key2Index;
1687
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001688 // By default try all stores. However, try the last known client first. If
1689 // the last known client fails, retry once. We do this by pushing the last
1690 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001691 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001692 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001693 indices.push_front(--index);
1694 }
1695
1696 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001697 {
1698 std::scoped_lock lock{key2IndexMutex};
1699 auto it = key2Index.find(key);
1700 if (it != key2Index.end()) {
1701 indices.push_front(it->second);
1702 wasMapped = true;
1703 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001704 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001705
1706 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001707 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001708 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1709 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001710 status = predicate(client);
1711 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001712 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001713 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001714 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001715 } else if (status == C2_NO_MEMORY) {
1716 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001717 } else if (status == C2_TRANSACTION_FAILED) {
1718 LOG(WARNING) << "\"" << key << "\" failed for service \""
1719 << client->getName()
1720 << "\" due to transaction failure. "
1721 << "(Service may have crashed.)"
1722 << (tries > 1 ? " Retrying..." : "");
1723 cache.invalidate();
1724 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001725 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001726 if (wasMapped) {
1727 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1728 << client->getName() << "\". Retrying...";
1729 wasMapped = false;
1730 }
1731 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001732 }
1733 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001734 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001735}
1736
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001737c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001738 const char* componentName,
1739 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001740 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001741 std::shared_ptr<Codec2Client>* owner,
1742 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001743 std::string key{"create:"};
1744 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001745 c2_status_t status = ForAllServices(
1746 key,
1747 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001748 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001749 const std::shared_ptr<Codec2Client> &client)
1750 -> c2_status_t {
1751 c2_status_t status = client->createComponent(componentName,
1752 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001753 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001754 if (status == C2_OK) {
1755 if (owner) {
1756 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001757 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001758 } else if (status != C2_NOT_FOUND) {
1759 LOG(DEBUG) << "IComponentStore("
1760 << client->getServiceName()
1761 << ")::createComponent(\"" << componentName
1762 << "\") returned status = "
1763 << status << ".";
1764 }
1765 return status;
1766 });
1767 if (status != C2_OK) {
1768 LOG(DEBUG) << "Failed to create component \"" << componentName
1769 << "\" from all known services. "
1770 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001771 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001772 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001773}
1774
Wonsik Kime8e98152022-12-16 16:04:17 -08001775std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001776 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001777 std::shared_ptr<Codec2Client>* owner,
1778 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001779 std::string key{"create:"};
1780 key.append(interfaceName);
1781 std::shared_ptr<Interface> interface;
1782 c2_status_t status = ForAllServices(
1783 key,
1784 numberOfAttempts,
1785 [owner, &interface, interfaceName](
1786 const std::shared_ptr<Codec2Client> &client)
1787 -> c2_status_t {
1788 c2_status_t status = client->createInterface(interfaceName,
1789 &interface);
1790 if (status == C2_OK) {
1791 if (owner) {
1792 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001793 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001794 } else if (status != C2_NOT_FOUND) {
1795 LOG(DEBUG) << "IComponentStore("
1796 << client->getServiceName()
1797 << ")::createInterface(\"" << interfaceName
1798 << "\") returned status = "
1799 << status << ".";
1800 }
1801 return status;
1802 });
1803 if (status != C2_OK) {
1804 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1805 << "\" from all known services. "
1806 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001807 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001808 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001809}
1810
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001811std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1812 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001813 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001814 for (Cache& cache : Cache::List()) {
1815 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1816 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001817 }
1818 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001819 }()};
1820 return sList;
1821}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001822
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001823std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1824 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001825 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1826 "debug.stagefright.c2inputsurface", int32_t(0));
1827 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001828 return nullptr;
1829 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001830 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001831 if (serviceName) {
1832 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001833 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001834 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1835 << serviceName << "\"";
1836 }
1837 }
1838
1839 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001840 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001841 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1842 if (client->createInputSurface(&inputSurface) == C2_OK) {
1843 return inputSurface;
1844 }
1845 }
1846 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1847 "from all services...";
1848 for (Cache& cache : Cache::List()) {
1849 std::shared_ptr<Codec2Client> client = cache.getClient();
1850 if (client->createInputSurface(&inputSurface) == C2_OK) {
1851 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1852 "service \"" << client->getServiceName() << "\"";
1853 return inputSurface;
1854 }
1855 }
1856 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1857 "from all services";
1858 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001859}
1860
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001861// Codec2Client::Interface
Wonsik Kime8e98152022-12-16 16:04:17 -08001862Codec2Client::Interface::Interface(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001863 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001864 [base]() -> sp<c2_hidl::IConfigurable> {
1865 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001866 base->getConfigurable();
1867 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001868 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001869 nullptr;
1870 }()
1871 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001872 mHidlBase{base} {
1873}
1874
1875Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
1876 : Configurable{
1877 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
1878 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
1879 ::ndk::ScopedAStatus transStatus =
1880 base->getConfigurable(&aidlConfigurable);
1881 return transStatus.isOk() ? aidlConfigurable : nullptr;
1882 }()
1883 },
1884 mAidlBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001885}
1886
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001887// Codec2Client::Component
Wonsik Kime8e98152022-12-16 16:04:17 -08001888
1889class Codec2Client::Component::AidlDeathManager {
1890public:
1891 AidlDeathManager()
1892 : mSeq(0),
1893 mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
1894 }
1895
1896 ~AidlDeathManager() = default;
1897
1898 bool linkToDeath(
1899 const std::shared_ptr<Component> &comp,
1900 const std::shared_ptr<Listener> &listener,
1901 size_t *seqPtr) {
1902 std::unique_lock lock(mMutex);
1903 size_t seq = mSeq++;
1904 if (!mMap.try_emplace(seq, comp, listener).second) {
1905 return false;
1906 }
1907 if (STATUS_OK != AIBinder_linkToDeath(
1908 comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
1909 mMap.erase(seq);
1910 return false;
1911 }
1912 *seqPtr = seq;
1913 return true;
1914 }
1915
1916 void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
1917 std::unique_lock lock(mMutex);
1918 AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
1919 mMap.erase(seq);
1920 }
1921
1922private:
1923 std::mutex mMutex;
1924 size_t mSeq;
1925 typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
1926 std::map<size_t, Context> mMap;
1927 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
1928
1929 bool extractContext(size_t seq, Context *context) {
1930 std::unique_lock lock(mMutex);
1931 auto node = mMap.extract(seq);
1932 if (!node) {
1933 return false;
1934 }
1935 *context = node.mapped();
1936 return true;
1937 }
1938
1939 static void OnBinderDied(void *cookie) {
1940 size_t seq = size_t(cookie);
1941 Context context;
1942 if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
1943 return;
1944 }
1945 std::weak_ptr<Component> weakComponent;
1946 std::weak_ptr<Listener> weakListener;
1947 std::tie(weakComponent, weakListener) = context;
1948 if (std::shared_ptr<Listener> listener = weakListener.lock()) {
1949 listener->onDeath(weakComponent);
1950 } else {
1951 LOG(DEBUG) << "onDeath -- listener died.";
1952 }
1953 }
1954};
1955
1956Codec2Client::Component::Component(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001957 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001958 [base]() -> sp<c2_hidl::IConfigurable> {
1959 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001960 base->getInterface();
1961 if (!transResult1.isOk()) {
1962 return nullptr;
1963 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001964 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1965 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001966 getConfigurable();
1967 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001968 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001969 nullptr;
1970 }()
1971 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001972 mHidlBase1_0{base},
1973 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1974 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1975 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001976 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1977}
1978
Wonsik Kime8e98152022-12-16 16:04:17 -08001979Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001980 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001981 [base]() -> sp<c2_hidl::IConfigurable> {
1982 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001983 base->getInterface();
1984 if (!transResult1.isOk()) {
1985 return nullptr;
1986 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001987 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1988 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001989 getConfigurable();
1990 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001991 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001992 nullptr;
1993 }()
1994 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001995 mHidlBase1_0{base},
1996 mHidlBase1_1{base},
1997 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1998 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Sungtak Lee8577dab2021-03-12 02:25:50 -08001999 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2000}
2001
Wonsik Kime8e98152022-12-16 16:04:17 -08002002Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
Sungtak Lee8577dab2021-03-12 02:25:50 -08002003 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002004 [base]() -> sp<c2_hidl::IConfigurable> {
2005 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08002006 base->getInterface();
2007 if (!transResult1.isOk()) {
2008 return nullptr;
2009 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002010 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2011 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08002012 getConfigurable();
2013 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002014 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08002015 nullptr;
2016 }()
2017 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002018 mHidlBase1_0{base},
2019 mHidlBase1_1{base},
2020 mHidlBase1_2{base},
2021 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2022 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2023}
2024
2025Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
2026 : Configurable{
2027 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2028 std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
2029 ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
2030 if (!transStatus.isOk()) {
2031 return nullptr;
2032 }
2033 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2034 transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
2035 return transStatus.isOk() ? aidlConfigurable : nullptr;
2036 }()
2037 },
2038 mAidlBase{base},
2039 mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002040 mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002041}
2042
2043Codec2Client::Component::~Component() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002044 if (mAidlDeathSeq) {
2045 GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
2046 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002047}
2048
2049c2_status_t Codec2Client::Component::createBlockPool(
2050 C2Allocator::id_t id,
2051 C2BlockPool::local_id_t* blockPoolId,
2052 std::shared_ptr<Codec2Client::Configurable>* configurable) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002053 if (mAidlBase) {
2054 c2_aidl::IComponent::BlockPool aidlBlockPool;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002055 c2_status_t status = C2_OK;
2056
2057 // TODO: Temporary mapping for the current CCodecBufferChannel.
2058 // Handle this properly and remove this temporary allocator mapping.
2059 id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
2060 C2PlatformAllocatorStore::IGBA : id;
2061
2062 if (id == C2PlatformAllocatorStore::IGBA) {
2063 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2064 mGraphicBufferAllocators->create();
2065 ::ndk::ScopedFileDescriptor waitableFd;
2066 ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
2067 status = GetC2Status(ret, "Gba::getWaitableFd");
2068 if (status != C2_OK) {
2069 return status;
2070 }
2071 c2_aidl::IComponent::BlockPoolAllocator allocator;
2072 allocator.set<c2_aidl::IComponent::BlockPoolAllocator::allocator>();
2073 allocator.get<c2_aidl::IComponent::BlockPoolAllocator::allocator>().igba =
2074 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2075 allocator.get<c2_aidl::IComponent::BlockPoolAllocator::allocator>().waitableFd =
2076 std::move(waitableFd);
2077 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2078 allocator, &aidlBlockPool);
2079 status = GetC2Status(transStatus, "createBlockPool");
2080 if (status != C2_OK) {
2081 return status;
2082 }
2083 mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
2084 } else {
2085 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2086 static_cast<int32_t>(id), &aidlBlockPool);
2087 status = GetC2Status(transStatus, "createBlockPool");
2088 if (status != C2_OK) {
2089 return status;
2090 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002091 }
2092 *blockPoolId = aidlBlockPool.blockPoolId;
2093 *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
2094 return C2_OK;
2095 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002096 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002097 Return<void> transStatus = mHidlBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002098 static_cast<uint32_t>(id),
2099 [&status, blockPoolId, configurable](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002100 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08002101 uint64_t pId,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002102 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002103 status = static_cast<c2_status_t>(s);
2104 configurable->reset();
2105 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002106 LOG(DEBUG) << "createBlockPool -- call failed: "
2107 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002108 return;
2109 }
2110 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002111 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002112 });
2113 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002114 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002115 return C2_TRANSACTION_FAILED;
2116 }
2117 return status;
2118}
2119
2120c2_status_t Codec2Client::Component::destroyBlockPool(
2121 C2BlockPool::local_id_t localId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002122 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002123 mGraphicBufferAllocators->remove(localId);
Wonsik Kime8e98152022-12-16 16:04:17 -08002124 ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
2125 return GetC2Status(transStatus, "destroyBlockPool");
2126 }
2127 Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002128 static_cast<uint64_t>(localId));
2129 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002130 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002131 return C2_TRANSACTION_FAILED;
2132 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002133 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002134}
2135
Wonsik Kimab34ed62019-01-31 15:28:46 -08002136void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002137 const std::list<std::unique_ptr<C2Work>> &workItems) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002138 if (mAidlBase) {
2139 holdIgbaBlocks(workItems);
2140 } else {
2141 // Output bufferqueue-based blocks' lifetime management
2142 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
2143 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002144}
2145
2146c2_status_t Codec2Client::Component::queue(
2147 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002148 if (mAidlBase) {
2149 c2_aidl::WorkBundle workBundle;
2150 if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
2151 LOG(ERROR) << "queue -- bad input.";
2152 return C2_TRANSACTION_FAILED;
2153 }
2154 ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
2155 return GetC2Status(transStatus, "queue");
2156 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002157 c2_hidl::WorkBundle workBundle;
Wonsik Kime8e98152022-12-16 16:04:17 -08002158 if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002159 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002160 return C2_TRANSACTION_FAILED;
2161 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002162 Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002163 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002164 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002165 return C2_TRANSACTION_FAILED;
2166 }
2167 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002168 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002169 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002170 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002171 }
2172 return status;
2173}
2174
2175c2_status_t Codec2Client::Component::flush(
2176 C2Component::flush_mode_t mode,
2177 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002178 (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
2179 c2_status_t status = C2_OK;
2180 if (mAidlBase) {
2181 c2_aidl::WorkBundle workBundle;
2182 ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
2183 c2_status_t status = GetC2Status(transStatus, "flush");
2184 if (status != C2_OK) {
2185 return status;
2186 }
2187 if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
2188 LOG(DEBUG) << "flush -- flushedWork corrupted.";
2189 return C2_CORRUPTED;
2190 }
2191 } else {
2192 Return<void> transStatus = mHidlBase1_0->flush(
2193 [&status, flushedWork](
2194 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
2195 status = static_cast<c2_status_t>(s);
2196 if (status != C2_OK) {
2197 LOG(DEBUG) << "flush -- call failed: " << status << ".";
2198 return;
2199 }
2200 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
2201 status = C2_CORRUPTED;
2202 } else {
2203 status = C2_OK;
2204 }
2205 });
2206 if (!transStatus.isOk()) {
2207 LOG(ERROR) << "flush -- transaction failed.";
2208 return C2_TRANSACTION_FAILED;
2209 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002210 }
2211
2212 // Indices of flushed work items.
2213 std::vector<uint64_t> flushedIndices;
2214 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
2215 if (work) {
2216 if (work->worklets.empty()
2217 || !work->worklets.back()
2218 || (work->worklets.back()->output.flags &
2219 C2FrameData::FLAG_INCOMPLETE) == 0) {
2220 // input is complete
2221 flushedIndices.emplace_back(
2222 work->input.ordinal.frameIndex.peeku());
2223 }
2224 }
2225 }
2226
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002227 if (mAidlBase) {
2228 holdIgbaBlocks(*flushedWork);
2229 } else {
2230 // Output bufferqueue-based blocks' lifetime management
2231 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
2232 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002233
2234 return status;
2235}
2236
2237c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002238 if (mAidlBase) {
2239 ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
2240 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2241 return GetC2Status(transStatus, "drain");
2242 }
2243 Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002244 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2245 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002246 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002247 return C2_TRANSACTION_FAILED;
2248 }
2249 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002250 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002251 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002252 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002253 }
2254 return status;
2255}
2256
2257c2_status_t Codec2Client::Component::start() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002258 if (mAidlBase) {
2259 ::ndk::ScopedAStatus transStatus = mAidlBase->start();
2260 return GetC2Status(transStatus, "start");
2261 }
2262 Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002263 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002264 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002265 return C2_TRANSACTION_FAILED;
2266 }
2267 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002268 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002269 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002270 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002271 }
2272 return status;
2273}
2274
2275c2_status_t Codec2Client::Component::stop() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002276 if (mAidlBase) {
2277 ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
2278 return GetC2Status(transStatus, "stop");
2279 }
2280 Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002281 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002282 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002283 return C2_TRANSACTION_FAILED;
2284 }
2285 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002286 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002287 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002288 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002289 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002290 return status;
2291}
2292
2293c2_status_t Codec2Client::Component::reset() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002294 if (mAidlBase) {
2295 ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
2296 return GetC2Status(transStatus, "reset");
2297 }
2298 Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002299 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002300 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002301 return C2_TRANSACTION_FAILED;
2302 }
2303 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002304 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002305 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002306 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002307 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002308 return status;
2309}
2310
2311c2_status_t Codec2Client::Component::release() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002312 if (mAidlBase) {
2313 ::ndk::ScopedAStatus transStatus = mAidlBase->release();
2314 return GetC2Status(transStatus, "release");
2315 }
2316 Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002317 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002318 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002319 return C2_TRANSACTION_FAILED;
2320 }
2321 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002322 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002323 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002324 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002325 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002326 return status;
2327}
2328
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002329c2_status_t Codec2Client::Component::configureVideoTunnel(
2330 uint32_t avSyncHwId,
2331 native_handle_t** sidebandHandle) {
2332 *sidebandHandle = nullptr;
Wonsik Kime8e98152022-12-16 16:04:17 -08002333 if (mAidlBase) {
2334 ::aidl::android::hardware::common::NativeHandle handle;
2335 ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
2336 c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
2337 if (status != C2_OK) {
2338 return status;
2339 }
2340 if (isAidlNativeHandleEmpty(handle)) {
2341 LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
2342 } else {
2343 *sidebandHandle = dupFromAidl(handle);
2344 }
2345 return C2_OK;
2346 }
2347 if (!mHidlBase1_1) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002348 return C2_OMITTED;
2349 }
2350 c2_status_t status{};
Wonsik Kime8e98152022-12-16 16:04:17 -08002351 Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002352 [&status, sidebandHandle](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002353 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002354 status = static_cast<c2_status_t>(s);
2355 if (h.getNativeHandle()) {
2356 *sidebandHandle = native_handle_clone(h.getNativeHandle());
2357 }
2358 });
2359 if (!transStatus.isOk()) {
2360 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
2361 return C2_TRANSACTION_FAILED;
2362 }
2363 return status;
2364}
2365
Pawin Vongmasa36653902018-11-15 00:10:25 -08002366c2_status_t Codec2Client::Component::setOutputSurface(
2367 C2BlockPool::local_id_t blockPoolId,
2368 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07002369 uint32_t generation,
2370 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002371 if (mAidlBase) {
2372 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2373 mGraphicBufferAllocators->current();
2374 if (!gba) {
2375 LOG(ERROR) << "setOutputSurface for AIDL -- "
2376 "GraphicBufferAllocator was not created.";
2377 return C2_CORRUPTED;
2378 }
2379 bool ret = gba->configure(surface, generation, maxDequeueCount);
2380 return ret ? C2_OK : C2_CORRUPTED;
2381 }
Sungtak Lee08515812019-06-05 11:16:32 -07002382 uint64_t bqId = 0;
2383 sp<IGraphicBufferProducer> nullIgbp;
2384 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08002385
Sungtak Lee08515812019-06-05 11:16:32 -07002386 sp<HGraphicBufferProducer2> igbp = surface ?
2387 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
2388 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002389 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002390 }
2391
Sungtak Leefb579022022-05-10 06:36:15 +00002392 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07002393 std::shared_ptr<SurfaceSyncObj> syncObj;
2394
Sungtak Lee08515812019-06-05 11:16:32 -07002395 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07002396 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002397 } else if (surface->getUniqueId(&bqId) != OK) {
2398 LOG(ERROR) << "setOutputSurface -- "
2399 "cannot obtain bufferqueue id.";
2400 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07002401 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002402 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08002403 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
2404 mHidlBase1_2 ? &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002405 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002406
2407 // set consumer bits
2408 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
2409 // can be set atomically?
2410 uint64_t consumerUsage = kDefaultConsumerUsage;
2411 {
2412 if (surface) {
Sungtak Lee46a69d62023-08-12 07:24:24 +00002413 uint64_t usage = 0;
2414 status_t err = surface->getConsumerUsage(&usage);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002415 if (err != NO_ERROR) {
2416 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
2417 err, asString(err));
2418 } else {
2419 // Note: we are adding the default usage because components must support
2420 // producing output frames that can be displayed an all output surfaces.
2421
2422 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
2423 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
2424 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
2425 // through the sideband channel.
2426
Sungtak Lee46a69d62023-08-12 07:24:24 +00002427 consumerUsage = usage | kDefaultConsumerUsage;
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002428 }
2429 }
2430
2431 C2StreamUsageTuning::output outputUsage{
2432 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
2433 std::vector<std::unique_ptr<C2SettingResult>> failures;
2434 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
2435 if (err != C2_OK) {
2436 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
2437 err, asString(err));
2438 }
2439 }
2440 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
2441 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07002442
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002443 Return<c2_hidl::Status> transStatus = syncObj ?
Wonsik Kime8e98152022-12-16 16:04:17 -08002444 mHidlBase1_2->setOutputSurfaceWithSyncObj(
Sungtak Leea714f112021-03-16 05:40:03 -07002445 static_cast<uint64_t>(blockPoolId),
2446 bqId == 0 ? nullHgbp : igbp, *syncObj) :
Wonsik Kime8e98152022-12-16 16:04:17 -08002447 mHidlBase1_0->setOutputSurface(
Sungtak Leea714f112021-03-16 05:40:03 -07002448 static_cast<uint64_t>(blockPoolId),
2449 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002450
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002451 mOutputBufferQueue->expireOldWaiters();
2452
Pawin Vongmasa36653902018-11-15 00:10:25 -08002453 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002454 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002455 return C2_TRANSACTION_FAILED;
2456 }
2457 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002458 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002459 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002460 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002461 }
Sungtak Leea714f112021-03-16 05:40:03 -07002462 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08002463 return status;
2464}
2465
2466status_t Codec2Client::Component::queueToOutputSurface(
2467 const C2ConstGraphicBlock& block,
2468 const QueueBufferInput& input,
2469 QueueBufferOutput* output) {
Arun Johnson7ba67072023-11-06 22:23:04 +00002470 ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002471 if (mAidlBase) {
2472 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2473 mGraphicBufferAllocators->current();
2474 if (gba) {
2475 return gba->displayBuffer(block, input, output);
2476 } else {
2477 return C2_NOT_FOUND;
2478 }
2479 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002480 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002481}
2482
Brian Lindahlc953b462023-01-27 16:21:43 -07002483void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002484 if (mAidlBase) {
2485 // TODO b/311348680
2486 return;
2487 }
Brian Lindahlc953b462023-01-27 16:21:43 -07002488 mOutputBufferQueue->pollForRenderedFrames(delta);
2489}
2490
Sungtak Leea714f112021-03-16 05:40:03 -07002491void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
2492 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002493 if (mAidlBase) {
2494 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2495 mGraphicBufferAllocators->current();
2496 if (gba) {
2497 gba->updateMaxDequeueBufferCount(maxDequeueCount);
2498 }
2499 return;
2500 }
Sungtak Leea714f112021-03-16 05:40:03 -07002501 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
2502}
2503
Sungtak Leec7da7a02022-05-05 08:45:33 +00002504void Codec2Client::Component::stopUsingOutputSurface(
2505 C2BlockPool::local_id_t blockPoolId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002506 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002507 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2508 mGraphicBufferAllocators->current();
2509 if (gba) {
2510 gba->reset();
2511 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002512 return;
2513 }
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002514 std::scoped_lock lock(mOutputMutex);
2515 mOutputBufferQueue->stop();
Wonsik Kime8e98152022-12-16 16:04:17 -08002516 Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00002517 static_cast<uint64_t>(blockPoolId), nullptr);
2518 if (!transStatus.isOk()) {
2519 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
2520 } else {
2521 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002522 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00002523 if (status != C2_OK) {
2524 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
2525 << status << ".";
2526 }
2527 }
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002528 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00002529}
2530
Sungtak Lee214ce612023-11-01 10:01:13 +00002531void Codec2Client::Component::onBufferReleasedFromOutputSurface(
2532 uint32_t generation) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002533 if (mAidlBase) {
2534 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2535 mGraphicBufferAllocators->current();
2536 if (gba) {
2537 gba->onBufferReleased(generation);
2538 }
2539 return;
2540 }
Sungtak Lee6700cc92023-11-22 18:04:05 +00002541 mOutputBufferQueue->onBufferReleased(generation);
Sungtak Lee214ce612023-11-01 10:01:13 +00002542}
2543
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002544void Codec2Client::Component::holdIgbaBlocks(
2545 const std::list<std::unique_ptr<C2Work>>& workList) {
2546 if (!mAidlBase) {
2547 return;
2548 }
2549 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2550 mGraphicBufferAllocators->current();
2551 if (!gba) {
2552 return;
2553 }
2554 std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
2555 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2556 for (const std::unique_ptr<C2Work>& work : workList) {
2557 if (!work) [[unlikely]] {
2558 continue;
2559 }
2560 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
2561 if (!worklet) {
2562 continue;
2563 }
2564 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
2565 if (buffer) {
2566 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
2567 std::shared_ptr<_C2BlockPoolData> poolData =
2568 _C2BlockFactory::GetGraphicBlockPoolData(block);
2569 _C2BlockFactory::RegisterIgba(poolData, igba);
2570 }
2571 }
2572 }
2573 }
2574 }
2575}
2576
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002577c2_status_t Codec2Client::Component::connectToInputSurface(
2578 const std::shared_ptr<InputSurface>& inputSurface,
2579 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002580 if (mAidlBase) {
2581 // FIXME
2582 return C2_OMITTED;
2583 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002584 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002585 Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002586 inputSurface->mBase,
2587 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002588 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002589 status = static_cast<c2_status_t>(s);
2590 if (status != C2_OK) {
2591 LOG(DEBUG) << "connectToInputSurface -- call failed: "
2592 << status << ".";
2593 return;
2594 }
2595 *connection = std::make_shared<InputSurfaceConnection>(c);
2596 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08002597 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002598 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002599 return C2_TRANSACTION_FAILED;
2600 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002601 return status;
2602}
2603
2604c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002605 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002606 const sp<HGraphicBufferSource>& source,
2607 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002608 if (mAidlBase) {
2609 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
2610 return C2_OMITTED;
2611 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002612 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002613 Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002614 producer, source,
2615 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002616 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002617 status = static_cast<c2_status_t>(s);
2618 if (status != C2_OK) {
2619 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
2620 << status << ".";
2621 return;
2622 }
2623 *connection = std::make_shared<InputSurfaceConnection>(c);
2624 });
2625 if (!transStatus.isOk()) {
2626 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
2627 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002628 }
2629 return status;
2630}
2631
2632c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002633 if (mAidlBase) {
2634 // FIXME
2635 return C2_OMITTED;
2636 }
2637 Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002638 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002639 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002640 return C2_TRANSACTION_FAILED;
2641 }
2642 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002643 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002644 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002645 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
2646 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002647 }
2648 return status;
2649}
2650
Wonsik Kime8e98152022-12-16 16:04:17 -08002651Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
2652 // This object never gets destructed
2653 static AidlDeathManager *sManager = new AidlDeathManager();
2654 return sManager;
2655}
2656
Pawin Vongmasa36653902018-11-15 00:10:25 -08002657c2_status_t Codec2Client::Component::setDeathListener(
2658 const std::shared_ptr<Component>& component,
2659 const std::shared_ptr<Listener>& listener) {
2660
2661 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
2662 std::weak_ptr<Component> component;
2663 std::weak_ptr<Listener> base;
2664
2665 virtual void serviceDied(
2666 uint64_t /* cookie */,
2667 const wp<::android::hidl::base::V1_0::IBase>& /* who */
2668 ) override {
2669 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
2670 listener->onDeath(component);
2671 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002672 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002673 }
2674 }
2675 };
2676
Wonsik Kime8e98152022-12-16 16:04:17 -08002677 if (component->mAidlBase) {
2678 size_t seq;
2679 if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
2680 component->mAidlDeathSeq = seq;
2681 }
2682 return C2_OK;
2683 }
2684
Pawin Vongmasa36653902018-11-15 00:10:25 -08002685 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
2686 deathRecipient->base = listener;
2687 deathRecipient->component = component;
2688
2689 component->mDeathRecipient = deathRecipient;
Wonsik Kime8e98152022-12-16 16:04:17 -08002690 Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002691 component->mDeathRecipient, 0);
2692 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002693 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002694 return C2_TRANSACTION_FAILED;
2695 }
2696 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002697 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002698 return C2_CORRUPTED;
2699 }
2700 return C2_OK;
2701}
2702
2703// Codec2Client::InputSurface
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002704Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002705 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002706 [base]() -> sp<c2_hidl::IConfigurable> {
2707 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002708 base->getConfigurable();
2709 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002710 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002711 nullptr;
2712 }()
2713 },
2714 mBase{base},
2715 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002716 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
2717 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002718 base->getGraphicBufferProducer();
2719 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002720 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002721 nullptr;
2722 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002723}
2724
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002725sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08002726 Codec2Client::InputSurface::getGraphicBufferProducer() const {
2727 return mGraphicBufferProducer;
2728}
2729
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002730sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002731 return mBase;
2732}
2733
2734// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08002735Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002736 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002737 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002738 [base]() -> sp<c2_hidl::IConfigurable> {
2739 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002740 base->getConfigurable();
2741 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002742 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002743 nullptr;
2744 }()
2745 },
2746 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002747}
2748
2749c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002750 Return<c2_hidl::Status> transResult = mBase->disconnect();
2751 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002752}
2753
2754} // namespace android