blob: 9ed94583a3af341ca78b855a50e58e399de7a4e5 [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 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000638 c2_aidl::IConfigurable::QueryResult result;
Wonsik Kim1caded02022-12-09 13:03:11 -0800639 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 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000644 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800645
Wonsik Kim1caded02022-12-09 13:03:11 -0800646 std::vector<C2Param*> paramPointers;
Sungtak Lee932255f2024-01-03 10:57:45 +0000647 if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result.params)) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800648 LOG(ERROR) << "query -- error while parsing params.";
649 return C2_CORRUPTED;
650 }
651 size_t i = 0;
Wonsik Kim977176c2023-12-18 17:14:20 -0800652 size_t numUpdatedStackParams = 0;
653 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800654 C2Param* paramPointer = *it;
655 if (numStackIndices > 0) {
656 --numStackIndices;
657 if (!paramPointer) {
658 LOG(DEBUG) << "query -- null stack param.";
659 ++it;
660 continue;
661 }
662 for (; i < stackParams.size() && !stackParams[i]; ) {
663 ++i;
664 }
665 if (i >= stackParams.size()) {
666 LOG(ERROR) << "query -- unexpected error.";
667 status = C2_CORRUPTED;
668 break;
669 }
670 if (stackParams[i]->index() != paramPointer->index()) {
671 LOG(DEBUG) << "query -- param skipped: "
672 "index = "
673 << stackParams[i]->index() << ".";
674 stackParams[i++]->invalidate();
675 // this means that the param could not be queried.
676 // signalling C2_BAD_INDEX to the client.
677 status = C2_BAD_INDEX;
678 continue;
679 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800680 if (stackParams[i++]->updateFrom(*paramPointer)) {
681 ++numUpdatedStackParams;
682 } else {
Wonsik Kim1caded02022-12-09 13:03:11 -0800683 LOG(WARNING) << "query -- param update failed: "
684 "index = "
685 << paramPointer->index() << ".";
686 }
687 } else {
688 if (!paramPointer) {
689 LOG(DEBUG) << "query -- null heap param.";
690 ++it;
691 continue;
692 }
693 if (!heapParams) {
694 LOG(WARNING) << "query -- "
695 "unexpected extra stack param.";
696 } else {
697 heapParams->emplace_back(C2Param::Copy(*paramPointer));
698 }
699 }
700 ++it;
701 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800702 size_t numQueried = numUpdatedStackParams;
703 if (heapParams) {
704 numQueried += heapParams->size();
705 }
706 if (status == C2_OK && indices.size() != numQueried) {
707 status = C2_BAD_INDEX;
708 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800709 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800710}
711
712c2_status_t Codec2ConfigurableClient::AidlImpl::config(
713 const std::vector<C2Param*> &params,
714 c2_blocking_t mayBlock,
715 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800716 c2_aidl::Params aidlParams;
717 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
718 LOG(ERROR) << "config -- bad input.";
719 return C2_TRANSACTION_FAILED;
720 }
721 c2_aidl::IConfigurable::ConfigResult result;
722 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800723 c2_status_t status = GetC2Status(transStatus, "config");
724 if (status != C2_OK) {
725 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800726 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000727 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800728 size_t i = failures->size();
729 failures->resize(i + result.failures.size());
730 for (const c2_aidl::SettingResult& sf : result.failures) {
731 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
732 LOG(ERROR) << "config -- invalid SettingResult returned.";
733 return C2_CORRUPTED;
734 }
735 }
736 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
737 LOG(ERROR) << "config -- "
738 << "failed to parse returned params.";
739 status = C2_CORRUPTED;
740 }
741 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800742}
743
744c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
745 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800746 // TODO: Cache and query properly!
747 std::vector<c2_aidl::ParamDescriptor> result;
748 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
749 std::numeric_limits<uint32_t>::min(),
750 std::numeric_limits<uint32_t>::max(),
751 &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800752 c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
753 if (status != C2_OK) {
754 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800755 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800756 size_t i = params->size();
757 params->resize(i + result.size());
758 for (const c2_aidl::ParamDescriptor& sp : result) {
759 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
760 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
761 return C2_CORRUPTED;
762 }
763 }
764 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800765}
766
767c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
768 std::vector<C2FieldSupportedValuesQuery>& fields,
769 c2_blocking_t mayBlock) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800770 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
771 for (size_t i = 0; i < fields.size(); ++i) {
772 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
773 LOG(ERROR) << "querySupportedValues -- bad input";
774 return C2_TRANSACTION_FAILED;
775 }
776 }
777
Sungtak Lee932255f2024-01-03 10:57:45 +0000778 c2_aidl::IConfigurable::QuerySupportedValuesResult result;
779
Wonsik Kim1caded02022-12-09 13:03:11 -0800780 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
781 inFields, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800782 c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
783 if (status != C2_OK) {
784 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800785 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000786 status = static_cast<c2_status_t>(result.status.status);
787 if (result.values.size() != fields.size()) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800788 LOG(ERROR) << "querySupportedValues -- "
789 "input and output lists "
790 "have different sizes.";
791 return C2_CORRUPTED;
792 }
793 for (size_t i = 0; i < fields.size(); ++i) {
Sungtak Lee932255f2024-01-03 10:57:45 +0000794 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result.values[i])) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800795 LOG(ERROR) << "querySupportedValues -- "
796 "invalid returned value.";
797 return C2_CORRUPTED;
798 }
799 }
800 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800801}
802
803// Codec2ConfigurableClient
804
805Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
806 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
807}
808
809Codec2ConfigurableClient::Codec2ConfigurableClient(
810 const std::shared_ptr<AidlBase> &aidlBase)
811 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
812}
813
814const C2String& Codec2ConfigurableClient::getName() const {
815 return mImpl->getName();
816}
817
818c2_status_t Codec2ConfigurableClient::query(
819 const std::vector<C2Param*>& stackParams,
820 const std::vector<C2Param::Index> &heapParamIndices,
821 c2_blocking_t mayBlock,
822 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
823 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
824}
825
826c2_status_t Codec2ConfigurableClient::config(
827 const std::vector<C2Param*> &params,
828 c2_blocking_t mayBlock,
829 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
830 return mImpl->config(params, mayBlock, failures);
831}
832
833c2_status_t Codec2ConfigurableClient::querySupportedParams(
834 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
835 return mImpl->querySupportedParams(params);
836}
837
838c2_status_t Codec2ConfigurableClient::querySupportedValues(
839 std::vector<C2FieldSupportedValuesQuery>& fields,
840 c2_blocking_t mayBlock) const {
841 return mImpl->querySupportedValues(fields, mayBlock);
842}
843
844
Pawin Vongmasa36653902018-11-15 00:10:25 -0800845// Codec2Client::Component::HidlListener
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800846struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800847 std::weak_ptr<Component> component;
848 std::weak_ptr<Listener> base;
849
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800850 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800851 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800852 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800853 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800854 return Void();
855 }
856 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800857 std::shared_ptr<Codec2Client::Component> strongComponent =
858 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800859 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800860 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861 }
862 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800863 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800864 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800865 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800866 }
867 return Void();
868 }
869
870 virtual Return<void> onTripped(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800871 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800872 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
873 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800874 for (size_t i = 0; i < settingResults.size(); ++i) {
875 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800876 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800877 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800878 return Void();
879 }
880 c2SettingResults[i] = std::move(c2SettingResult);
881 }
882 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
883 listener->onTripped(component, c2SettingResults);
884 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800885 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800886 }
887 return Void();
888 }
889
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800890 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800891 LOG(DEBUG) << "onError --"
892 << " status = " << s
893 << ", errorCode = " << errorCode
894 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800895 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800896 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897 errorCode : static_cast<c2_status_t>(s));
898 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800899 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800900 }
901 return Void();
902 }
903
904 virtual Return<void> onFramesRendered(
905 const hidl_vec<RenderedFrame>& renderedFrames) override {
906 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800907 if (!listener) {
908 LOG(DEBUG) << "onFramesRendered -- listener died.";
909 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800910 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800911 for (const RenderedFrame& renderedFrame : renderedFrames) {
912 listener->onFrameRendered(
913 renderedFrame.bufferQueueId,
914 renderedFrame.slotId,
915 renderedFrame.timestampNs);
916 }
917 return Void();
918 }
919
920 virtual Return<void> onInputBuffersReleased(
921 const hidl_vec<InputBuffer>& inputBuffers) override {
922 std::shared_ptr<Listener> listener = base.lock();
923 if (!listener) {
924 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
925 return Void();
926 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800927 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800928 LOG(VERBOSE) << "onInputBuffersReleased --"
929 " received death notification of"
930 " input buffer:"
931 " frameIndex = " << inputBuffer.frameIndex
932 << ", bufferIndex = " << inputBuffer.arrayIndex
933 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800934 listener->onInputBufferDone(
935 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800936 }
937 return Void();
938 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800939
Pawin Vongmasa36653902018-11-15 00:10:25 -0800940};
941
Wonsik Kime8e98152022-12-16 16:04:17 -0800942// Codec2Client::Component::AidlListener
943struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
944 std::weak_ptr<Component> component;
945 std::weak_ptr<Listener> base;
946
947 virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
948 std::list<std::unique_ptr<C2Work>> workItems;
949 if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
950 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
951 return ::ndk::ScopedAStatus::ok();
952 }
953 // release input buffers potentially held by the component from queue
954 std::shared_ptr<Codec2Client::Component> strongComponent =
955 component.lock();
956 if (strongComponent) {
957 strongComponent->handleOnWorkDone(workItems);
958 }
959 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
960 listener->onWorkDone(component, workItems);
961 } else {
962 LOG(DEBUG) << "onWorkDone -- listener died.";
963 }
964 return ::ndk::ScopedAStatus::ok();
965 }
966
967 virtual ::ndk::ScopedAStatus onTripped(
968 const std::vector<c2_aidl::SettingResult>& settingResults) override {
969 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
970 settingResults.size());
971 for (size_t i = 0; i < settingResults.size(); ++i) {
972 std::unique_ptr<C2SettingResult> c2SettingResult;
973 if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
974 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
975 return ::ndk::ScopedAStatus::ok();
976 }
977 c2SettingResults[i] = std::move(c2SettingResult);
978 }
979 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
980 listener->onTripped(component, c2SettingResults);
981 } else {
982 LOG(DEBUG) << "onTripped -- listener died.";
983 }
984 return ::ndk::ScopedAStatus::ok();
985 }
986
987 virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
988 LOG(DEBUG) << "onError --"
989 << " status = " << s.status
990 << ", errorCode = " << errorCode
991 << ".";
992 if (std::shared_ptr<Listener> listener = base.lock()) {
993 listener->onError(component, s.status == c2_aidl::Status::OK ?
994 errorCode : static_cast<c2_status_t>(s.status));
995 } else {
996 LOG(DEBUG) << "onError -- listener died.";
997 }
998 return ::ndk::ScopedAStatus::ok();
999 }
1000
1001 virtual ::ndk::ScopedAStatus onFramesRendered(
1002 const std::vector<RenderedFrame>& renderedFrames) override {
1003 std::shared_ptr<Listener> listener = base.lock();
1004 if (!listener) {
1005 LOG(DEBUG) << "onFramesRendered -- listener died.";
1006 return ::ndk::ScopedAStatus::ok();
1007 }
1008 for (const RenderedFrame& renderedFrame : renderedFrames) {
1009 listener->onFrameRendered(
1010 renderedFrame.bufferQueueId,
1011 renderedFrame.slotId,
1012 renderedFrame.timestampNs);
1013 }
1014 return ::ndk::ScopedAStatus::ok();
1015 }
1016
1017 virtual ::ndk::ScopedAStatus onInputBuffersReleased(
1018 const std::vector<InputBuffer>& inputBuffers) override {
1019 std::shared_ptr<Listener> listener = base.lock();
1020 if (!listener) {
1021 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1022 return ::ndk::ScopedAStatus::ok();
1023 }
1024 for (const InputBuffer& inputBuffer : inputBuffers) {
1025 LOG(VERBOSE) << "onInputBuffersReleased --"
1026 " received death notification of"
1027 " input buffer:"
1028 " frameIndex = " << inputBuffer.frameIndex
1029 << ", bufferIndex = " << inputBuffer.arrayIndex
1030 << ".";
1031 listener->onInputBufferDone(
1032 inputBuffer.frameIndex, inputBuffer.arrayIndex);
1033 }
1034 return ::ndk::ScopedAStatus::ok();
1035 }
1036
1037};
1038
1039// Codec2Client::Component::HidlBufferPoolSender
1040struct Codec2Client::Component::HidlBufferPoolSender :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001041 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
Wonsik Kime8e98152022-12-16 16:04:17 -08001042 HidlBufferPoolSender()
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001043 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
1044 }
1045};
1046
Wonsik Kime8e98152022-12-16 16:04:17 -08001047// Codec2Client::Component::AidlBufferPoolSender
1048struct Codec2Client::Component::AidlBufferPoolSender :
1049 c2_aidl::utils::DefaultBufferPoolSender {
1050 AidlBufferPoolSender()
1051 : c2_aidl::utils::DefaultBufferPoolSender() {
1052 }
1053};
1054
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001055// Codec2Client::Component::OutputBufferQueue
1056struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -07001057 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001058 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -07001059 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001060 }
1061};
1062
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001063// The class holds GraphicBufferAllocator and the associated id of
1064// HAL side BlockPool.
1065// This is tightly coupled with BlockPool creation and destruction.
1066// The life cycle inside class will be as follows.
1067//
1068// On createBlockPool client request.
1069// 1. this::create() creates a GraphicBufferAllocator and set it as
1070// the current.
1071// 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
1072// the GraphicBufferAllocator created in #1.
1073// 3. this::setCurrentId() associates the id returned in #2 to the current
1074//
1075// On destroyBlockPool cliet request
1076// 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
1077// from HAL process.
1078// 2. this::remove() destroys GraphicBufferAllocator which is associatted
1079// with the C2BlockPool in #1.
1080//
1081struct Codec2Client::Component::GraphicBufferAllocators {
1082private:
1083 std::optional<C2BlockPool::local_id_t> mCurrentId;
1084 std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
1085
1086 // A new BlockPool is created before the old BlockPool is destroyed.
1087 // This holds the reference of the old BlockPool when a new BlockPool is
1088 // created until the old BlockPool is explicitly requested for destruction.
1089 std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
1090 std::mutex mMutex;
1091
1092public:
1093 // Creates a GraphicBufferAllocator which will be passed to HAL
1094 // for creating C2BlockPool. And the created GraphicBufferAllocator
1095 // will be used afterwards by current().
1096 std::shared_ptr<AidlGraphicBufferAllocator> create() {
1097 std::unique_lock<std::mutex> l(mMutex);
1098 if (mCurrent) {
1099 // If this is not stopped.
1100 mCurrent->reset();
1101 if (mCurrentId.has_value()) {
1102 mOlds.emplace(mCurrentId.value(), mCurrent);
1103 }
1104 mCurrentId.reset();
1105 mCurrent.reset();
1106 }
1107 // TODO: integrate initial value with CCodec/CCodecBufferChannel
1108 mCurrent =
1109 AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
1110 ALOGD("GraphicBufferAllocator created");
1111 return mCurrent;
1112 }
1113
1114 // Associates the blockpool Id returned from HAL to the
1115 // current GraphicBufferAllocator.
1116 void setCurrentId(C2BlockPool::local_id_t id) {
1117 std::unique_lock<std::mutex> l(mMutex);
1118 CHECK(!mCurrentId.has_value());
1119 mCurrentId = id;
1120 }
1121
1122 // Returns the current GraphicBufferAllocator.
1123 std::shared_ptr<AidlGraphicBufferAllocator> current() {
1124 std::unique_lock<std::mutex> l(mMutex);
1125 return mCurrent;
1126 }
1127
1128 // Removes the GraphicBufferAllocator associated with given \p id.
1129 void remove(C2BlockPool::local_id_t id) {
1130 std::unique_lock<std::mutex> l(mMutex);
1131 mOlds.erase(id);
1132 if (mCurrentId == id) {
1133 if (mCurrent) {
1134 mCurrent->reset();
1135 mCurrent.reset();
1136 }
1137 mCurrentId.reset();
1138 }
1139 }
1140};
1141
Pawin Vongmasa36653902018-11-15 00:10:25 -08001142// Codec2Client
Wonsik Kime8e98152022-12-16 16:04:17 -08001143Codec2Client::Codec2Client(sp<HidlBase> const& base,
Sungtak Leef4b39512023-05-10 07:17:22 +00001144 sp<c2_hidl::IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001145 size_t serviceIndex)
Sungtak Leef4b39512023-05-10 07:17:22 +00001146 : Configurable{configurable},
Wonsik Kime8e98152022-12-16 16:04:17 -08001147 mHidlBase1_0{base},
1148 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1149 mHidlBase1_2{HidlBase1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001150 mServiceIndex{serviceIndex} {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001151 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001152 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001153 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001154 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08001155 mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 }
1157}
1158
Wonsik Kime8e98152022-12-16 16:04:17 -08001159Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
1160 std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
1161 size_t serviceIndex)
1162 : Configurable{configurable},
1163 mAidlBase{base},
1164 mServiceIndex{serviceIndex} {
1165 ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
1166 if (!transStatus.isOk()) {
1167 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1168 mAidlHostPoolManager.reset();
1169 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001170}
1171
Wonsik Kime8e98152022-12-16 16:04:17 -08001172sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
1173 return mHidlBase1_0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001174}
1175
Wonsik Kime8e98152022-12-16 16:04:17 -08001176sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
1177 return mHidlBase1_0;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001178}
1179
Wonsik Kime8e98152022-12-16 16:04:17 -08001180sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
1181 return mHidlBase1_1;
1182}
1183
1184sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
1185 return mHidlBase1_2;
1186}
1187
1188::ndk::SpAIBinder Codec2Client::getAidlBase() const {
1189 return mAidlBase ? mAidlBase->asBinder() : nullptr;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001190}
1191
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001192std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001193 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001194}
1195
Pawin Vongmasa36653902018-11-15 00:10:25 -08001196c2_status_t Codec2Client::createComponent(
1197 const C2String& name,
1198 const std::shared_ptr<Codec2Client::Listener>& listener,
1199 std::shared_ptr<Codec2Client::Component>* const component) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001200 if (mAidlBase) {
1201 std::shared_ptr<Component::AidlListener> aidlListener =
1202 Component::AidlListener::make<Component::AidlListener>();
1203 aidlListener->base = listener;
1204 std::shared_ptr<c2_aidl::IComponent> aidlComponent;
1205 ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
1206 name,
1207 aidlListener,
1208 bufferpool2_aidl::implementation::ClientManager::getInstance(),
1209 &aidlComponent);
1210 c2_status_t status = GetC2Status(transStatus, "createComponent");
1211 if (status != C2_OK) {
1212 return status;
1213 } else if (!aidlComponent) {
1214 LOG(ERROR) << "createComponent(" << name.c_str()
1215 << ") -- null component.";
1216 return C2_CORRUPTED;
1217 }
1218 *component = std::make_shared<Codec2Client::Component>(aidlComponent);
1219 status = (*component)->setDeathListener((*component), listener);
1220 if (status != C2_OK) {
1221 LOG(ERROR) << "createComponent(" << name.c_str()
1222 << ") -- failed to set up death listener: "
1223 << status << ".";
1224 }
1225 (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001226 aidlListener->component = *component;
Wonsik Kime8e98152022-12-16 16:04:17 -08001227 return status;
1228 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001229
Pawin Vongmasa36653902018-11-15 00:10:25 -08001230 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001231 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001232 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001233 Return<void> transStatus;
Wonsik Kime8e98152022-12-16 16:04:17 -08001234 if (mHidlBase1_2) {
1235 transStatus = mHidlBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001236 name,
1237 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001238 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001239 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001240 c2_hidl::Status s,
1241 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001242 status = static_cast<c2_status_t>(s);
1243 if (status != C2_OK) {
1244 return;
1245 }
1246 *component = std::make_shared<Codec2Client::Component>(c);
1247 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001248 });
1249 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001250 else if (mHidlBase1_1) {
1251 transStatus = mHidlBase1_1->createComponent_1_1(
Sungtak Lee8577dab2021-03-12 02:25:50 -08001252 name,
1253 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001254 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -08001255 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001256 c2_hidl::Status s,
1257 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -08001258 status = static_cast<c2_status_t>(s);
1259 if (status != C2_OK) {
1260 return;
1261 }
1262 *component = std::make_shared<Codec2Client::Component>(c);
1263 hidlListener->component = *component;
1264 });
Wonsik Kime8e98152022-12-16 16:04:17 -08001265 } else if (mHidlBase1_0) { // ver1_0
1266 transStatus = mHidlBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001267 name,
1268 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001269 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001270 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001271 c2_hidl::Status s,
1272 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001273 status = static_cast<c2_status_t>(s);
1274 if (status != C2_OK) {
1275 return;
1276 }
1277 *component = std::make_shared<Codec2Client::Component>(c);
1278 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001279 });
Sungtak Lee8577dab2021-03-12 02:25:50 -08001280 } else {
1281 status = C2_CORRUPTED;
1282 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001283 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001284 LOG(ERROR) << "createComponent(" << name.c_str()
1285 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001286 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001287 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001288 if (status == C2_NOT_FOUND) {
1289 LOG(VERBOSE) << "createComponent(" << name.c_str()
1290 << ") -- component not found.";
1291 } else {
1292 LOG(ERROR) << "createComponent(" << name.c_str()
1293 << ") -- call failed: " << status << ".";
1294 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001295 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001296 } else if (!*component) {
1297 LOG(ERROR) << "createComponent(" << name.c_str()
1298 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001299 return C2_CORRUPTED;
1300 }
1301
1302 status = (*component)->setDeathListener(*component, listener);
1303 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001304 LOG(ERROR) << "createComponent(" << name.c_str()
1305 << ") -- failed to set up death listener: "
1306 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001307 }
1308
Wonsik Kime8e98152022-12-16 16:04:17 -08001309 (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001310 return status;
1311}
1312
1313c2_status_t Codec2Client::createInterface(
1314 const C2String& name,
1315 std::shared_ptr<Codec2Client::Interface>* const interface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001316 if (mAidlBase) {
1317 std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
1318 ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
1319 name,
1320 &aidlInterface);
1321 c2_status_t status = GetC2Status(transStatus, "createInterface");
1322 if (status != C2_OK) {
1323 return status;
1324 } else if (!aidlInterface) {
1325 LOG(ERROR) << "createInterface(" << name.c_str()
1326 << ") -- null interface.";
1327 return C2_CORRUPTED;
1328 }
1329 interface->reset(new Codec2Client::Interface(aidlInterface));
1330 return C2_OK;
1331 }
1332
Pawin Vongmasa36653902018-11-15 00:10:25 -08001333 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001334 Return<void> transStatus = mHidlBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001335 name,
1336 [&status, interface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001337 c2_hidl::Status s,
1338 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001339 status = static_cast<c2_status_t>(s);
1340 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001341 return;
1342 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001343 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001344 });
1345 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001346 LOG(ERROR) << "createInterface(" << name.c_str()
1347 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001348 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001349 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001350 if (status == C2_NOT_FOUND) {
1351 LOG(VERBOSE) << "createInterface(" << name.c_str()
1352 << ") -- component not found.";
1353 } else {
1354 LOG(ERROR) << "createInterface(" << name.c_str()
1355 << ") -- call failed: " << status << ".";
1356 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001357 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001358 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001359
Pawin Vongmasa36653902018-11-15 00:10:25 -08001360 return status;
1361}
1362
1363c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001364 std::shared_ptr<InputSurface>* const inputSurface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001365 if (mAidlBase) {
1366 // FIXME
1367 return C2_OMITTED;
1368 }
1369
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001370 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001371 Return<void> transStatus = mHidlBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001372 [&status, inputSurface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001373 c2_hidl::Status s,
1374 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001375 status = static_cast<c2_status_t>(s);
1376 if (status != C2_OK) {
1377 return;
1378 }
1379 *inputSurface = std::make_shared<InputSurface>(i);
1380 });
1381 if (!transStatus.isOk()) {
1382 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001383 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001384 } else if (status != C2_OK) {
1385 LOG(DEBUG) << "createInputSurface -- call failed: "
1386 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001387 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001388 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001389}
1390
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001391std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
1392 return Cache::List()[mServiceIndex].getTraits();
1393}
1394
1395std::vector<C2Component::Traits> Codec2Client::_listComponents(
1396 bool* success) const {
1397 std::vector<C2Component::Traits> traits;
1398 std::string const& serviceName = getServiceName();
Wonsik Kime8e98152022-12-16 16:04:17 -08001399
1400 if (mAidlBase) {
1401 std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
1402 ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
1403 if (!transStatus.isOk()) {
1404 LOG(ERROR) << "_listComponents -- transaction failed.";
1405 *success = false;
1406 } else {
1407 traits.resize(aidlTraits.size());
1408 *success = true;
1409 for (size_t i = 0; i < aidlTraits.size(); ++i) {
1410 if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
1411 LOG(ERROR) << "_listComponents -- corrupted output.";
1412 *success = false;
1413 traits.clear();
1414 break;
1415 }
1416 traits[i].owner = serviceName;
1417 }
1418 }
1419 return traits;
1420 }
1421 Return<void> transStatus = mHidlBase1_0->listComponents(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001422 [&traits, &serviceName](c2_hidl::Status s,
1423 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
1424 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001425 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001426 << static_cast<c2_status_t>(s) << ".";
1427 return;
1428 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001429 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001430 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001431 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001432 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001433 return;
1434 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001435 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001436 }
1437 });
1438 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001439 LOG(ERROR) << "_listComponents -- transaction failed.";
1440 *success = false;
1441 } else {
1442 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001443 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001444 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001445}
1446
1447c2_status_t Codec2Client::copyBuffer(
1448 const std::shared_ptr<C2Buffer>& src,
1449 const std::shared_ptr<C2Buffer>& dst) {
1450 // TODO: Implement?
1451 (void)src;
1452 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001453 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001454 return C2_OMITTED;
1455}
1456
Wonsik Kime8e98152022-12-16 16:04:17 -08001457std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001458 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1459 // should reflect the HAL API.
Wonsik Kime8e98152022-12-16 16:04:17 -08001460 struct HidlSimpleParamReflector : public C2ParamReflector {
1461 std::unique_ptr<C2StructDescriptor> describe(
1462 C2Param::CoreIndex coreIndex) const override {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001463 hidl_vec<c2_hidl::ParamIndex> indices(1);
1464 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001465 std::unique_ptr<C2StructDescriptor> descriptor;
1466 Return<void> transStatus = mBase->getStructDescriptors(
1467 indices,
1468 [&descriptor](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001469 c2_hidl::Status s,
1470 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001471 c2_status_t status = static_cast<c2_status_t>(s);
1472 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001473 LOG(DEBUG) << "SimpleParamReflector -- "
1474 "getStructDescriptors() failed: "
1475 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001476 descriptor.reset();
1477 return;
1478 }
1479 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001480 LOG(DEBUG) << "SimpleParamReflector -- "
1481 "getStructDescriptors() "
1482 "returned vector of size "
1483 << sd.size() << ". "
1484 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001485 descriptor.reset();
1486 return;
1487 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001488 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001489 LOG(DEBUG) << "SimpleParamReflector -- "
1490 "getStructDescriptors() returned "
1491 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001492 descriptor.reset();
1493 return;
1494 }
1495 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001496 if (!transStatus.isOk()) {
1497 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1498 << transStatus.description();
1499 descriptor.reset();
1500 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001501 return descriptor;
1502 }
1503
Wonsik Kime8e98152022-12-16 16:04:17 -08001504 HidlSimpleParamReflector(sp<HidlBase> base)
Pawin Vongmasa36653902018-11-15 00:10:25 -08001505 : mBase(base) { }
1506
Wonsik Kime8e98152022-12-16 16:04:17 -08001507 sp<HidlBase> mBase;
1508 };
1509 struct AidlSimpleParamReflector : public C2ParamReflector {
1510 std::unique_ptr<C2StructDescriptor> describe(
1511 C2Param::CoreIndex coreIndex) const override {
1512 std::vector<c2_aidl::StructDescriptor> aidlDesc;
1513 std::unique_ptr<C2StructDescriptor> descriptor;
1514 ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
1515 {int32_t(coreIndex.coreIndex())},
1516 &aidlDesc);
1517 c2_status_t status = GetC2Status(transStatus, "describe");
1518 if (status != C2_OK) {
1519 descriptor.reset();
1520 } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
1521 LOG(ERROR) << "describe -- conversion failed.";
1522 descriptor.reset();
1523 }
1524 return descriptor;
1525 }
1526
1527 AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
1528 : mBase(base) { }
1529
1530 std::shared_ptr<AidlBase> mBase;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001531 };
1532
Wonsik Kime8e98152022-12-16 16:04:17 -08001533 if (mAidlBase) {
1534 return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
1535 }
1536 return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001537};
1538
Wonsik Kime8e98152022-12-16 16:04:17 -08001539std::vector<std::string> Codec2Client::CacheServiceNames() {
1540 std::vector<std::string> names;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001541
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001542 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001543 if (__builtin_available(android __ANDROID_API_S__, *)) {
1544 // Get AIDL service names
1545 AServiceManager_forEachDeclaredInstance(
1546 AidlBase::descriptor, &names, [](const char *name, void *context) {
1547 std::vector<std::string> *names = (std::vector<std::string> *)context;
1548 names->emplace_back(name);
1549 });
1550 } else {
1551 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
1552 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001553 } else {
1554 // Get HIDL service names
1555 using ::android::hardware::media::c2::V1_0::IComponentStore;
1556 using ::android::hidl::manager::V1_2::IServiceManager;
1557 while (true) {
1558 sp<IServiceManager> serviceManager = IServiceManager::getService();
1559 CHECK(serviceManager) << "Hardware service manager is not running.";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001560
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001561 Return<void> transResult;
1562 transResult = serviceManager->listManifestByInterface(
1563 IComponentStore::descriptor,
1564 [&names](
1565 hidl_vec<hidl_string> const& instanceNames) {
1566 names.insert(names.end(), instanceNames.begin(), instanceNames.end());
1567 });
1568 if (transResult.isOk()) {
1569 break;
1570 }
1571 LOG(ERROR) << "Could not retrieve the list of service instances of "
1572 << IComponentStore::descriptor
1573 << ". Retrying...";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001574 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001575 }
1576 // Sort service names in each category.
1577 std::stable_sort(
1578 names.begin(), names.end(),
1579 [](const std::string &a, const std::string &b) {
1580 // First compare by prefix: default -> vendor -> {everything else}
1581 constexpr int DEFAULT = 1;
1582 constexpr int VENDOR = 2;
1583 constexpr int OTHER = 3;
1584 int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
1585 (a.compare(0, 6, "vendor") == 0) ? VENDOR :
1586 OTHER);
1587 int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
1588 (b.compare(0, 6, "vendor") == 0) ? VENDOR :
1589 OTHER);
1590 if (aPrefix != bPrefix) {
1591 return aPrefix < bPrefix;
1592 }
1593 // If the prefix is the same, compare alphabetically
1594 return a < b;
1595 });
1596
1597 // Summarize to logcat.
1598 if (names.empty()) {
1599 LOG(INFO) << "No Codec2 services declared in the manifest.";
1600 } else {
1601 std::stringstream stringOutput;
1602 stringOutput << "Available Codec2 services:";
1603 for (std::string const& name : names) {
1604 stringOutput << " \"" << name << "\"";
1605 }
1606 LOG(INFO) << stringOutput.str();
1607 }
1608
1609 return names;
1610}
1611
1612std::vector<std::string> const& Codec2Client::GetServiceNames() {
1613 static std::vector<std::string> sServiceNames = CacheServiceNames();
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001614 return sServiceNames;
1615}
1616
Pawin Vongmasa36653902018-11-15 00:10:25 -08001617std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001618 const char* name,
1619 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001620 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001621 if (index == GetServiceNames().size()) {
1622 if (setAsPreferredCodec2ComponentStore) {
1623 LOG(WARNING) << "CreateFromService(" << name
1624 << ") -- preferred C2ComponentStore not set.";
1625 }
1626 return nullptr;
1627 }
1628 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1629 if (setAsPreferredCodec2ComponentStore) {
1630 SetPreferredCodec2ComponentStore(
1631 std::make_shared<Client2Store>(client));
1632 LOG(INFO) << "CreateFromService(" << name
1633 << ") -- service set as preferred C2ComponentStore.";
1634 }
1635 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001636}
1637
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001638std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1639 CreateFromAllServices() {
1640 std::vector<std::shared_ptr<Codec2Client>> clients(
1641 GetServiceNames().size());
1642 for (size_t i = GetServiceNames().size(); i > 0; ) {
1643 --i;
1644 clients[i] = _CreateFromIndex(i);
1645 }
1646 return clients;
1647}
1648
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001649std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001650 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001651 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Wonsik Kime8e98152022-12-16 16:04:17 -08001652
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001653 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001654 if (__builtin_available(android __ANDROID_API_S__, *)) {
1655 std::string instanceName =
1656 ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
1657 if (AServiceManager_isDeclared(instanceName.c_str())) {
1658 std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
1659 ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
1660 CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
1661 " inaccessible for unknown reasons.";
1662 LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
1663 std::shared_ptr<c2_aidl::IConfigurable> configurable;
1664 ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
1665 CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
1666 "does not have IConfigurable.";
1667 return std::make_shared<Codec2Client>(baseStore, configurable, index);
1668 } else {
1669 LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
1670 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001671 } else {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001672 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
Wonsik Kime8e98152022-12-16 16:04:17 -08001673 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001674 } else {
1675 std::string instanceName = "android.hardware.media.c2/" + name;
1676 sp<HidlBase> baseStore = HidlBase::getService(name);
1677 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1678 " inaccessible for unknown reasons.";
1679 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
1680 Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
1681 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1682 "does not have IConfigurable.";
1683 sp<c2_hidl::IConfigurable> configurable =
1684 static_cast<sp<c2_hidl::IConfigurable>>(transResult);
1685 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Wonsik Kime8e98152022-12-16 16:04:17 -08001686 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001687 return nullptr;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001688}
1689
1690c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001691 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001692 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001693 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1694 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001695 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1696
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001697 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001698 static std::mutex key2IndexMutex;
1699 static std::map<std::string, size_t> key2Index;
1700
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001701 // By default try all stores. However, try the last known client first. If
1702 // the last known client fails, retry once. We do this by pushing the last
1703 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001704 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001705 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001706 indices.push_front(--index);
1707 }
1708
1709 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001710 {
1711 std::scoped_lock lock{key2IndexMutex};
1712 auto it = key2Index.find(key);
1713 if (it != key2Index.end()) {
1714 indices.push_front(it->second);
1715 wasMapped = true;
1716 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001717 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001718
1719 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001720 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001721 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1722 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001723 status = predicate(client);
1724 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001725 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001726 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001727 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001728 } else if (status == C2_NO_MEMORY) {
1729 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001730 } else if (status == C2_TRANSACTION_FAILED) {
1731 LOG(WARNING) << "\"" << key << "\" failed for service \""
1732 << client->getName()
1733 << "\" due to transaction failure. "
1734 << "(Service may have crashed.)"
1735 << (tries > 1 ? " Retrying..." : "");
1736 cache.invalidate();
1737 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001738 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001739 if (wasMapped) {
1740 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1741 << client->getName() << "\". Retrying...";
1742 wasMapped = false;
1743 }
1744 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001745 }
1746 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001747 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001748}
1749
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001750c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001751 const char* componentName,
1752 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001753 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001754 std::shared_ptr<Codec2Client>* owner,
1755 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001756 std::string key{"create:"};
1757 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001758 c2_status_t status = ForAllServices(
1759 key,
1760 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001761 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001762 const std::shared_ptr<Codec2Client> &client)
1763 -> c2_status_t {
1764 c2_status_t status = client->createComponent(componentName,
1765 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001766 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001767 if (status == C2_OK) {
1768 if (owner) {
1769 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001770 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001771 } else if (status != C2_NOT_FOUND) {
1772 LOG(DEBUG) << "IComponentStore("
1773 << client->getServiceName()
1774 << ")::createComponent(\"" << componentName
1775 << "\") returned status = "
1776 << status << ".";
1777 }
1778 return status;
1779 });
1780 if (status != C2_OK) {
1781 LOG(DEBUG) << "Failed to create component \"" << componentName
1782 << "\" from all known services. "
1783 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001784 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001785 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001786}
1787
Wonsik Kime8e98152022-12-16 16:04:17 -08001788std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001789 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001790 std::shared_ptr<Codec2Client>* owner,
1791 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001792 std::string key{"create:"};
1793 key.append(interfaceName);
1794 std::shared_ptr<Interface> interface;
1795 c2_status_t status = ForAllServices(
1796 key,
1797 numberOfAttempts,
1798 [owner, &interface, interfaceName](
1799 const std::shared_ptr<Codec2Client> &client)
1800 -> c2_status_t {
1801 c2_status_t status = client->createInterface(interfaceName,
1802 &interface);
1803 if (status == C2_OK) {
1804 if (owner) {
1805 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001806 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001807 } else if (status != C2_NOT_FOUND) {
1808 LOG(DEBUG) << "IComponentStore("
1809 << client->getServiceName()
1810 << ")::createInterface(\"" << interfaceName
1811 << "\") returned status = "
1812 << status << ".";
1813 }
1814 return status;
1815 });
1816 if (status != C2_OK) {
1817 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1818 << "\" from all known services. "
1819 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001820 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001821 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001822}
1823
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001824std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1825 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001826 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001827 for (Cache& cache : Cache::List()) {
1828 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1829 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001830 }
1831 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001832 }()};
1833 return sList;
1834}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001835
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001836std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1837 char const* serviceName) {
Pawin Vongmasa18588322019-05-18 01:52:13 -07001838 int32_t inputSurfaceSetting = ::android::base::GetIntProperty(
1839 "debug.stagefright.c2inputsurface", int32_t(0));
1840 if (inputSurfaceSetting <= 0) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001841 return nullptr;
1842 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001843 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001844 if (serviceName) {
1845 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001846 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001847 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1848 << serviceName << "\"";
1849 }
1850 }
1851
1852 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001853 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001854 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1855 if (client->createInputSurface(&inputSurface) == C2_OK) {
1856 return inputSurface;
1857 }
1858 }
1859 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1860 "from all services...";
1861 for (Cache& cache : Cache::List()) {
1862 std::shared_ptr<Codec2Client> client = cache.getClient();
1863 if (client->createInputSurface(&inputSurface) == C2_OK) {
1864 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1865 "service \"" << client->getServiceName() << "\"";
1866 return inputSurface;
1867 }
1868 }
1869 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1870 "from all services";
1871 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001872}
1873
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001874// Codec2Client::Interface
Wonsik Kime8e98152022-12-16 16:04:17 -08001875Codec2Client::Interface::Interface(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001876 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001877 [base]() -> sp<c2_hidl::IConfigurable> {
1878 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001879 base->getConfigurable();
1880 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001881 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001882 nullptr;
1883 }()
1884 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001885 mHidlBase{base} {
1886}
1887
1888Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
1889 : Configurable{
1890 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
1891 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
1892 ::ndk::ScopedAStatus transStatus =
1893 base->getConfigurable(&aidlConfigurable);
1894 return transStatus.isOk() ? aidlConfigurable : nullptr;
1895 }()
1896 },
1897 mAidlBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001898}
1899
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001900// Codec2Client::Component
Wonsik Kime8e98152022-12-16 16:04:17 -08001901
1902class Codec2Client::Component::AidlDeathManager {
1903public:
1904 AidlDeathManager()
1905 : mSeq(0),
1906 mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
1907 }
1908
1909 ~AidlDeathManager() = default;
1910
1911 bool linkToDeath(
1912 const std::shared_ptr<Component> &comp,
1913 const std::shared_ptr<Listener> &listener,
1914 size_t *seqPtr) {
1915 std::unique_lock lock(mMutex);
1916 size_t seq = mSeq++;
1917 if (!mMap.try_emplace(seq, comp, listener).second) {
1918 return false;
1919 }
1920 if (STATUS_OK != AIBinder_linkToDeath(
1921 comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
1922 mMap.erase(seq);
1923 return false;
1924 }
1925 *seqPtr = seq;
1926 return true;
1927 }
1928
1929 void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
1930 std::unique_lock lock(mMutex);
1931 AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
1932 mMap.erase(seq);
1933 }
1934
1935private:
1936 std::mutex mMutex;
1937 size_t mSeq;
1938 typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
1939 std::map<size_t, Context> mMap;
1940 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
1941
1942 bool extractContext(size_t seq, Context *context) {
1943 std::unique_lock lock(mMutex);
1944 auto node = mMap.extract(seq);
1945 if (!node) {
1946 return false;
1947 }
1948 *context = node.mapped();
1949 return true;
1950 }
1951
1952 static void OnBinderDied(void *cookie) {
1953 size_t seq = size_t(cookie);
1954 Context context;
1955 if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
1956 return;
1957 }
1958 std::weak_ptr<Component> weakComponent;
1959 std::weak_ptr<Listener> weakListener;
1960 std::tie(weakComponent, weakListener) = context;
1961 if (std::shared_ptr<Listener> listener = weakListener.lock()) {
1962 listener->onDeath(weakComponent);
1963 } else {
1964 LOG(DEBUG) << "onDeath -- listener died.";
1965 }
1966 }
1967};
1968
1969Codec2Client::Component::Component(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001970 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001971 [base]() -> sp<c2_hidl::IConfigurable> {
1972 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001973 base->getInterface();
1974 if (!transResult1.isOk()) {
1975 return nullptr;
1976 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001977 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1978 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001979 getConfigurable();
1980 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001981 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001982 nullptr;
1983 }()
1984 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001985 mHidlBase1_0{base},
1986 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1987 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1988 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001989 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1990}
1991
Wonsik Kime8e98152022-12-16 16:04:17 -08001992Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001993 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001994 [base]() -> sp<c2_hidl::IConfigurable> {
1995 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001996 base->getInterface();
1997 if (!transResult1.isOk()) {
1998 return nullptr;
1999 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002000 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2001 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002002 getConfigurable();
2003 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002004 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002005 nullptr;
2006 }()
2007 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002008 mHidlBase1_0{base},
2009 mHidlBase1_1{base},
2010 mHidlBase1_2{HidlBase1_2::castFrom(base)},
2011 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Sungtak Lee8577dab2021-03-12 02:25:50 -08002012 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2013}
2014
Wonsik Kime8e98152022-12-16 16:04:17 -08002015Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
Sungtak Lee8577dab2021-03-12 02:25:50 -08002016 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002017 [base]() -> sp<c2_hidl::IConfigurable> {
2018 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08002019 base->getInterface();
2020 if (!transResult1.isOk()) {
2021 return nullptr;
2022 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002023 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2024 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08002025 getConfigurable();
2026 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002027 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08002028 nullptr;
2029 }()
2030 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002031 mHidlBase1_0{base},
2032 mHidlBase1_1{base},
2033 mHidlBase1_2{base},
2034 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2035 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2036}
2037
2038Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
2039 : Configurable{
2040 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2041 std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
2042 ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
2043 if (!transStatus.isOk()) {
2044 return nullptr;
2045 }
2046 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2047 transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
2048 return transStatus.isOk() ? aidlConfigurable : nullptr;
2049 }()
2050 },
2051 mAidlBase{base},
2052 mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002053 mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002054}
2055
2056Codec2Client::Component::~Component() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002057 if (mAidlDeathSeq) {
2058 GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
2059 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002060}
2061
2062c2_status_t Codec2Client::Component::createBlockPool(
2063 C2Allocator::id_t id,
2064 C2BlockPool::local_id_t* blockPoolId,
2065 std::shared_ptr<Codec2Client::Configurable>* configurable) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002066 if (mAidlBase) {
2067 c2_aidl::IComponent::BlockPool aidlBlockPool;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002068 c2_status_t status = C2_OK;
2069
2070 // TODO: Temporary mapping for the current CCodecBufferChannel.
2071 // Handle this properly and remove this temporary allocator mapping.
2072 id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
2073 C2PlatformAllocatorStore::IGBA : id;
2074
Sungtak Leefffb5692024-01-18 11:22:38 +00002075 c2_aidl::IComponent::BlockPoolAllocator allocator;
2076 allocator.allocatorId = id;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002077 if (id == C2PlatformAllocatorStore::IGBA) {
2078 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2079 mGraphicBufferAllocators->create();
2080 ::ndk::ScopedFileDescriptor waitableFd;
2081 ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
2082 status = GetC2Status(ret, "Gba::getWaitableFd");
2083 if (status != C2_OK) {
2084 return status;
2085 }
Sungtak Leefffb5692024-01-18 11:22:38 +00002086 c2_aidl::IComponent::GbAllocator gbAllocator;
2087 gbAllocator.waitableFd = std::move(waitableFd);
2088 gbAllocator.igba =
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002089 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
Sungtak Leefffb5692024-01-18 11:22:38 +00002090 allocator.gbAllocator = std::move(gbAllocator);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002091 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2092 allocator, &aidlBlockPool);
2093 status = GetC2Status(transStatus, "createBlockPool");
2094 if (status != C2_OK) {
2095 return status;
2096 }
2097 mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
2098 } else {
2099 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
Sungtak Leefffb5692024-01-18 11:22:38 +00002100 allocator, &aidlBlockPool);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002101 status = GetC2Status(transStatus, "createBlockPool");
2102 if (status != C2_OK) {
2103 return status;
2104 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002105 }
2106 *blockPoolId = aidlBlockPool.blockPoolId;
2107 *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
2108 return C2_OK;
2109 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002110 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002111 Return<void> transStatus = mHidlBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002112 static_cast<uint32_t>(id),
2113 [&status, blockPoolId, configurable](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002114 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08002115 uint64_t pId,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002116 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002117 status = static_cast<c2_status_t>(s);
2118 configurable->reset();
2119 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002120 LOG(DEBUG) << "createBlockPool -- call failed: "
2121 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002122 return;
2123 }
2124 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002125 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002126 });
2127 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002128 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002129 return C2_TRANSACTION_FAILED;
2130 }
2131 return status;
2132}
2133
2134c2_status_t Codec2Client::Component::destroyBlockPool(
2135 C2BlockPool::local_id_t localId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002136 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002137 mGraphicBufferAllocators->remove(localId);
Wonsik Kime8e98152022-12-16 16:04:17 -08002138 ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
2139 return GetC2Status(transStatus, "destroyBlockPool");
2140 }
2141 Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002142 static_cast<uint64_t>(localId));
2143 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002144 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002145 return C2_TRANSACTION_FAILED;
2146 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002147 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002148}
2149
Wonsik Kimab34ed62019-01-31 15:28:46 -08002150void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002151 const std::list<std::unique_ptr<C2Work>> &workItems) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002152 if (mAidlBase) {
2153 holdIgbaBlocks(workItems);
2154 } else {
2155 // Output bufferqueue-based blocks' lifetime management
2156 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
2157 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002158}
2159
2160c2_status_t Codec2Client::Component::queue(
2161 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002162 if (mAidlBase) {
2163 c2_aidl::WorkBundle workBundle;
2164 if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
2165 LOG(ERROR) << "queue -- bad input.";
2166 return C2_TRANSACTION_FAILED;
2167 }
2168 ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
2169 return GetC2Status(transStatus, "queue");
2170 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002171 c2_hidl::WorkBundle workBundle;
Wonsik Kime8e98152022-12-16 16:04:17 -08002172 if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002173 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002174 return C2_TRANSACTION_FAILED;
2175 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002176 Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002177 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002178 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002179 return C2_TRANSACTION_FAILED;
2180 }
2181 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002182 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002183 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002184 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002185 }
2186 return status;
2187}
2188
2189c2_status_t Codec2Client::Component::flush(
2190 C2Component::flush_mode_t mode,
2191 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002192 (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
2193 c2_status_t status = C2_OK;
2194 if (mAidlBase) {
2195 c2_aidl::WorkBundle workBundle;
2196 ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
2197 c2_status_t status = GetC2Status(transStatus, "flush");
2198 if (status != C2_OK) {
2199 return status;
2200 }
2201 if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
2202 LOG(DEBUG) << "flush -- flushedWork corrupted.";
2203 return C2_CORRUPTED;
2204 }
2205 } else {
2206 Return<void> transStatus = mHidlBase1_0->flush(
2207 [&status, flushedWork](
2208 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
2209 status = static_cast<c2_status_t>(s);
2210 if (status != C2_OK) {
2211 LOG(DEBUG) << "flush -- call failed: " << status << ".";
2212 return;
2213 }
2214 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
2215 status = C2_CORRUPTED;
2216 } else {
2217 status = C2_OK;
2218 }
2219 });
2220 if (!transStatus.isOk()) {
2221 LOG(ERROR) << "flush -- transaction failed.";
2222 return C2_TRANSACTION_FAILED;
2223 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002224 }
2225
2226 // Indices of flushed work items.
2227 std::vector<uint64_t> flushedIndices;
2228 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
2229 if (work) {
2230 if (work->worklets.empty()
2231 || !work->worklets.back()
2232 || (work->worklets.back()->output.flags &
2233 C2FrameData::FLAG_INCOMPLETE) == 0) {
2234 // input is complete
2235 flushedIndices.emplace_back(
2236 work->input.ordinal.frameIndex.peeku());
2237 }
2238 }
2239 }
2240
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002241 if (mAidlBase) {
2242 holdIgbaBlocks(*flushedWork);
2243 } else {
2244 // Output bufferqueue-based blocks' lifetime management
2245 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
2246 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002247
2248 return status;
2249}
2250
2251c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002252 if (mAidlBase) {
2253 ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
2254 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2255 return GetC2Status(transStatus, "drain");
2256 }
2257 Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002258 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2259 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002260 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002261 return C2_TRANSACTION_FAILED;
2262 }
2263 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002264 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002265 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002266 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002267 }
2268 return status;
2269}
2270
2271c2_status_t Codec2Client::Component::start() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002272 if (mAidlBase) {
2273 ::ndk::ScopedAStatus transStatus = mAidlBase->start();
2274 return GetC2Status(transStatus, "start");
2275 }
2276 Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002277 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002278 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002279 return C2_TRANSACTION_FAILED;
2280 }
2281 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002282 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002283 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002284 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002285 }
2286 return status;
2287}
2288
2289c2_status_t Codec2Client::Component::stop() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002290 if (mAidlBase) {
2291 ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
2292 return GetC2Status(transStatus, "stop");
2293 }
2294 Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002295 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002296 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002297 return C2_TRANSACTION_FAILED;
2298 }
2299 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002300 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002301 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002302 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002303 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002304 return status;
2305}
2306
2307c2_status_t Codec2Client::Component::reset() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002308 if (mAidlBase) {
2309 ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
2310 return GetC2Status(transStatus, "reset");
2311 }
2312 Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002313 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002314 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002315 return C2_TRANSACTION_FAILED;
2316 }
2317 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002318 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002319 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002320 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002321 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002322 return status;
2323}
2324
2325c2_status_t Codec2Client::Component::release() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002326 if (mAidlBase) {
2327 ::ndk::ScopedAStatus transStatus = mAidlBase->release();
2328 return GetC2Status(transStatus, "release");
2329 }
2330 Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002331 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002332 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002333 return C2_TRANSACTION_FAILED;
2334 }
2335 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002336 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002337 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002338 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002339 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002340 return status;
2341}
2342
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002343c2_status_t Codec2Client::Component::configureVideoTunnel(
2344 uint32_t avSyncHwId,
2345 native_handle_t** sidebandHandle) {
2346 *sidebandHandle = nullptr;
Wonsik Kime8e98152022-12-16 16:04:17 -08002347 if (mAidlBase) {
2348 ::aidl::android::hardware::common::NativeHandle handle;
2349 ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
2350 c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
2351 if (status != C2_OK) {
2352 return status;
2353 }
2354 if (isAidlNativeHandleEmpty(handle)) {
2355 LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
2356 } else {
2357 *sidebandHandle = dupFromAidl(handle);
2358 }
2359 return C2_OK;
2360 }
2361 if (!mHidlBase1_1) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002362 return C2_OMITTED;
2363 }
2364 c2_status_t status{};
Wonsik Kime8e98152022-12-16 16:04:17 -08002365 Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002366 [&status, sidebandHandle](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002367 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002368 status = static_cast<c2_status_t>(s);
2369 if (h.getNativeHandle()) {
2370 *sidebandHandle = native_handle_clone(h.getNativeHandle());
2371 }
2372 });
2373 if (!transStatus.isOk()) {
2374 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
2375 return C2_TRANSACTION_FAILED;
2376 }
2377 return status;
2378}
2379
Pawin Vongmasa36653902018-11-15 00:10:25 -08002380c2_status_t Codec2Client::Component::setOutputSurface(
2381 C2BlockPool::local_id_t blockPoolId,
2382 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07002383 uint32_t generation,
2384 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002385 if (mAidlBase) {
2386 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2387 mGraphicBufferAllocators->current();
2388 if (!gba) {
2389 LOG(ERROR) << "setOutputSurface for AIDL -- "
2390 "GraphicBufferAllocator was not created.";
2391 return C2_CORRUPTED;
2392 }
2393 bool ret = gba->configure(surface, generation, maxDequeueCount);
2394 return ret ? C2_OK : C2_CORRUPTED;
2395 }
Sungtak Lee08515812019-06-05 11:16:32 -07002396 uint64_t bqId = 0;
2397 sp<IGraphicBufferProducer> nullIgbp;
2398 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08002399
Sungtak Lee08515812019-06-05 11:16:32 -07002400 sp<HGraphicBufferProducer2> igbp = surface ?
2401 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
2402 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002403 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002404 }
2405
Sungtak Leefb579022022-05-10 06:36:15 +00002406 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07002407 std::shared_ptr<SurfaceSyncObj> syncObj;
2408
Sungtak Lee08515812019-06-05 11:16:32 -07002409 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07002410 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002411 } else if (surface->getUniqueId(&bqId) != OK) {
2412 LOG(ERROR) << "setOutputSurface -- "
2413 "cannot obtain bufferqueue id.";
2414 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07002415 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002416 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08002417 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
2418 mHidlBase1_2 ? &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002419 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002420
2421 // set consumer bits
2422 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
2423 // can be set atomically?
2424 uint64_t consumerUsage = kDefaultConsumerUsage;
2425 {
2426 if (surface) {
Sungtak Lee46a69d62023-08-12 07:24:24 +00002427 uint64_t usage = 0;
2428 status_t err = surface->getConsumerUsage(&usage);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002429 if (err != NO_ERROR) {
2430 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
2431 err, asString(err));
2432 } else {
2433 // Note: we are adding the default usage because components must support
2434 // producing output frames that can be displayed an all output surfaces.
2435
2436 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
2437 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
2438 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
2439 // through the sideband channel.
2440
Sungtak Lee46a69d62023-08-12 07:24:24 +00002441 consumerUsage = usage | kDefaultConsumerUsage;
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002442 }
2443 }
2444
2445 C2StreamUsageTuning::output outputUsage{
2446 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
2447 std::vector<std::unique_ptr<C2SettingResult>> failures;
2448 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
2449 if (err != C2_OK) {
2450 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
2451 err, asString(err));
2452 }
2453 }
2454 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
2455 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07002456
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002457 Return<c2_hidl::Status> transStatus = syncObj ?
Wonsik Kime8e98152022-12-16 16:04:17 -08002458 mHidlBase1_2->setOutputSurfaceWithSyncObj(
Sungtak Leea714f112021-03-16 05:40:03 -07002459 static_cast<uint64_t>(blockPoolId),
2460 bqId == 0 ? nullHgbp : igbp, *syncObj) :
Wonsik Kime8e98152022-12-16 16:04:17 -08002461 mHidlBase1_0->setOutputSurface(
Sungtak Leea714f112021-03-16 05:40:03 -07002462 static_cast<uint64_t>(blockPoolId),
2463 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002464
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002465 mOutputBufferQueue->expireOldWaiters();
2466
Pawin Vongmasa36653902018-11-15 00:10:25 -08002467 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002468 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002469 return C2_TRANSACTION_FAILED;
2470 }
2471 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002472 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002473 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002474 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002475 }
Sungtak Leea714f112021-03-16 05:40:03 -07002476 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08002477 return status;
2478}
2479
2480status_t Codec2Client::Component::queueToOutputSurface(
2481 const C2ConstGraphicBlock& block,
2482 const QueueBufferInput& input,
2483 QueueBufferOutput* output) {
Arun Johnson7ba67072023-11-06 22:23:04 +00002484 ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002485 if (mAidlBase) {
2486 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2487 mGraphicBufferAllocators->current();
2488 if (gba) {
2489 return gba->displayBuffer(block, input, output);
2490 } else {
2491 return C2_NOT_FOUND;
2492 }
2493 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002494 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002495}
2496
Brian Lindahlc953b462023-01-27 16:21:43 -07002497void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002498 if (mAidlBase) {
2499 // TODO b/311348680
2500 return;
2501 }
Brian Lindahlc953b462023-01-27 16:21:43 -07002502 mOutputBufferQueue->pollForRenderedFrames(delta);
2503}
2504
Sungtak Leea714f112021-03-16 05:40:03 -07002505void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
2506 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002507 if (mAidlBase) {
2508 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2509 mGraphicBufferAllocators->current();
2510 if (gba) {
2511 gba->updateMaxDequeueBufferCount(maxDequeueCount);
2512 }
2513 return;
2514 }
Sungtak Leea714f112021-03-16 05:40:03 -07002515 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
2516}
2517
Sungtak Leec7da7a02022-05-05 08:45:33 +00002518void Codec2Client::Component::stopUsingOutputSurface(
2519 C2BlockPool::local_id_t blockPoolId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002520 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002521 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2522 mGraphicBufferAllocators->current();
2523 if (gba) {
2524 gba->reset();
2525 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002526 return;
2527 }
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002528 std::scoped_lock lock(mOutputMutex);
2529 mOutputBufferQueue->stop();
Wonsik Kime8e98152022-12-16 16:04:17 -08002530 Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00002531 static_cast<uint64_t>(blockPoolId), nullptr);
2532 if (!transStatus.isOk()) {
2533 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
2534 } else {
2535 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002536 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00002537 if (status != C2_OK) {
2538 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
2539 << status << ".";
2540 }
2541 }
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002542 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00002543}
2544
Sungtak Lee214ce612023-11-01 10:01:13 +00002545void Codec2Client::Component::onBufferReleasedFromOutputSurface(
2546 uint32_t generation) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002547 if (mAidlBase) {
2548 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2549 mGraphicBufferAllocators->current();
2550 if (gba) {
2551 gba->onBufferReleased(generation);
2552 }
2553 return;
2554 }
Sungtak Lee6700cc92023-11-22 18:04:05 +00002555 mOutputBufferQueue->onBufferReleased(generation);
Sungtak Lee214ce612023-11-01 10:01:13 +00002556}
2557
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002558void Codec2Client::Component::holdIgbaBlocks(
2559 const std::list<std::unique_ptr<C2Work>>& workList) {
2560 if (!mAidlBase) {
2561 return;
2562 }
2563 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2564 mGraphicBufferAllocators->current();
2565 if (!gba) {
2566 return;
2567 }
2568 std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
2569 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2570 for (const std::unique_ptr<C2Work>& work : workList) {
2571 if (!work) [[unlikely]] {
2572 continue;
2573 }
2574 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
2575 if (!worklet) {
2576 continue;
2577 }
2578 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
2579 if (buffer) {
2580 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
2581 std::shared_ptr<_C2BlockPoolData> poolData =
2582 _C2BlockFactory::GetGraphicBlockPoolData(block);
2583 _C2BlockFactory::RegisterIgba(poolData, igba);
2584 }
2585 }
2586 }
2587 }
2588 }
2589}
2590
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002591c2_status_t Codec2Client::Component::connectToInputSurface(
2592 const std::shared_ptr<InputSurface>& inputSurface,
2593 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002594 if (mAidlBase) {
2595 // FIXME
2596 return C2_OMITTED;
2597 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002598 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002599 Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002600 inputSurface->mBase,
2601 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002602 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002603 status = static_cast<c2_status_t>(s);
2604 if (status != C2_OK) {
2605 LOG(DEBUG) << "connectToInputSurface -- call failed: "
2606 << status << ".";
2607 return;
2608 }
2609 *connection = std::make_shared<InputSurfaceConnection>(c);
2610 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08002611 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002612 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002613 return C2_TRANSACTION_FAILED;
2614 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002615 return status;
2616}
2617
2618c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002619 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002620 const sp<HGraphicBufferSource>& source,
2621 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002622 if (mAidlBase) {
2623 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
2624 return C2_OMITTED;
2625 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002626 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002627 Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002628 producer, source,
2629 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002630 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002631 status = static_cast<c2_status_t>(s);
2632 if (status != C2_OK) {
2633 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
2634 << status << ".";
2635 return;
2636 }
2637 *connection = std::make_shared<InputSurfaceConnection>(c);
2638 });
2639 if (!transStatus.isOk()) {
2640 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
2641 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002642 }
2643 return status;
2644}
2645
2646c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002647 if (mAidlBase) {
2648 // FIXME
2649 return C2_OMITTED;
2650 }
2651 Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002652 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002653 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002654 return C2_TRANSACTION_FAILED;
2655 }
2656 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002657 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002658 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002659 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
2660 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002661 }
2662 return status;
2663}
2664
Wonsik Kime8e98152022-12-16 16:04:17 -08002665Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
2666 // This object never gets destructed
2667 static AidlDeathManager *sManager = new AidlDeathManager();
2668 return sManager;
2669}
2670
Pawin Vongmasa36653902018-11-15 00:10:25 -08002671c2_status_t Codec2Client::Component::setDeathListener(
2672 const std::shared_ptr<Component>& component,
2673 const std::shared_ptr<Listener>& listener) {
2674
2675 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
2676 std::weak_ptr<Component> component;
2677 std::weak_ptr<Listener> base;
2678
2679 virtual void serviceDied(
2680 uint64_t /* cookie */,
2681 const wp<::android::hidl::base::V1_0::IBase>& /* who */
2682 ) override {
2683 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
2684 listener->onDeath(component);
2685 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002686 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002687 }
2688 }
2689 };
2690
Wonsik Kime8e98152022-12-16 16:04:17 -08002691 if (component->mAidlBase) {
2692 size_t seq;
2693 if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
2694 component->mAidlDeathSeq = seq;
2695 }
2696 return C2_OK;
2697 }
2698
Pawin Vongmasa36653902018-11-15 00:10:25 -08002699 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
2700 deathRecipient->base = listener;
2701 deathRecipient->component = component;
2702
2703 component->mDeathRecipient = deathRecipient;
Wonsik Kime8e98152022-12-16 16:04:17 -08002704 Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002705 component->mDeathRecipient, 0);
2706 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002707 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002708 return C2_TRANSACTION_FAILED;
2709 }
2710 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002711 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002712 return C2_CORRUPTED;
2713 }
2714 return C2_OK;
2715}
2716
2717// Codec2Client::InputSurface
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002718Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002719 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002720 [base]() -> sp<c2_hidl::IConfigurable> {
2721 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002722 base->getConfigurable();
2723 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002724 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002725 nullptr;
2726 }()
2727 },
2728 mBase{base},
2729 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002730 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
2731 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002732 base->getGraphicBufferProducer();
2733 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002734 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002735 nullptr;
2736 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002737}
2738
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002739sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08002740 Codec2Client::InputSurface::getGraphicBufferProducer() const {
2741 return mGraphicBufferProducer;
2742}
2743
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002744sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002745 return mBase;
2746}
2747
2748// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08002749Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002750 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002751 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002752 [base]() -> sp<c2_hidl::IConfigurable> {
2753 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002754 base->getConfigurable();
2755 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002756 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002757 nullptr;
2758 }()
2759 },
2760 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002761}
2762
2763c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002764 Return<c2_hidl::Status> transResult = mBase->disconnect();
2765 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002766}
2767
2768} // namespace android