blob: 9ee9b9ee86a3abeb418044b8c185410cb71c019f [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
Wonsik Kimffc868e2024-11-25 18:18:38 +000023#include <android_media_codec.h>
24
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000025#include <codec2/aidl/GraphicBufferAllocator.h>
Sungtak Lee587aa322024-11-13 08:47:32 +000026#include <codec2/common/HalSelection.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080027#include <codec2/hidl/client.h>
Sungtak Lee587aa322024-11-13 08:47:32 +000028
Pawin Vongmasabf69de92019-10-29 06:21:27 -070029#include <C2Debug.h>
30#include <C2BufferPriv.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080031#include <C2Config.h> // for C2StreamUsageTuning
Pawin Vongmasabf69de92019-10-29 06:21:27 -070032#include <C2PlatformSupport.h>
33
34#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
35#include <android/hardware/media/c2/1.0/IComponent.h>
36#include <android/hardware/media/c2/1.0/IComponentInterface.h>
37#include <android/hardware/media/c2/1.0/IComponentListener.h>
38#include <android/hardware/media/c2/1.0/IComponentStore.h>
39#include <android/hardware/media/c2/1.0/IConfigurable.h>
40#include <android/hidl/manager/1.2/IServiceManager.h>
41
Wonsik Kime8e98152022-12-16 16:04:17 -080042#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
43#include <aidl/android/hardware/media/c2/BnComponentListener.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080044#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
45#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
46#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
47#include <aidl/android/hardware/media/c2/IComponent.h>
48#include <aidl/android/hardware/media/c2/IComponentInterface.h>
49#include <aidl/android/hardware/media/c2/IComponentStore.h>
50#include <aidl/android/hardware/media/c2/IConfigurable.h>
51#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080052#include <aidl/android/hardware/media/c2/StructDescriptor.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080053
Wonsik Kime8e98152022-12-16 16:04:17 -080054#include <aidlcommonsupport/NativeHandle.h>
Wonsik Kim138db0d2023-11-02 16:02:01 -070055#include <android/api-level.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080056#include <android/binder_auto_utils.h>
57#include <android/binder_ibinder.h>
58#include <android/binder_manager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070059#include <android-base/properties.h>
Wonsik Kimffc868e2024-11-25 18:18:38 +000060#include <android-base/scopeguard.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080061#include <android-base/stringprintf.h>
Wonsik Kimffc868e2024-11-25 18:18:38 +000062#include <apex/ApexCodecs.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070063#include <bufferpool/ClientManager.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080064#include <bufferpool2/ClientManager.h>
65#include <codec2/aidl/BufferTypes.h>
Wonsik Kim1caded02022-12-09 13:03:11 -080066#include <codec2/aidl/ParamTypes.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070067#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070068#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080069#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070070#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070071#include <cutils/native_handle.h>
72#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
73#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080074#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070075#include <hidl/HidlSupport.h>
Satish Yalla65af9eb2024-11-25 02:13:51 +000076#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Wonsik Kimffc868e2024-11-25 18:18:38 +000077#include <private/android/AHardwareBufferHelpers.h>
78#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
Pawin Vongmasa36653902018-11-15 00:10:25 -080079
80#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070081#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080082#include <limits>
83#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070084#include <mutex>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000085#include <optional>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070086#include <sstream>
87#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080088#include <type_traits>
89#include <vector>
90
Pawin Vongmasa36653902018-11-15 00:10:25 -080091namespace android {
92
93using ::android::hardware::hidl_vec;
94using ::android::hardware::hidl_string;
95using ::android::hardware::Return;
96using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080097
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080098using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
99 V1_0::IGraphicBufferProducer;
100using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
101 V2_0::IGraphicBufferProducer;
102using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
103 V2_0::utils::B2HGraphicBufferProducer;
104using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
105 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -0700106using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -0800107
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000108using AidlGraphicBufferAllocator = ::aidl::android::hardware::media::c2::
109 implementation::GraphicBufferAllocator;
110
Wonsik Kime8e98152022-12-16 16:04:17 -0800111namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800112namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
113namespace c2_aidl = ::aidl::android::hardware::media::c2;
114namespace c2_hidl_base = ::android::hardware::media::c2;
115namespace c2_hidl = ::android::hardware::media::c2::V1_2;
116
117using c2_hidl::utils::operator<<;
118
Pawin Vongmasa36653902018-11-15 00:10:25 -0800119namespace /* unnamed */ {
120
121// c2_status_t value that corresponds to hwbinder transaction failure.
122constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
123
Lajos Molnar78aa7c92021-02-18 21:39:01 -0800124// By default prepare buffer to be displayed on any of the common surfaces
125constexpr uint64_t kDefaultConsumerUsage =
126 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
127
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700128// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700129// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700130// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700131size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700132 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700133 size_t i = 0;
134 for (; i < names.size(); ++i) {
135 if (name == names[i]) {
136 break;
137 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800138 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700139 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800140}
141
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800142class Client2Store : public C2ComponentStore {
143 std::shared_ptr<Codec2Client> mClient;
144
145public:
146 Client2Store(std::shared_ptr<Codec2Client> const& client)
147 : mClient(client) { }
148
149 virtual ~Client2Store() = default;
150
151 virtual c2_status_t config_sm(
152 std::vector<C2Param*> const &params,
153 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
154 return mClient->config(params, C2_MAY_BLOCK, failures);
155 };
156
157 virtual c2_status_t copyBuffer(
158 std::shared_ptr<C2GraphicBuffer>,
159 std::shared_ptr<C2GraphicBuffer>) {
160 return C2_OMITTED;
161 }
162
163 virtual c2_status_t createComponent(
164 C2String, std::shared_ptr<C2Component>* const component) {
165 component->reset();
166 return C2_OMITTED;
167 }
168
169 virtual c2_status_t createInterface(
170 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
171 interface->reset();
172 return C2_OMITTED;
173 }
174
175 virtual c2_status_t query_sm(
176 std::vector<C2Param*> const& stackParams,
177 std::vector<C2Param::Index> const& heapParamIndices,
178 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
179 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
180 }
181
182 virtual c2_status_t querySupportedParams_nb(
183 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
184 return mClient->querySupportedParams(params);
185 }
186
187 virtual c2_status_t querySupportedValues_sm(
188 std::vector<C2FieldSupportedValuesQuery>& fields) const {
189 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
190 }
191
192 virtual C2String getName() const {
193 return mClient->getName();
194 }
195
196 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
197 return mClient->getParamReflector();
198 }
199
200 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
201 return std::vector<std::shared_ptr<C2Component::Traits const>>();
202 }
203};
204
Wonsik Kime8e98152022-12-16 16:04:17 -0800205c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
206 if (!transStatus.isOk()) {
207 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
208 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
209 LOG(DEBUG) << method << " -- call failed: " << status << ".";
210 return status;
211 } else {
212 LOG(ERROR) << method << " -- transaction failed.";
213 return C2_TRANSACTION_FAILED;
214 }
215 }
216 return C2_OK;
217}
218
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700219} // unnamed namespace
220
221// This class caches a Codec2Client object and its component traits. The client
222// will be created the first time it is needed, and it can be refreshed if the
223// service dies (by calling invalidate()). The first time listComponents() is
224// called from the client, the result will be cached.
225class Codec2Client::Cache {
226 // Cached client
227 std::shared_ptr<Codec2Client> mClient;
228 mutable std::mutex mClientMutex;
229
230 // Cached component traits
231 std::vector<C2Component::Traits> mTraits;
232 std::once_flag mTraitsInitializationFlag;
233
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700234 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700235 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700236 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700237 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700238 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700239 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700240 void init(size_t index) {
241 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700242 }
243
244public:
245 Cache() = default;
246
247 // Initializes mClient if needed, then returns mClient.
248 // If the service is unavailable but listed in the manifest, this function
249 // will block indefinitely.
250 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700251 std::scoped_lock lock{mClientMutex};
252 if (!mClient) {
253 mClient = Codec2Client::_CreateFromIndex(mIndex);
254 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700255 CHECK(mClient) << "Failed to create Codec2Client to service \""
256 << GetServiceNames()[mIndex] << "\". (Index = "
257 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700258 return mClient;
259 }
260
261 // Causes a subsequent call to getClient() to create a new client. This
262 // function should be called after the service dies.
263 //
264 // Note: This function is called only by ForAllServices().
265 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700266 std::scoped_lock lock{mClientMutex};
267 mClient = nullptr;
268 }
269
270 // Returns a list of traits for components supported by the service. This
271 // list is cached.
272 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700273 std::call_once(mTraitsInitializationFlag, [this]() {
274 bool success{false};
275 // Spin until _listComponents() is successful.
276 while (true) {
277 std::shared_ptr<Codec2Client> client = getClient();
278 mTraits = client->_listComponents(&success);
279 if (success) {
280 break;
281 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700282 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700283 using namespace std::chrono_literals;
284 static constexpr auto kServiceRetryPeriod = 5s;
285 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700286 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700287 "Retrying...";
288 std::this_thread::sleep_for(kServiceRetryPeriod);
289 }
290 });
291 return mTraits;
292 }
293
294 // List() returns the list of all caches.
295 static std::vector<Cache>& List() {
296 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700297 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700298 std::vector<Cache> caches(numServices);
299 for (size_t i = 0; i < numServices; ++i) {
300 caches[i].init(i);
301 }
302 return caches;
303 }()};
304 return sCaches;
305 }
306};
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800307// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800308
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800309struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
310 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800312 // base cannot be null.
313 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800315 const C2String& getName() const override {
316 return mName;
317 }
318
319 c2_status_t query(
320 const std::vector<C2Param*>& stackParams,
321 const std::vector<C2Param::Index> &heapParamIndices,
322 c2_blocking_t mayBlock,
323 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
324
325 c2_status_t config(
326 const std::vector<C2Param*> &params,
327 c2_blocking_t mayBlock,
328 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
329
330 c2_status_t querySupportedParams(
331 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
332 ) const override;
333
334 c2_status_t querySupportedValues(
335 std::vector<C2FieldSupportedValuesQuery>& fields,
336 c2_blocking_t mayBlock) const override;
337
338private:
339 sp<Base> mBase;
340 const C2String mName;
341};
342
343Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800344 : mBase{base},
345 mName{[base]() -> C2String {
346 C2String outName;
347 Return<void> transStatus = base->getName(
348 [&outName](const hidl_string& name) {
349 outName = name.c_str();
350 });
351 return transStatus.isOk() ? outName : "";
352 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800353}
354
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800355c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800356 const std::vector<C2Param*> &stackParams,
357 const std::vector<C2Param::Index> &heapParamIndices,
358 c2_blocking_t mayBlock,
359 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800360 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800361 stackParams.size() + heapParamIndices.size());
362 size_t numIndices = 0;
363 for (C2Param* const& stackParam : stackParams) {
364 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800365 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366 continue;
367 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800368 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800369 }
370 size_t numStackIndices = numIndices;
371 for (const C2Param::Index& index : heapParamIndices) {
372 indices[numIndices++] =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800373 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800374 }
375 indices.resize(numIndices);
376 if (heapParams) {
377 heapParams->reserve(heapParams->size() + numIndices);
378 }
379 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800380 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800381 indices,
382 mayBlock == C2_MAY_BLOCK,
383 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800384 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800385 status = static_cast<c2_status_t>(s);
386 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800387 LOG(DEBUG) << "query -- call failed: "
388 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800389 return;
390 }
391 std::vector<C2Param*> paramPointers;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800392 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800393 LOG(ERROR) << "query -- error while parsing params.";
394 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800395 return;
396 }
397 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800398 for (auto it = paramPointers.begin();
399 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800400 C2Param* paramPointer = *it;
401 if (numStackIndices > 0) {
402 --numStackIndices;
403 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800404 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800405 ++it;
406 continue;
407 }
408 for (; i < stackParams.size() && !stackParams[i]; ) {
409 ++i;
410 }
411 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800412 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800413 status = C2_CORRUPTED;
414 return;
415 }
416 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800417 LOG(WARNING) << "query -- param skipped: "
418 "index = "
419 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800420 stackParams[i++]->invalidate();
421 continue;
422 }
423 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800424 LOG(WARNING) << "query -- param update failed: "
425 "index = "
426 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800427 }
428 } else {
429 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800430 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800431 ++it;
432 continue;
433 }
434 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800435 LOG(WARNING) << "query -- "
436 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800437 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800438 heapParams->emplace_back(
439 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800440 }
441 }
442 ++it;
443 }
444 });
445 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800446 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447 return C2_TRANSACTION_FAILED;
448 }
449 return status;
450}
451
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800452c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800453 const std::vector<C2Param*> &params,
454 c2_blocking_t mayBlock,
455 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800456 c2_hidl::Params hidlParams;
457 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800458 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459 return C2_TRANSACTION_FAILED;
460 }
461 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800462 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800463 hidlParams,
464 mayBlock == C2_MAY_BLOCK,
465 [&status, &params, failures](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800466 c2_hidl::Status s,
467 const hidl_vec<c2_hidl::SettingResult> f,
468 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800470 if (status != C2_OK && status != C2_BAD_INDEX) {
471 LOG(DEBUG) << "config -- call failed: "
472 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800473 }
474 size_t i = failures->size();
475 failures->resize(i + f.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800476 for (const c2_hidl::SettingResult& sf : f) {
477 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800478 LOG(ERROR) << "config -- "
479 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800480 return;
481 }
482 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800483 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800484 LOG(ERROR) << "config -- "
485 << "failed to parse returned params.";
486 status = C2_CORRUPTED;
487 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800488 });
489 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800490 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800491 return C2_TRANSACTION_FAILED;
492 }
493 return status;
494}
495
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800496c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
498 // TODO: Cache and query properly!
499 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800500 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800501 std::numeric_limits<uint32_t>::min(),
502 std::numeric_limits<uint32_t>::max(),
503 [&status, params](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800504 c2_hidl::Status s,
505 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 status = static_cast<c2_status_t>(s);
507 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800508 LOG(DEBUG) << "querySupportedParams -- call failed: "
509 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800510 return;
511 }
512 size_t i = params->size();
513 params->resize(i + p.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800514 for (const c2_hidl::ParamDescriptor& sp : p) {
515 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800516 LOG(ERROR) << "querySupportedParams -- "
517 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800518 return;
519 }
520 }
521 });
522 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800523 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800524 return C2_TRANSACTION_FAILED;
525 }
526 return status;
527}
528
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800529c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800530 std::vector<C2FieldSupportedValuesQuery>& fields,
531 c2_blocking_t mayBlock) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800532 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800533 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800534 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800535 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800536 return C2_TRANSACTION_FAILED;
537 }
538 }
539
540 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800541 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800542 inFields,
543 mayBlock == C2_MAY_BLOCK,
544 [&status, &inFields, &fields](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800545 c2_hidl::Status s,
546 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800547 status = static_cast<c2_status_t>(s);
548 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800549 LOG(DEBUG) << "querySupportedValues -- call failed: "
550 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 return;
552 }
553 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800554 LOG(ERROR) << "querySupportedValues -- "
555 "input and output lists "
556 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800557 status = C2_CORRUPTED;
558 return;
559 }
560 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800561 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800562 LOG(ERROR) << "querySupportedValues -- "
563 "invalid returned value.";
564 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800565 return;
566 }
567 }
568 });
569 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800570 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800571 return C2_TRANSACTION_FAILED;
572 }
573 return status;
574}
575
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800576// Codec2ConfigurableClient::AidlImpl
577
578struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
579 typedef c2_aidl::IConfigurable Base;
580
581 // base cannot be null.
582 explicit AidlImpl(const std::shared_ptr<Base>& base);
583
584 const C2String& getName() const override {
585 return mName;
586 }
587
588 c2_status_t query(
589 const std::vector<C2Param*>& stackParams,
590 const std::vector<C2Param::Index> &heapParamIndices,
591 c2_blocking_t mayBlock,
592 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
593
594 c2_status_t config(
595 const std::vector<C2Param*> &params,
596 c2_blocking_t mayBlock,
597 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
598
599 c2_status_t querySupportedParams(
600 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
601 ) const override;
602
603 c2_status_t querySupportedValues(
604 std::vector<C2FieldSupportedValuesQuery>& fields,
605 c2_blocking_t mayBlock) const override;
606
607private:
608 std::shared_ptr<Base> mBase;
609 const C2String mName;
610};
611
612Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
613 : mBase{base},
614 mName{[base]() -> C2String {
615 std::string outName;
616 ndk::ScopedAStatus status = base->getName(&outName);
617 return status.isOk() ? outName : "";
618 }()} {
619}
620
621c2_status_t Codec2ConfigurableClient::AidlImpl::query(
622 const std::vector<C2Param*> &stackParams,
623 const std::vector<C2Param::Index> &heapParamIndices,
624 c2_blocking_t mayBlock,
625 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800626 std::vector<int> indices(
627 stackParams.size() + heapParamIndices.size());
628 size_t numIndices = 0;
629 for (C2Param* const& stackParam : stackParams) {
630 if (!stackParam) {
631 LOG(WARNING) << "query -- null stack param encountered.";
632 continue;
633 }
634 indices[numIndices++] = int(stackParam->index());
635 }
636 size_t numStackIndices = numIndices;
637 for (const C2Param::Index& index : heapParamIndices) {
638 indices[numIndices++] = int(static_cast<uint32_t>(index));
639 }
640 indices.resize(numIndices);
641 if (heapParams) {
642 heapParams->reserve(heapParams->size() + numIndices);
643 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000644 c2_aidl::IConfigurable::QueryResult result;
Wonsik Kim1caded02022-12-09 13:03:11 -0800645 ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800646 c2_status_t status = GetC2Status(transStatus, "query");
647 if (status != C2_OK) {
648 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800649 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000650 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800651
Wonsik Kim1caded02022-12-09 13:03:11 -0800652 std::vector<C2Param*> paramPointers;
Sungtak Lee932255f2024-01-03 10:57:45 +0000653 if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result.params)) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800654 LOG(ERROR) << "query -- error while parsing params.";
655 return C2_CORRUPTED;
656 }
657 size_t i = 0;
Wonsik Kim095e72e2024-02-27 11:33:21 -0800658 size_t numQueried = 0;
Wonsik Kim977176c2023-12-18 17:14:20 -0800659 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800660 C2Param* paramPointer = *it;
661 if (numStackIndices > 0) {
662 --numStackIndices;
663 if (!paramPointer) {
664 LOG(DEBUG) << "query -- null stack param.";
665 ++it;
666 continue;
667 }
668 for (; i < stackParams.size() && !stackParams[i]; ) {
669 ++i;
670 }
671 if (i >= stackParams.size()) {
672 LOG(ERROR) << "query -- unexpected error.";
673 status = C2_CORRUPTED;
674 break;
675 }
676 if (stackParams[i]->index() != paramPointer->index()) {
677 LOG(DEBUG) << "query -- param skipped: "
678 "index = "
679 << stackParams[i]->index() << ".";
680 stackParams[i++]->invalidate();
681 // this means that the param could not be queried.
682 // signalling C2_BAD_INDEX to the client.
683 status = C2_BAD_INDEX;
684 continue;
685 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800686 if (stackParams[i++]->updateFrom(*paramPointer)) {
Wonsik Kim095e72e2024-02-27 11:33:21 -0800687 ++numQueried;
Wonsik Kim977176c2023-12-18 17:14:20 -0800688 } else {
Wonsik Kim1caded02022-12-09 13:03:11 -0800689 LOG(WARNING) << "query -- param update failed: "
690 "index = "
691 << paramPointer->index() << ".";
692 }
693 } else {
694 if (!paramPointer) {
695 LOG(DEBUG) << "query -- null heap param.";
696 ++it;
697 continue;
698 }
699 if (!heapParams) {
700 LOG(WARNING) << "query -- "
701 "unexpected extra stack param.";
702 } else {
703 heapParams->emplace_back(C2Param::Copy(*paramPointer));
Wonsik Kim095e72e2024-02-27 11:33:21 -0800704 ++numQueried;
Wonsik Kim1caded02022-12-09 13:03:11 -0800705 }
706 }
707 ++it;
708 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800709 if (status == C2_OK && indices.size() != numQueried) {
710 status = C2_BAD_INDEX;
711 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800712 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800713}
714
715c2_status_t Codec2ConfigurableClient::AidlImpl::config(
716 const std::vector<C2Param*> &params,
717 c2_blocking_t mayBlock,
718 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800719 c2_aidl::Params aidlParams;
720 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
721 LOG(ERROR) << "config -- bad input.";
722 return C2_TRANSACTION_FAILED;
723 }
724 c2_aidl::IConfigurable::ConfigResult result;
725 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800726 c2_status_t status = GetC2Status(transStatus, "config");
727 if (status != C2_OK) {
728 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800729 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000730 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800731 size_t i = failures->size();
732 failures->resize(i + result.failures.size());
733 for (const c2_aidl::SettingResult& sf : result.failures) {
734 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
735 LOG(ERROR) << "config -- invalid SettingResult returned.";
736 return C2_CORRUPTED;
737 }
738 }
739 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
740 LOG(ERROR) << "config -- "
741 << "failed to parse returned params.";
742 status = C2_CORRUPTED;
743 }
744 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800745}
746
747c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
748 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800749 // TODO: Cache and query properly!
750 std::vector<c2_aidl::ParamDescriptor> result;
751 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
752 std::numeric_limits<uint32_t>::min(),
753 std::numeric_limits<uint32_t>::max(),
754 &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800755 c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
756 if (status != C2_OK) {
757 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800758 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800759 size_t i = params->size();
760 params->resize(i + result.size());
761 for (const c2_aidl::ParamDescriptor& sp : result) {
762 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
763 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
764 return C2_CORRUPTED;
765 }
766 }
767 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800768}
769
770c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
771 std::vector<C2FieldSupportedValuesQuery>& fields,
772 c2_blocking_t mayBlock) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800773 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
774 for (size_t i = 0; i < fields.size(); ++i) {
775 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
776 LOG(ERROR) << "querySupportedValues -- bad input";
777 return C2_TRANSACTION_FAILED;
778 }
779 }
780
Sungtak Lee932255f2024-01-03 10:57:45 +0000781 c2_aidl::IConfigurable::QuerySupportedValuesResult result;
782
Wonsik Kim1caded02022-12-09 13:03:11 -0800783 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
784 inFields, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800785 c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
786 if (status != C2_OK) {
787 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800788 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000789 status = static_cast<c2_status_t>(result.status.status);
790 if (result.values.size() != fields.size()) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800791 LOG(ERROR) << "querySupportedValues -- "
792 "input and output lists "
793 "have different sizes.";
794 return C2_CORRUPTED;
795 }
796 for (size_t i = 0; i < fields.size(); ++i) {
Sungtak Lee932255f2024-01-03 10:57:45 +0000797 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result.values[i])) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800798 LOG(ERROR) << "querySupportedValues -- "
799 "invalid returned value.";
800 return C2_CORRUPTED;
801 }
802 }
803 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800804}
805
Wonsik Kimffc868e2024-11-25 18:18:38 +0000806// Codec2ConfigurableClient::ApexImpl
807
808struct Codec2ConfigurableClient::ApexImpl : public Codec2ConfigurableClient::ImplBase {
809 ApexImpl(ApexCodec_Configurable *base, const C2String &name);
810
811 const C2String& getName() const override {
812 return mName;
813 }
814
815 c2_status_t query(
816 const std::vector<C2Param*>& stackParams,
817 const std::vector<C2Param::Index> &heapParamIndices,
818 c2_blocking_t mayBlock,
819 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
820
821 c2_status_t config(
822 const std::vector<C2Param*> &params,
823 c2_blocking_t mayBlock,
824 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
825
826 c2_status_t querySupportedParams(
827 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
828 ) const override;
829
830 c2_status_t querySupportedValues(
831 std::vector<C2FieldSupportedValuesQuery>& fields,
832 c2_blocking_t mayBlock) const override;
833
834private:
835 ApexCodec_Configurable* mBase;
836 const C2String mName;
837};
838
839Codec2ConfigurableClient::ApexImpl::ApexImpl(ApexCodec_Configurable *base, const C2String &name)
840 : mBase{base},
841 mName{name} {
842}
843
844c2_status_t Codec2ConfigurableClient::ApexImpl::query(
845 const std::vector<C2Param*> &stackParams,
846 const std::vector<C2Param::Index> &heapParamIndices,
847 [[maybe_unused]] c2_blocking_t mayBlock,
848 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
849 if (mBase == nullptr) {
850 return C2_OMITTED;
851 }
852
853 if (__builtin_available(android 36, *)) {
854 std::vector<uint32_t> indices(
855 stackParams.size() + heapParamIndices.size());
856 size_t numIndices = 0;
857 for (C2Param* const& stackParam : stackParams) {
858 if (!stackParam) {
859 LOG(WARNING) << "query -- null stack param encountered.";
860 continue;
861 }
862 indices[numIndices++] = uint32_t(stackParam->index());
863 }
864 size_t numStackIndices = numIndices;
865 for (const C2Param::Index& index : heapParamIndices) {
866 indices[numIndices++] = uint32_t(index);
867 }
868 indices.resize(numIndices);
869 if (heapParams) {
870 heapParams->reserve(heapParams->size() + numIndices);
871 }
872 if (numIndices == 0) {
873 return C2_OK;
874 }
875 thread_local std::vector<uint8_t> configBuffer(1024);
876 if (configBuffer.capacity() < numIndices * 16u) {
877 configBuffer.resize(numIndices * 16u);
878 }
879 ApexCodec_LinearBuffer config{configBuffer.data(), configBuffer.capacity()};
880 size_t writtenOrRequested = 0;
881 ApexCodec_Status status = ApexCodec_Configurable_query(
882 mBase, indices.data(), indices.size(), &config, &writtenOrRequested);
883 if (status == APEXCODEC_STATUS_NO_MEMORY) {
884 size_t requested = writtenOrRequested;
885 configBuffer.resize(align(requested, 1024));
886 config.data = configBuffer.data();
887 config.size = configBuffer.capacity();
888 status = ApexCodec_Configurable_query(
889 mBase, indices.data(), indices.size(), &config, &writtenOrRequested);
890 }
891 size_t written = writtenOrRequested;
892 if (status != APEXCODEC_STATUS_OK && status != APEXCODEC_STATUS_BAD_INDEX) {
893 written = 0;
894 }
895 configBuffer.resize(written);
896 std::vector<C2Param*> paramPointers;
897 if (!::android::parseParamsBlob(&paramPointers, configBuffer)) {
898 LOG(ERROR) << "query -- error while parsing params.";
899 return C2_CORRUPTED;
900 }
901 size_t i = 0;
902 size_t numQueried = 0;
903 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
904 C2Param* paramPointer = *it;
905 if (numStackIndices > 0) {
906 --numStackIndices;
907 if (!paramPointer) {
908 LOG(DEBUG) << "query -- null stack param.";
909 ++it;
910 continue;
911 }
912 for (; i < stackParams.size() && !stackParams[i]; ) {
913 ++i;
914 }
915 if (i >= stackParams.size()) {
916 LOG(ERROR) << "query -- unexpected error.";
917 status = APEXCODEC_STATUS_CORRUPTED;
918 break;
919 }
920 if (stackParams[i]->index() != paramPointer->index()) {
921 LOG(DEBUG) << "query -- param skipped: "
922 "index = "
923 << stackParams[i]->index() << ".";
924 stackParams[i++]->invalidate();
925 // this means that the param could not be queried.
926 // signalling C2_BAD_INDEX to the client.
927 status = APEXCODEC_STATUS_BAD_INDEX;
928 continue;
929 }
930 if (stackParams[i++]->updateFrom(*paramPointer)) {
931 ++numQueried;
932 } else {
933 LOG(WARNING) << "query -- param update failed: "
934 "index = "
935 << paramPointer->index() << ".";
936 }
937 } else {
938 if (!paramPointer) {
939 LOG(DEBUG) << "query -- null heap param.";
940 ++it;
941 continue;
942 }
943 if (!heapParams) {
944 LOG(WARNING) << "query -- "
945 "unexpected extra stack param.";
946 } else {
947 heapParams->emplace_back(C2Param::Copy(*paramPointer));
948 ++numQueried;
949 }
950 }
951 ++it;
952 }
953 if (status == APEXCODEC_STATUS_OK && indices.size() != numQueried) {
954 status = APEXCODEC_STATUS_BAD_INDEX;
955 }
956 return (c2_status_t)status;
957 } else {
958 return C2_OMITTED;
959 }
960}
961
962namespace {
963struct ParamOrField : public C2ParamField {
964 explicit ParamOrField(const ApexCodec_ParamFieldValues& field)
965 : C2ParamField(field.index, field.offset, field.size) {}
966};
967
968static bool FromApex(
969 ApexCodec_SupportedValues *apexValues,
970 C2FieldSupportedValues* c2Values) {
971 if (__builtin_available(android 36, *)) {
972 if (apexValues == nullptr) {
973 c2Values->type = C2FieldSupportedValues::EMPTY;
974 return true;
975 }
976 ApexCodec_SupportedValuesType type = APEXCODEC_SUPPORTED_VALUES_EMPTY;
977 ApexCodec_SupportedValuesNumberType numberType = APEXCODEC_SUPPORTED_VALUES_TYPE_NONE;
978 ApexCodec_Value* values = nullptr;
979 uint32_t numValues = 0;
980 ApexCodec_SupportedValues_getTypeAndValues(
981 apexValues, &type, &numberType, &values, &numValues);
982 c2Values->type = (C2FieldSupportedValues::type_t)type;
983 std::function<C2Value::Primitive(const ApexCodec_Value &)> getPrimitive;
984 switch (numberType) {
985 case APEXCODEC_SUPPORTED_VALUES_TYPE_NONE:
986 getPrimitive = [](const ApexCodec_Value &) -> C2Value::Primitive {
987 return C2Value::Primitive();
988 };
989 break;
990 case APEXCODEC_SUPPORTED_VALUES_TYPE_INT32:
991 getPrimitive = [](const ApexCodec_Value &value) -> C2Value::Primitive {
992 return C2Value::Primitive(value.i32);
993 };
994 break;
995 case APEXCODEC_SUPPORTED_VALUES_TYPE_UINT32:
996 getPrimitive = [](const ApexCodec_Value &value) -> C2Value::Primitive {
997 return C2Value::Primitive(value.u32);
998 };
999 break;
1000 case APEXCODEC_SUPPORTED_VALUES_TYPE_INT64:
1001 getPrimitive = [](const ApexCodec_Value &value) -> C2Value::Primitive {
1002 return C2Value::Primitive(value.i64);
1003 };
1004 break;
1005 case APEXCODEC_SUPPORTED_VALUES_TYPE_UINT64:
1006 getPrimitive = [](const ApexCodec_Value &value) -> C2Value::Primitive {
1007 return C2Value::Primitive(value.u64);
1008 };
1009 break;
1010 case APEXCODEC_SUPPORTED_VALUES_TYPE_FLOAT:
1011 getPrimitive = [](const ApexCodec_Value &value) -> C2Value::Primitive {
1012 return C2Value::Primitive(value.f);
1013 };
1014 break;
1015 default:
1016 LOG(ERROR) << "Unsupported number type: " << numberType;
1017 return false;
1018 }
1019 switch (type) {
1020 case APEXCODEC_SUPPORTED_VALUES_EMPTY:
1021 break;
1022 case APEXCODEC_SUPPORTED_VALUES_RANGE:
1023 c2Values->range.min = getPrimitive(values[0]);
1024 c2Values->range.max = getPrimitive(values[1]);
1025 c2Values->range.step = getPrimitive(values[2]);
1026 c2Values->range.num = getPrimitive(values[3]);
1027 c2Values->range.denom = getPrimitive(values[4]);
1028 break;
1029 case APEXCODEC_SUPPORTED_VALUES_VALUES:
1030 case APEXCODEC_SUPPORTED_VALUES_FLAGS:
1031 c2Values->values.clear();
1032 for (uint32_t i = 0; i < numValues; ++i) {
1033 c2Values->values.push_back(getPrimitive(values[i]));
1034 }
1035 break;
1036 default:
1037 LOG(ERROR) << "Unsupported supported values type: " << type;
1038 return false;
1039 }
1040 return true;
1041 } else {
1042 return false;
1043 }
1044}
1045
1046} // anonymous namespace
1047
1048c2_status_t Codec2ConfigurableClient::ApexImpl::config(
1049 const std::vector<C2Param*> &params,
1050 c2_blocking_t mayBlock,
1051 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
1052 (void)mayBlock;
1053 if (mBase == nullptr) {
1054 return C2_OMITTED;
1055 }
1056
1057 if (__builtin_available(android 36, *)) {
1058 std::vector<uint8_t> configBuffer;
1059 if (!::android::_createParamsBlob(&configBuffer, params)) {
1060 LOG(ERROR) << "config -- bad input.";
1061 return C2_TRANSACTION_FAILED;
1062 }
1063 ApexCodec_SettingResults* result = nullptr;
1064 ApexCodec_LinearBuffer config{configBuffer.data(), configBuffer.size()};
1065 ApexCodec_Status status = ApexCodec_Configurable_config(
1066 mBase, &config, &result);
1067 base::ScopeGuard guard([result] {
1068 if (result) {
1069 ApexCodec_SettingResults_release(result);
1070 }
1071 });
1072 size_t index = 0;
1073 ApexCodec_SettingResultFailure failure;
1074 ApexCodec_ParamFieldValues field;
1075 ApexCodec_ParamFieldValues* conflicts = nullptr;
1076 size_t numConflicts = 0;
1077 ApexCodec_Status getResultStatus = ApexCodec_SettingResults_getResultAtIndex(
1078 result, 0, &failure, &field, &conflicts, &numConflicts);
1079 while (getResultStatus == APEXCODEC_STATUS_OK) {
1080 std::unique_ptr<C2SettingResult> settingResult;
1081 settingResult.reset(new C2SettingResult{
1082 C2SettingResult::Failure(failure), C2ParamFieldValues(ParamOrField(field)), {}
1083 });
1084 // TODO: settingResult->field.values = ?
1085 for (size_t i = 0; i < numConflicts; ++i) {
1086 settingResult->conflicts.emplace_back(ParamOrField(conflicts[i]));
1087 C2ParamFieldValues& conflict = settingResult->conflicts.back();
1088 conflict.values = std::make_unique<C2FieldSupportedValues>();
1089 FromApex(conflicts[i].values, conflict.values.get());
1090 }
1091 failures->push_back(std::move(settingResult));
1092 getResultStatus = ApexCodec_SettingResults_getResultAtIndex(
1093 result, ++index, &failure, &field, &conflicts, &numConflicts);
1094 }
1095 if (!::android::updateParamsFromBlob(params, configBuffer)) {
1096 LOG(ERROR) << "config -- "
1097 << "failed to parse returned params.";
1098 status = APEXCODEC_STATUS_CORRUPTED;
1099 }
1100 return (c2_status_t)status;
1101 } else {
1102 return C2_OMITTED;
1103 }
1104}
1105
1106c2_status_t Codec2ConfigurableClient::ApexImpl::querySupportedParams(
1107 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
1108 if (mBase == nullptr) {
1109 return C2_OMITTED;
1110 }
1111
1112 if (__builtin_available(android 36, *)) {
1113 // TODO: Cache and query properly!
1114 ApexCodec_ParamDescriptors* paramDescs = nullptr;
1115 ApexCodec_Configurable_querySupportedParams(mBase, &paramDescs);
1116 base::ScopeGuard guard([paramDescs] {
1117 if (paramDescs) {
1118 ApexCodec_ParamDescriptors_release(paramDescs);
1119 }
1120 });
1121 uint32_t *indices = nullptr;
1122 size_t numIndices = 0;
1123 ApexCodec_Status status = ApexCodec_ParamDescriptors_getIndices(
1124 paramDescs, &indices, &numIndices);
1125 if (status != APEXCODEC_STATUS_OK) {
1126 return (c2_status_t)status;
1127 }
1128 if (numIndices > 0) {
1129 for (int i = 0; i < numIndices; ++i) {
1130 uint32_t index = indices[i];
1131 ApexCodec_ParamAttribute attr = (ApexCodec_ParamAttribute)0;
1132 const char* name = nullptr;
1133 uint32_t* dependencies = nullptr;
1134 size_t numDependencies = 0;
1135 ApexCodec_Status status = ApexCodec_ParamDescriptors_getDescriptor(
1136 paramDescs, index, &attr, &name, &dependencies, &numDependencies);
1137 if (status != APEXCODEC_STATUS_OK) {
1138 LOG(WARNING) << "querySupportedParams -- "
1139 << "failed to get descriptor for index "
1140 << std::hex << index << std::dec << " with status " << status;
1141 continue;
1142 }
1143 params->push_back(std::make_shared<C2ParamDescriptor>(
1144 C2Param::Index(index), C2ParamDescriptor::attrib_t(attr), name,
1145 std::vector<C2Param::Index>(dependencies, dependencies + numDependencies)));
1146 }
1147 }
1148 return (c2_status_t)status;
1149 } else {
1150 return C2_OMITTED;
1151 }
1152}
1153
1154c2_status_t Codec2ConfigurableClient::ApexImpl::querySupportedValues(
1155 std::vector<C2FieldSupportedValuesQuery>& fields,
1156 [[maybe_unused]] c2_blocking_t mayBlock) const {
1157 if (mBase == nullptr) {
1158 return C2_OMITTED;
1159 }
1160
1161 if (__builtin_available(android 36, *)) {
1162 std::vector<ApexCodec_SupportedValuesQuery> queries(fields.size());
1163 for (size_t i = 0; i < fields.size(); ++i) {
1164 queries[i].index = _C2ParamInspector::GetIndex(fields[i].field());
1165 queries[i].offset = _C2ParamInspector::GetOffset(fields[i].field());
1166 queries[i].type = (ApexCodec_SupportedValuesQueryType)fields[i].type();
1167 queries[i].status = APEXCODEC_STATUS_OK;
1168 queries[i].values = nullptr;
1169 }
1170 ApexCodec_Status status = ApexCodec_Configurable_querySupportedValues(
1171 mBase, queries.data(), queries.size());
1172 for (size_t i = 0; i < fields.size(); ++i) {
1173 fields[i].status = (c2_status_t)queries[i].status;
1174 FromApex(queries[i].values, &fields[i].values);
1175 if (queries[i].values) {
1176 ApexCodec_SupportedValues_release(queries[i].values);
1177 queries[i].values = nullptr;
1178 }
1179 }
1180 return (c2_status_t)status;
1181 } else {
1182 return C2_OMITTED;
1183 }
1184}
1185
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001186// Codec2ConfigurableClient
1187
1188Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
1189 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
1190}
1191
1192Codec2ConfigurableClient::Codec2ConfigurableClient(
1193 const std::shared_ptr<AidlBase> &aidlBase)
1194 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
1195}
1196
Wonsik Kimffc868e2024-11-25 18:18:38 +00001197Codec2ConfigurableClient::Codec2ConfigurableClient(
1198 ApexCodec_Configurable *apexBase, const C2String &name)
1199 : mImpl(new Codec2ConfigurableClient::ApexImpl(apexBase, name)) {
1200}
1201
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001202const C2String& Codec2ConfigurableClient::getName() const {
1203 return mImpl->getName();
1204}
1205
1206c2_status_t Codec2ConfigurableClient::query(
1207 const std::vector<C2Param*>& stackParams,
1208 const std::vector<C2Param::Index> &heapParamIndices,
1209 c2_blocking_t mayBlock,
1210 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
1211 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
1212}
1213
1214c2_status_t Codec2ConfigurableClient::config(
1215 const std::vector<C2Param*> &params,
1216 c2_blocking_t mayBlock,
1217 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
1218 return mImpl->config(params, mayBlock, failures);
1219}
1220
1221c2_status_t Codec2ConfigurableClient::querySupportedParams(
1222 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
1223 return mImpl->querySupportedParams(params);
1224}
1225
1226c2_status_t Codec2ConfigurableClient::querySupportedValues(
1227 std::vector<C2FieldSupportedValuesQuery>& fields,
1228 c2_blocking_t mayBlock) const {
1229 return mImpl->querySupportedValues(fields, mayBlock);
1230}
1231
1232
Pawin Vongmasa36653902018-11-15 00:10:25 -08001233// Codec2Client::Component::HidlListener
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001234struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001235 std::weak_ptr<Component> component;
1236 std::weak_ptr<Listener> base;
1237
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001238 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001239 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001240 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001241 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001242 return Void();
1243 }
1244 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001245 std::shared_ptr<Codec2Client::Component> strongComponent =
1246 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001247 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -08001248 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001249 }
1250 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -08001251 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001252 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001253 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001254 }
1255 return Void();
1256 }
1257
1258 virtual Return<void> onTripped(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001259 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001260 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
1261 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001262 for (size_t i = 0; i < settingResults.size(); ++i) {
1263 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001264 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001265 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001266 return Void();
1267 }
1268 c2SettingResults[i] = std::move(c2SettingResult);
1269 }
1270 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1271 listener->onTripped(component, c2SettingResults);
1272 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001273 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001274 }
1275 return Void();
1276 }
1277
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001278 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001279 LOG(DEBUG) << "onError --"
1280 << " status = " << s
1281 << ", errorCode = " << errorCode
1282 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001283 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001284 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -08001285 errorCode : static_cast<c2_status_t>(s));
1286 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001287 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001288 }
1289 return Void();
1290 }
1291
1292 virtual Return<void> onFramesRendered(
1293 const hidl_vec<RenderedFrame>& renderedFrames) override {
1294 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001295 if (!listener) {
1296 LOG(DEBUG) << "onFramesRendered -- listener died.";
1297 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001299 for (const RenderedFrame& renderedFrame : renderedFrames) {
1300 listener->onFrameRendered(
1301 renderedFrame.bufferQueueId,
1302 renderedFrame.slotId,
1303 renderedFrame.timestampNs);
1304 }
1305 return Void();
1306 }
1307
1308 virtual Return<void> onInputBuffersReleased(
1309 const hidl_vec<InputBuffer>& inputBuffers) override {
1310 std::shared_ptr<Listener> listener = base.lock();
1311 if (!listener) {
1312 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1313 return Void();
1314 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001315 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001316 LOG(VERBOSE) << "onInputBuffersReleased --"
1317 " received death notification of"
1318 " input buffer:"
1319 " frameIndex = " << inputBuffer.frameIndex
1320 << ", bufferIndex = " << inputBuffer.arrayIndex
1321 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -08001322 listener->onInputBufferDone(
1323 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001324 }
1325 return Void();
1326 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001327
Pawin Vongmasa36653902018-11-15 00:10:25 -08001328};
1329
Wonsik Kime8e98152022-12-16 16:04:17 -08001330// Codec2Client::Component::AidlListener
1331struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
1332 std::weak_ptr<Component> component;
1333 std::weak_ptr<Listener> base;
1334
1335 virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
1336 std::list<std::unique_ptr<C2Work>> workItems;
1337 if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
1338 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
1339 return ::ndk::ScopedAStatus::ok();
1340 }
1341 // release input buffers potentially held by the component from queue
1342 std::shared_ptr<Codec2Client::Component> strongComponent =
1343 component.lock();
1344 if (strongComponent) {
1345 strongComponent->handleOnWorkDone(workItems);
1346 }
1347 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1348 listener->onWorkDone(component, workItems);
1349 } else {
1350 LOG(DEBUG) << "onWorkDone -- listener died.";
1351 }
1352 return ::ndk::ScopedAStatus::ok();
1353 }
1354
1355 virtual ::ndk::ScopedAStatus onTripped(
1356 const std::vector<c2_aidl::SettingResult>& settingResults) override {
1357 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
1358 settingResults.size());
1359 for (size_t i = 0; i < settingResults.size(); ++i) {
1360 std::unique_ptr<C2SettingResult> c2SettingResult;
1361 if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
1362 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
1363 return ::ndk::ScopedAStatus::ok();
1364 }
1365 c2SettingResults[i] = std::move(c2SettingResult);
1366 }
1367 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
1368 listener->onTripped(component, c2SettingResults);
1369 } else {
1370 LOG(DEBUG) << "onTripped -- listener died.";
1371 }
1372 return ::ndk::ScopedAStatus::ok();
1373 }
1374
1375 virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
1376 LOG(DEBUG) << "onError --"
1377 << " status = " << s.status
1378 << ", errorCode = " << errorCode
1379 << ".";
1380 if (std::shared_ptr<Listener> listener = base.lock()) {
1381 listener->onError(component, s.status == c2_aidl::Status::OK ?
1382 errorCode : static_cast<c2_status_t>(s.status));
1383 } else {
1384 LOG(DEBUG) << "onError -- listener died.";
1385 }
1386 return ::ndk::ScopedAStatus::ok();
1387 }
1388
1389 virtual ::ndk::ScopedAStatus onFramesRendered(
1390 const std::vector<RenderedFrame>& renderedFrames) override {
1391 std::shared_ptr<Listener> listener = base.lock();
1392 if (!listener) {
1393 LOG(DEBUG) << "onFramesRendered -- listener died.";
1394 return ::ndk::ScopedAStatus::ok();
1395 }
1396 for (const RenderedFrame& renderedFrame : renderedFrames) {
1397 listener->onFrameRendered(
1398 renderedFrame.bufferQueueId,
1399 renderedFrame.slotId,
1400 renderedFrame.timestampNs);
1401 }
1402 return ::ndk::ScopedAStatus::ok();
1403 }
1404
1405 virtual ::ndk::ScopedAStatus onInputBuffersReleased(
1406 const std::vector<InputBuffer>& inputBuffers) override {
1407 std::shared_ptr<Listener> listener = base.lock();
1408 if (!listener) {
1409 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1410 return ::ndk::ScopedAStatus::ok();
1411 }
1412 for (const InputBuffer& inputBuffer : inputBuffers) {
1413 LOG(VERBOSE) << "onInputBuffersReleased --"
1414 " received death notification of"
1415 " input buffer:"
1416 " frameIndex = " << inputBuffer.frameIndex
1417 << ", bufferIndex = " << inputBuffer.arrayIndex
1418 << ".";
1419 listener->onInputBufferDone(
1420 inputBuffer.frameIndex, inputBuffer.arrayIndex);
1421 }
1422 return ::ndk::ScopedAStatus::ok();
1423 }
1424
1425};
1426
Wonsik Kimffc868e2024-11-25 18:18:38 +00001427// Codec2Client::Component::ApexHandler
1428class Codec2Client::Component::ApexHandler {
1429public:
1430 ApexHandler(ApexCodec_Component *apexComponent,
1431 const std::shared_ptr<Listener> &listener,
1432 const std::shared_ptr<Component> &comp)
1433 : mApexComponent(apexComponent),
1434 mListener(listener),
1435 mComponent(comp),
1436 mStopped(false),
1437 mOutputBufferType(APEXCODEC_BUFFER_TYPE_INVALID) {
1438 }
1439
1440 void start() {
1441 std::shared_ptr<Component> comp = mComponent.lock();
1442 if (!comp) {
1443 LOG(ERROR) << "ApexHandler::start -- component died.";
1444 return;
1445 }
1446 C2ComponentDomainSetting domain;
1447 C2ComponentKindSetting kind;
1448 c2_status_t status = comp->query({&domain, &kind}, {}, C2_MAY_BLOCK, {});
1449 if (status != C2_OK) {
1450 LOG(ERROR) << "ApexHandler::start -- failed to query component domain and kind";
1451 return;
1452 }
1453 if (kind.value != C2Component::KIND_DECODER
1454 && kind.value != C2Component::KIND_ENCODER) {
1455 LOG(ERROR) << "ApexHandler::start -- unrecognized component kind " << kind.value;
1456 return;
1457 }
1458 ApexCodec_BufferType outputBufferType = APEXCODEC_BUFFER_TYPE_INVALID;
1459 if (domain.value == C2Component::DOMAIN_AUDIO) {
1460 // For both encoders and decoders the output buffer type is linear.
1461 outputBufferType = APEXCODEC_BUFFER_TYPE_LINEAR;
1462 } else if (domain.value == C2Component::DOMAIN_VIDEO
1463 || domain.value == C2Component::DOMAIN_IMAGE) {
1464 // For video / image domain the decoder outputs a graphic buffer, and the encoder
1465 // outputs a linear buffer.
1466 outputBufferType = (kind.value == C2Component::KIND_DECODER)
1467 ? APEXCODEC_BUFFER_TYPE_GRAPHIC : APEXCODEC_BUFFER_TYPE_LINEAR;
1468 } else {
1469 LOG(ERROR) << "ApexHandler::start -- unrecognized component domain " << domain.value;
1470 return;
1471 }
1472 {
1473 std::unique_lock<std::mutex> l(mMutex);
1474 mStopped = false;
1475 mOutputBufferType = outputBufferType;
1476 }
1477 mThread = std::thread([this]() {
1478 run();
1479 });
1480 }
1481
1482 void queue(std::list<std::unique_ptr<C2Work>>& workItems) {
1483 std::unique_lock<std::mutex> l(mMutex);
1484 mWorkQueue.splice(mWorkQueue.end(), workItems);
1485 mCondition.notify_all();
1486 }
1487
1488 void stop() {
1489 std::unique_lock<std::mutex> l(mMutex);
1490 mStopped = true;
1491 mCondition.notify_all();
1492 l.unlock();
1493 mThread.join();
1494 }
1495
1496private:
1497 void run() {
1498 while (true) {
1499 std::unique_lock<std::mutex> l(mMutex);
1500 mCondition.wait(l, [this]() {
1501 return !mWorkQueue.empty() || mStopped;
1502 });
1503 if (mStopped) {
1504 break;
1505 }
1506 if (mWorkQueue.empty()) {
1507 continue;
1508 }
1509 std::list<std::unique_ptr<C2Work>> workItems;
1510 mWorkQueue.swap(workItems);
1511 for (std::unique_ptr<C2Work>& workItem : workItems) {
1512 if (mStopped) {
1513 break;
1514 }
1515 l.unlock();
1516 handleWork(std::move(workItem));
1517 l.lock();
1518 }
1519 }
1520 mWorkQueue.clear();
1521 mWorkMap.clear();
1522 }
1523
1524 void handleWork(std::unique_ptr<C2Work> &&workItem) {
1525 if (__builtin_available(android 36, *)) {
1526 std::shared_ptr<Listener> listener = mListener.lock();
1527 if (!listener) {
1528 LOG(DEBUG) << "handleWork -- listener died.";
1529 return;
1530 }
1531 ApexCodec_Buffer input;
1532 input.flags = (ApexCodec_BufferFlags)workItem->input.flags;
1533 input.frameIndex = workItem->input.ordinal.frameIndex.peekll();
1534 input.timestampUs = workItem->input.ordinal.timestamp.peekll();
1535
1536 if (workItem->input.buffers.size() > 1) {
1537 LOG(ERROR) << "handleWork -- input buffer size is "
1538 << workItem->input.buffers.size();
1539 return;
1540 }
1541 std::shared_ptr<C2Buffer> buffer;
1542 std::optional<C2ReadView> linearView;
1543 if (!workItem->input.buffers.empty()) {
1544 buffer = workItem->input.buffers[0];
1545 }
1546 if (!FillMemory(buffer, &input, &linearView)) {
1547 LOG(ERROR) << "handleWork -- failed to map input";
1548 return;
1549 }
1550
1551 std::vector<uint8_t> configUpdatesVector;
1552 if (!_createParamsBlob(&configUpdatesVector, workItem->input.configUpdate)) {
1553 listener->onError(mComponent, C2_CORRUPTED);
1554 return;
1555 }
1556 input.configUpdates.data = configUpdatesVector.data();
1557 input.configUpdates.size = configUpdatesVector.size();
1558 mWorkMap.insert_or_assign(
1559 workItem->input.ordinal.frameIndex.peekll(), std::move(workItem));
1560
1561 std::list<std::unique_ptr<C2Work>> workItems;
1562 bool inputDrained = false;
1563 while (!inputDrained) {
1564 ApexCodec_Buffer output;
1565 std::shared_ptr<C2LinearBlock> linearBlock;
1566 std::optional<C2WriteView> linearView;
1567 std::shared_ptr<C2GraphicBlock> graphicBlock;
1568 allocOutputBuffer(&output, &linearBlock, &linearView, &graphicBlock);
1569 size_t consumed = 0;
1570 size_t produced = 0;
1571 ApexCodec_Status status = ApexCodec_Component_process(
1572 mApexComponent, &input, &output, &consumed, &produced);
1573 if (status == APEXCODEC_STATUS_NO_MEMORY) {
1574 continue;
1575 }
1576 if (produced > 0) {
1577 auto it = mWorkMap.find(output.frameIndex);
1578 std::unique_ptr<C2Work> outputWorkItem;
1579 if (it != mWorkMap.end()) {
1580 if (output.flags & APEXCODEC_FLAG_INCOMPLETE) {
1581 outputWorkItem = std::make_unique<C2Work>();
1582 outputWorkItem->input.ordinal = it->second->input.ordinal;
1583 outputWorkItem->input.flags = it->second->input.flags;
1584 } else {
1585 outputWorkItem = std::move(it->second);
1586 mWorkMap.erase(it);
1587 }
1588 } else {
1589 LOG(WARNING) << "handleWork -- no work item found for output frame index "
1590 << output.frameIndex;
1591 outputWorkItem = std::make_unique<C2Work>();
1592 outputWorkItem->input.ordinal.frameIndex = output.frameIndex;
1593 outputWorkItem->input.ordinal.timestamp = output.timestampUs;
1594 }
1595 outputWorkItem->worklets.emplace_back(new C2Worklet);
1596 const std::unique_ptr<C2Worklet> &worklet = outputWorkItem->worklets.front();
1597 if (worklet == nullptr) {
1598 LOG(ERROR) << "handleWork -- output work item has null worklet";
1599 return;
1600 }
1601 worklet->output.ordinal.frameIndex = output.frameIndex;
1602 worklet->output.ordinal.timestamp = output.timestampUs;
1603 // non-owning hidl_vec<> to wrap around the output config updates
1604 hidl_vec<uint8_t> outputConfigUpdates;
1605 outputConfigUpdates.setToExternal(
1606 output.configUpdates.data, output.configUpdates.size);
1607 std::vector<C2Param*> outputConfigUpdatePtrs;
1608 parseParamsBlob(&outputConfigUpdatePtrs, outputConfigUpdates);
1609 worklet->output.configUpdate.clear();
1610 std::ranges::transform(
1611 outputConfigUpdatePtrs,
1612 std::back_inserter(worklet->output.configUpdate),
1613 [](C2Param* param) { return C2Param::Copy(*param); });
1614 worklet->output.flags = (C2FrameData::flags_t)output.flags;
1615
1616 workItems.push_back(std::move(outputWorkItem));
1617 }
1618
1619 // determine whether the input buffer is drained
1620 if (input.type == APEXCODEC_BUFFER_TYPE_LINEAR) {
1621 if (input.memory.linear.size < consumed) {
1622 LOG(WARNING) << "handleWork -- component consumed more bytes "
1623 << "than the input buffer size";
1624 inputDrained = true;
1625 } else {
1626 input.memory.linear.data += consumed;
1627 input.memory.linear.size -= consumed;
1628 }
1629 } else if (input.type == APEXCODEC_BUFFER_TYPE_GRAPHIC) {
1630 inputDrained = (consumed > 0);
1631 }
1632 }
1633
1634 if (!workItems.empty()) {
1635 listener->onWorkDone(mComponent, workItems);
1636 }
1637 }
1638 }
1639
1640 bool ensureBlockPool() {
1641 std::shared_ptr<Component> comp = mComponent.lock();
1642 if (!comp) {
1643 return false;
1644 }
1645 std::vector<std::unique_ptr<C2Param>> heapParams;
1646 comp->query({}, {C2PortBlockPoolsTuning::output::PARAM_TYPE}, C2_MAY_BLOCK, &heapParams);
1647 if (heapParams.size() != 1) {
1648 return false;
1649 }
1650 const C2Param* param = heapParams[0].get();
1651 if (param->type() != C2PortBlockPoolsTuning::output::PARAM_TYPE) {
1652 return false;
1653 }
1654 const C2PortBlockPoolsTuning::output *blockPools =
1655 static_cast<const C2PortBlockPoolsTuning::output *>(param);
1656 if (blockPools->flexCount() == 0) {
1657 return false;
1658 }
1659 C2BlockPool::local_id_t blockPoolId = blockPools->m.values[0];
1660 if (mBlockPool && mBlockPool->getLocalId() == blockPoolId) {
1661 // no need to update
1662 return true;
1663 }
1664 return C2_OK == GetCodec2BlockPool(blockPoolId, nullptr, &mBlockPool);
1665 }
1666
1667 void allocOutputBuffer(
1668 ApexCodec_Buffer* output,
1669 std::shared_ptr<C2LinearBlock> *linearBlock,
1670 std::optional<C2WriteView> *linearView,
1671 std::shared_ptr<C2GraphicBlock> *graphicBlock) {
1672 if (mOutputBufferType == APEXCODEC_BUFFER_TYPE_LINEAR) {
1673 if (!ensureBlockPool()) {
1674 return;
1675 }
1676 {
1677 std::shared_ptr<Component> comp = mComponent.lock();
1678 if (!comp) {
1679 return;
1680 }
1681 C2StreamMaxBufferSizeInfo::output maxBufferSize(0u /* stream */);
1682 comp->query({&maxBufferSize}, {}, C2_MAY_BLOCK, {});
1683 mLinearBlockCapacity = maxBufferSize ? maxBufferSize.value : 1024 * 1024;
1684 }
1685 output->type = APEXCODEC_BUFFER_TYPE_LINEAR;
1686 c2_status_t status = mBlockPool->fetchLinearBlock(
1687 mLinearBlockCapacity,
1688 C2MemoryUsage(C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE),
1689 linearBlock);
1690 if (!(*linearBlock)) {
1691 return;
1692 }
1693 linearView->emplace((*linearBlock)->map().get());
1694 if ((*linearView)->error() != C2_OK) {
1695 return;
1696 }
1697 output->memory.linear.data = (*linearView)->data();
1698 output->memory.linear.size = (*linearView)->capacity();
1699 } else if (mOutputBufferType == APEXCODEC_BUFFER_TYPE_GRAPHIC) {
1700 if (!ensureBlockPool()) {
1701 return;
1702 }
1703 {
1704 std::shared_ptr<Component> comp = mComponent.lock();
1705 if (!comp) {
1706 return;
1707 }
1708 C2StreamMaxPictureSizeTuning::output maxPictureSize(0u /* stream */);
1709 C2StreamPictureSizeInfo::output pictureSize(0u /* stream */);
1710 C2StreamPixelFormatInfo::output pixelFormat(0u /* stream */);
1711 comp->query({&maxPictureSize, &pictureSize, &pixelFormat}, {}, C2_MAY_BLOCK, {});
1712 mWidth = maxPictureSize ? maxPictureSize.width : pictureSize.width;
1713 mHeight = maxPictureSize ? maxPictureSize.height : pictureSize.height;
1714 mFormat = pixelFormat ? pixelFormat.value : HAL_PIXEL_FORMAT_YCBCR_420_888;
1715 }
1716 output->type = APEXCODEC_BUFFER_TYPE_GRAPHIC;
1717 c2_status_t status = mBlockPool->fetchGraphicBlock(
1718 mWidth, mHeight, mFormat,
1719 C2MemoryUsage(C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE),
1720 graphicBlock);
1721 if (!(*graphicBlock)) {
1722 return;
1723 }
1724 const C2Handle *handle = (*graphicBlock)->handle();
1725 uint32_t width, height, format, stride, igbp_slot, generation;
1726 uint64_t usage, igbp_id;
1727 _UnwrapNativeCodec2GrallocMetadata(
1728 handle, &width, &height, &format, &usage, &stride, &generation,
1729 &igbp_id, &igbp_slot);
1730 native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(handle);
1731 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
1732 grallocHandle, GraphicBuffer::CLONE_HANDLE,
1733 width, height, format, 1, usage, stride);
1734 native_handle_delete(grallocHandle);
1735 AHardwareBuffer *hardwareBuffer =
1736 AHardwareBuffer_from_GraphicBuffer(graphicBuffer.get());
1737 AHardwareBuffer_acquire(hardwareBuffer);
1738 output->memory.graphic = hardwareBuffer;
1739 } else {
1740 LOG(ERROR) << "allocOutputBuffer -- unsupported output buffer type: "
1741 << mOutputBufferType;
1742 return;
1743 }
1744 }
1745
1746 static bool FillMemory(
1747 const std::shared_ptr<C2Buffer>& buffer,
1748 ApexCodec_Buffer* apexBuffer,
1749 std::optional<C2ReadView>* linearView) {
1750 if (buffer->data().type() == C2BufferData::LINEAR) {
1751 apexBuffer->type = APEXCODEC_BUFFER_TYPE_LINEAR;
1752 if (buffer->data().linearBlocks().empty()) {
1753 apexBuffer->memory.linear.data = nullptr;
1754 apexBuffer->memory.linear.size = 0;
1755 return true;
1756 } else if (buffer->data().linearBlocks().size() > 1) {
1757 return false;
1758 }
1759 linearView->emplace(buffer->data().linearBlocks().front().map().get());
1760 if ((*linearView)->error() != C2_OK) {
1761 return false;
1762 }
1763 apexBuffer->memory.linear.data = const_cast<uint8_t*>((*linearView)->data());
1764 apexBuffer->memory.linear.size = (*linearView)->capacity();
1765 return true;
1766 } else if (buffer->data().type() == C2BufferData::GRAPHIC) {
1767 apexBuffer->type = APEXCODEC_BUFFER_TYPE_GRAPHIC;
1768 if (buffer->data().graphicBlocks().empty()) {
1769 apexBuffer->memory.graphic = nullptr;
1770 return true;
1771 } else if (buffer->data().graphicBlocks().size() > 1) {
1772 return false;
1773 }
1774 const C2Handle *handle = buffer->data().graphicBlocks().front().handle();
1775 uint32_t width, height, format, stride, igbp_slot, generation;
1776 uint64_t usage, igbp_id;
1777 _UnwrapNativeCodec2GrallocMetadata(
1778 handle, &width, &height, &format, &usage, &stride, &generation,
1779 &igbp_id, &igbp_slot);
1780 native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(handle);
1781 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
1782 grallocHandle, GraphicBuffer::CLONE_HANDLE,
1783 width, height, format, 1, usage, stride);
1784 native_handle_delete(grallocHandle);
1785 AHardwareBuffer *hardwareBuffer =
1786 AHardwareBuffer_from_GraphicBuffer(graphicBuffer.get());
1787 AHardwareBuffer_acquire(hardwareBuffer);
1788 apexBuffer->memory.graphic = hardwareBuffer;
1789 return true;
1790 }
1791 return false;
1792 }
1793
1794 ApexCodec_Component *mApexComponent;
1795 std::weak_ptr<Listener> mListener;
1796 std::weak_ptr<Component> mComponent;
1797
1798 std::thread mThread;
1799 std::mutex mMutex;
1800 std::condition_variable mCondition;
1801 bool mStopped;
1802 ApexCodec_BufferType mOutputBufferType;
1803
1804 size_t mLinearBlockCapacity;
1805 uint32_t mWidth;
1806 uint32_t mHeight;
1807 uint32_t mFormat;
1808
1809 std::shared_ptr<C2BlockPool> mBlockPool;
1810 std::list<std::unique_ptr<C2Work>> mWorkQueue;
1811 std::map<uint64_t, std::unique_ptr<C2Work>> mWorkMap;
1812};
1813
Wonsik Kime8e98152022-12-16 16:04:17 -08001814// Codec2Client::Component::HidlBufferPoolSender
1815struct Codec2Client::Component::HidlBufferPoolSender :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001816 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
Wonsik Kime8e98152022-12-16 16:04:17 -08001817 HidlBufferPoolSender()
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001818 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
1819 }
1820};
1821
Wonsik Kime8e98152022-12-16 16:04:17 -08001822// Codec2Client::Component::AidlBufferPoolSender
1823struct Codec2Client::Component::AidlBufferPoolSender :
1824 c2_aidl::utils::DefaultBufferPoolSender {
1825 AidlBufferPoolSender()
1826 : c2_aidl::utils::DefaultBufferPoolSender() {
1827 }
1828};
1829
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001830// Codec2Client::Component::OutputBufferQueue
1831struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -07001832 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001833 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -07001834 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001835 }
1836};
1837
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001838// The class holds GraphicBufferAllocator and the associated id of
1839// HAL side BlockPool.
1840// This is tightly coupled with BlockPool creation and destruction.
1841// The life cycle inside class will be as follows.
1842//
1843// On createBlockPool client request.
1844// 1. this::create() creates a GraphicBufferAllocator and set it as
1845// the current.
1846// 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
1847// the GraphicBufferAllocator created in #1.
1848// 3. this::setCurrentId() associates the id returned in #2 to the current
1849//
1850// On destroyBlockPool cliet request
1851// 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
1852// from HAL process.
1853// 2. this::remove() destroys GraphicBufferAllocator which is associatted
1854// with the C2BlockPool in #1.
1855//
1856struct Codec2Client::Component::GraphicBufferAllocators {
1857private:
1858 std::optional<C2BlockPool::local_id_t> mCurrentId;
1859 std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
1860
1861 // A new BlockPool is created before the old BlockPool is destroyed.
1862 // This holds the reference of the old BlockPool when a new BlockPool is
1863 // created until the old BlockPool is explicitly requested for destruction.
1864 std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
1865 std::mutex mMutex;
1866
1867public:
1868 // Creates a GraphicBufferAllocator which will be passed to HAL
1869 // for creating C2BlockPool. And the created GraphicBufferAllocator
1870 // will be used afterwards by current().
1871 std::shared_ptr<AidlGraphicBufferAllocator> create() {
1872 std::unique_lock<std::mutex> l(mMutex);
1873 if (mCurrent) {
1874 // If this is not stopped.
1875 mCurrent->reset();
1876 if (mCurrentId.has_value()) {
1877 mOlds.emplace(mCurrentId.value(), mCurrent);
1878 }
1879 mCurrentId.reset();
1880 mCurrent.reset();
1881 }
1882 // TODO: integrate initial value with CCodec/CCodecBufferChannel
1883 mCurrent =
1884 AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
1885 ALOGD("GraphicBufferAllocator created");
1886 return mCurrent;
1887 }
1888
1889 // Associates the blockpool Id returned from HAL to the
1890 // current GraphicBufferAllocator.
1891 void setCurrentId(C2BlockPool::local_id_t id) {
1892 std::unique_lock<std::mutex> l(mMutex);
1893 CHECK(!mCurrentId.has_value());
1894 mCurrentId = id;
1895 }
1896
1897 // Returns the current GraphicBufferAllocator.
1898 std::shared_ptr<AidlGraphicBufferAllocator> current() {
1899 std::unique_lock<std::mutex> l(mMutex);
1900 return mCurrent;
1901 }
1902
1903 // Removes the GraphicBufferAllocator associated with given \p id.
1904 void remove(C2BlockPool::local_id_t id) {
1905 std::unique_lock<std::mutex> l(mMutex);
1906 mOlds.erase(id);
1907 if (mCurrentId == id) {
1908 if (mCurrent) {
1909 mCurrent->reset();
1910 mCurrent.reset();
1911 }
1912 mCurrentId.reset();
1913 }
1914 }
1915};
1916
Pawin Vongmasa36653902018-11-15 00:10:25 -08001917// Codec2Client
Wonsik Kime8e98152022-12-16 16:04:17 -08001918Codec2Client::Codec2Client(sp<HidlBase> const& base,
Sungtak Leef4b39512023-05-10 07:17:22 +00001919 sp<c2_hidl::IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001920 size_t serviceIndex)
Sungtak Leef4b39512023-05-10 07:17:22 +00001921 : Configurable{configurable},
Wonsik Kime8e98152022-12-16 16:04:17 -08001922 mHidlBase1_0{base},
1923 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1924 mHidlBase1_2{HidlBase1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001925 mServiceIndex{serviceIndex} {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001926 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001927 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001928 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001929 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08001930 mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001931 }
1932}
1933
Wonsik Kime8e98152022-12-16 16:04:17 -08001934Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
1935 std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
1936 size_t serviceIndex)
1937 : Configurable{configurable},
1938 mAidlBase{base},
1939 mServiceIndex{serviceIndex} {
1940 ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
1941 if (!transStatus.isOk()) {
1942 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1943 mAidlHostPoolManager.reset();
1944 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001945}
1946
Wonsik Kimffc868e2024-11-25 18:18:38 +00001947Codec2Client::Codec2Client(ApexCodec_ComponentStore *base,
1948 size_t serviceIndex)
1949 : Configurable{nullptr, "android.componentStore.apexCodecs"},
1950 mApexBase{base},
1951 mServiceIndex{serviceIndex} {
1952}
1953
Wonsik Kime8e98152022-12-16 16:04:17 -08001954sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
1955 return mHidlBase1_0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001956}
1957
Wonsik Kime8e98152022-12-16 16:04:17 -08001958sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
1959 return mHidlBase1_0;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001960}
1961
Wonsik Kime8e98152022-12-16 16:04:17 -08001962sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
1963 return mHidlBase1_1;
1964}
1965
1966sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
1967 return mHidlBase1_2;
1968}
1969
1970::ndk::SpAIBinder Codec2Client::getAidlBase() const {
1971 return mAidlBase ? mAidlBase->asBinder() : nullptr;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001972}
1973
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001974std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001975 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001976}
1977
Pawin Vongmasa36653902018-11-15 00:10:25 -08001978c2_status_t Codec2Client::createComponent(
1979 const C2String& name,
1980 const std::shared_ptr<Codec2Client::Listener>& listener,
1981 std::shared_ptr<Codec2Client::Component>* const component) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00001982 if (mApexBase) {
1983 return createComponent_apex(name, listener, component);
1984 } else if (mAidlBase) {
1985 return createComponent_aidl(name, listener, component);
1986 } else {
1987 return createComponent_hidl(name, listener, component);
Wonsik Kima9ee43d2024-11-22 23:45:42 +00001988 }
Wonsik Kimffc868e2024-11-25 18:18:38 +00001989}
Wonsik Kima9ee43d2024-11-22 23:45:42 +00001990
Wonsik Kimffc868e2024-11-25 18:18:38 +00001991c2_status_t Codec2Client::createComponent_apex(
1992 const C2String& name,
1993 const std::shared_ptr<Codec2Client::Listener>& listener,
1994 std::shared_ptr<Codec2Client::Component>* const component) {
1995 if (__builtin_available(android 36, *)) {
1996 ApexCodec_Component *apexComponent = nullptr;
1997 ApexCodec_Status status = ApexCodec_Component_create(
1998 mApexBase, name.c_str(), &apexComponent);
1999 if (status != APEXCODEC_STATUS_OK) {
2000 return (c2_status_t)status;
2001 }
2002 *component = std::make_shared<Codec2Client::Component>(apexComponent, name);
2003 (*component)->initApexHandler(listener, *component);
2004 return C2_OK;
2005 } else {
2006 return C2_OMITTED;
2007 }
2008}
2009
2010c2_status_t Codec2Client::createComponent_aidl(
2011 const C2String& name,
2012 const std::shared_ptr<Codec2Client::Listener>& listener,
2013 std::shared_ptr<Codec2Client::Component>* const component) {
2014 std::shared_ptr<Component::AidlListener> aidlListener =
2015 Component::AidlListener::make<Component::AidlListener>();
2016 aidlListener->base = listener;
2017 std::shared_ptr<c2_aidl::IComponent> aidlComponent;
2018 ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
2019 name,
2020 aidlListener,
2021 bufferpool2_aidl::implementation::ClientManager::getInstance(),
2022 &aidlComponent);
2023 c2_status_t status = GetC2Status(transStatus, "createComponent");
2024 if (status != C2_OK) {
2025 return status;
2026 } else if (!aidlComponent) {
2027 LOG(ERROR) << "createComponent(" << name.c_str()
2028 << ") -- null component.";
2029 return C2_CORRUPTED;
2030 }
2031 *component = std::make_shared<Codec2Client::Component>(aidlComponent);
2032 status = (*component)->setDeathListener((*component), listener);
2033 if (status != C2_OK) {
2034 LOG(ERROR) << "createComponent(" << name.c_str()
2035 << ") -- failed to set up death listener: "
2036 << status << ".";
2037 }
2038 (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
2039 aidlListener->component = *component;
2040 return status;
2041}
2042
2043c2_status_t Codec2Client::createComponent_hidl(
2044 const C2String& name,
2045 const std::shared_ptr<Codec2Client::Listener>& listener,
2046 std::shared_ptr<Codec2Client::Component>* const component) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002047 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002048 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -08002049 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -08002050 Return<void> transStatus;
Wonsik Kime8e98152022-12-16 16:04:17 -08002051 if (mHidlBase1_2) {
2052 transStatus = mHidlBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002053 name,
2054 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002055 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -08002056 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002057 c2_hidl::Status s,
2058 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002059 status = static_cast<c2_status_t>(s);
2060 if (status != C2_OK) {
2061 return;
2062 }
2063 *component = std::make_shared<Codec2Client::Component>(c);
2064 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -08002065 });
2066 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002067 else if (mHidlBase1_1) {
2068 transStatus = mHidlBase1_1->createComponent_1_1(
Sungtak Lee8577dab2021-03-12 02:25:50 -08002069 name,
2070 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002071 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -08002072 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002073 c2_hidl::Status s,
2074 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -08002075 status = static_cast<c2_status_t>(s);
2076 if (status != C2_OK) {
2077 return;
2078 }
2079 *component = std::make_shared<Codec2Client::Component>(c);
2080 hidlListener->component = *component;
2081 });
Wonsik Kime8e98152022-12-16 16:04:17 -08002082 } else if (mHidlBase1_0) { // ver1_0
2083 transStatus = mHidlBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002084 name,
2085 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002086 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002087 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002088 c2_hidl::Status s,
2089 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002090 status = static_cast<c2_status_t>(s);
2091 if (status != C2_OK) {
2092 return;
2093 }
2094 *component = std::make_shared<Codec2Client::Component>(c);
2095 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002096 });
Sungtak Lee8577dab2021-03-12 02:25:50 -08002097 } else {
2098 status = C2_CORRUPTED;
2099 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002100 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002101 LOG(ERROR) << "createComponent(" << name.c_str()
2102 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002103 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002104 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08002105 if (status == C2_NOT_FOUND) {
2106 LOG(VERBOSE) << "createComponent(" << name.c_str()
2107 << ") -- component not found.";
2108 } else {
2109 LOG(ERROR) << "createComponent(" << name.c_str()
2110 << ") -- call failed: " << status << ".";
2111 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002112 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002113 } else if (!*component) {
2114 LOG(ERROR) << "createComponent(" << name.c_str()
2115 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002116 return C2_CORRUPTED;
2117 }
2118
2119 status = (*component)->setDeathListener(*component, listener);
2120 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002121 LOG(ERROR) << "createComponent(" << name.c_str()
2122 << ") -- failed to set up death listener: "
2123 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002124 }
2125
Wonsik Kime8e98152022-12-16 16:04:17 -08002126 (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002127 return status;
2128}
2129
2130c2_status_t Codec2Client::createInterface(
2131 const C2String& name,
2132 std::shared_ptr<Codec2Client::Interface>* const interface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002133 if (mAidlBase) {
2134 std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
2135 ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
2136 name,
2137 &aidlInterface);
2138 c2_status_t status = GetC2Status(transStatus, "createInterface");
2139 if (status != C2_OK) {
2140 return status;
2141 } else if (!aidlInterface) {
2142 LOG(ERROR) << "createInterface(" << name.c_str()
2143 << ") -- null interface.";
2144 return C2_CORRUPTED;
2145 }
2146 interface->reset(new Codec2Client::Interface(aidlInterface));
2147 return C2_OK;
2148 }
2149
Pawin Vongmasa36653902018-11-15 00:10:25 -08002150 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002151 Return<void> transStatus = mHidlBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002152 name,
2153 [&status, interface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002154 c2_hidl::Status s,
2155 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002156 status = static_cast<c2_status_t>(s);
2157 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002158 return;
2159 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002160 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002161 });
2162 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002163 LOG(ERROR) << "createInterface(" << name.c_str()
2164 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002165 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002166 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08002167 if (status == C2_NOT_FOUND) {
2168 LOG(VERBOSE) << "createInterface(" << name.c_str()
2169 << ") -- component not found.";
2170 } else {
2171 LOG(ERROR) << "createInterface(" << name.c_str()
2172 << ") -- call failed: " << status << ".";
2173 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002174 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002175 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002176
Pawin Vongmasa36653902018-11-15 00:10:25 -08002177 return status;
2178}
2179
2180c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002181 std::shared_ptr<InputSurface>* const inputSurface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002182 if (mAidlBase) {
2183 // FIXME
2184 return C2_OMITTED;
2185 }
2186
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002187 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002188 Return<void> transStatus = mHidlBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002189 [&status, inputSurface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002190 c2_hidl::Status s,
2191 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002192 status = static_cast<c2_status_t>(s);
2193 if (status != C2_OK) {
2194 return;
2195 }
2196 *inputSurface = std::make_shared<InputSurface>(i);
2197 });
2198 if (!transStatus.isOk()) {
2199 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002200 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002201 } else if (status != C2_OK) {
2202 LOG(DEBUG) << "createInputSurface -- call failed: "
2203 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002204 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002205 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002206}
2207
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002208std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
2209 return Cache::List()[mServiceIndex].getTraits();
2210}
2211
2212std::vector<C2Component::Traits> Codec2Client::_listComponents(
2213 bool* success) const {
2214 std::vector<C2Component::Traits> traits;
2215 std::string const& serviceName = getServiceName();
Wonsik Kime8e98152022-12-16 16:04:17 -08002216
2217 if (mAidlBase) {
2218 std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
2219 ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
2220 if (!transStatus.isOk()) {
2221 LOG(ERROR) << "_listComponents -- transaction failed.";
2222 *success = false;
2223 } else {
2224 traits.resize(aidlTraits.size());
2225 *success = true;
2226 for (size_t i = 0; i < aidlTraits.size(); ++i) {
2227 if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
2228 LOG(ERROR) << "_listComponents -- corrupted output.";
2229 *success = false;
2230 traits.clear();
2231 break;
2232 }
2233 traits[i].owner = serviceName;
2234 }
2235 }
2236 return traits;
2237 }
2238 Return<void> transStatus = mHidlBase1_0->listComponents(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002239 [&traits, &serviceName](c2_hidl::Status s,
2240 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
2241 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002242 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002243 << static_cast<c2_status_t>(s) << ".";
2244 return;
2245 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002246 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08002247 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002248 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002249 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002250 return;
2251 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002252 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002253 }
2254 });
2255 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002256 LOG(ERROR) << "_listComponents -- transaction failed.";
2257 *success = false;
2258 } else {
2259 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002260 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002261 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002262}
2263
2264c2_status_t Codec2Client::copyBuffer(
2265 const std::shared_ptr<C2Buffer>& src,
2266 const std::shared_ptr<C2Buffer>& dst) {
2267 // TODO: Implement?
2268 (void)src;
2269 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002270 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002271 return C2_OMITTED;
2272}
2273
Wonsik Kime8e98152022-12-16 16:04:17 -08002274std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002275 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
2276 // should reflect the HAL API.
Wonsik Kime8e98152022-12-16 16:04:17 -08002277 struct HidlSimpleParamReflector : public C2ParamReflector {
2278 std::unique_ptr<C2StructDescriptor> describe(
2279 C2Param::CoreIndex coreIndex) const override {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002280 hidl_vec<c2_hidl::ParamIndex> indices(1);
2281 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08002282 std::unique_ptr<C2StructDescriptor> descriptor;
2283 Return<void> transStatus = mBase->getStructDescriptors(
2284 indices,
2285 [&descriptor](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002286 c2_hidl::Status s,
2287 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002288 c2_status_t status = static_cast<c2_status_t>(s);
2289 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002290 LOG(DEBUG) << "SimpleParamReflector -- "
2291 "getStructDescriptors() failed: "
2292 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002293 descriptor.reset();
2294 return;
2295 }
2296 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002297 LOG(DEBUG) << "SimpleParamReflector -- "
2298 "getStructDescriptors() "
2299 "returned vector of size "
2300 << sd.size() << ". "
2301 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002302 descriptor.reset();
2303 return;
2304 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002305 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002306 LOG(DEBUG) << "SimpleParamReflector -- "
2307 "getStructDescriptors() returned "
2308 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002309 descriptor.reset();
2310 return;
2311 }
2312 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08002313 if (!transStatus.isOk()) {
2314 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
2315 << transStatus.description();
2316 descriptor.reset();
2317 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002318 return descriptor;
2319 }
2320
Wonsik Kime8e98152022-12-16 16:04:17 -08002321 HidlSimpleParamReflector(sp<HidlBase> base)
Pawin Vongmasa36653902018-11-15 00:10:25 -08002322 : mBase(base) { }
2323
Wonsik Kime8e98152022-12-16 16:04:17 -08002324 sp<HidlBase> mBase;
2325 };
2326 struct AidlSimpleParamReflector : public C2ParamReflector {
2327 std::unique_ptr<C2StructDescriptor> describe(
2328 C2Param::CoreIndex coreIndex) const override {
2329 std::vector<c2_aidl::StructDescriptor> aidlDesc;
2330 std::unique_ptr<C2StructDescriptor> descriptor;
2331 ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
2332 {int32_t(coreIndex.coreIndex())},
2333 &aidlDesc);
2334 c2_status_t status = GetC2Status(transStatus, "describe");
2335 if (status != C2_OK) {
2336 descriptor.reset();
2337 } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
2338 LOG(ERROR) << "describe -- conversion failed.";
2339 descriptor.reset();
2340 }
2341 return descriptor;
2342 }
2343
2344 AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
2345 : mBase(base) { }
2346
2347 std::shared_ptr<AidlBase> mBase;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002348 };
2349
Wonsik Kime8e98152022-12-16 16:04:17 -08002350 if (mAidlBase) {
2351 return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
2352 }
2353 return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002354};
2355
Wonsik Kime8e98152022-12-16 16:04:17 -08002356std::vector<std::string> Codec2Client::CacheServiceNames() {
2357 std::vector<std::string> names;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002358
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002359 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07002360 if (__builtin_available(android __ANDROID_API_S__, *)) {
2361 // Get AIDL service names
2362 AServiceManager_forEachDeclaredInstance(
2363 AidlBase::descriptor, &names, [](const char *name, void *context) {
2364 std::vector<std::string> *names = (std::vector<std::string> *)context;
2365 names->emplace_back(name);
2366 });
2367 } else {
2368 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
2369 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002370 } else {
2371 // Get HIDL service names
2372 using ::android::hardware::media::c2::V1_0::IComponentStore;
2373 using ::android::hidl::manager::V1_2::IServiceManager;
2374 while (true) {
2375 sp<IServiceManager> serviceManager = IServiceManager::getService();
2376 CHECK(serviceManager) << "Hardware service manager is not running.";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002377
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002378 Return<void> transResult;
2379 transResult = serviceManager->listManifestByInterface(
2380 IComponentStore::descriptor,
2381 [&names](
2382 hidl_vec<hidl_string> const& instanceNames) {
2383 names.insert(names.end(), instanceNames.begin(), instanceNames.end());
2384 });
2385 if (transResult.isOk()) {
2386 break;
2387 }
2388 LOG(ERROR) << "Could not retrieve the list of service instances of "
2389 << IComponentStore::descriptor
2390 << ". Retrying...";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002391 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002392 }
2393 // Sort service names in each category.
2394 std::stable_sort(
2395 names.begin(), names.end(),
2396 [](const std::string &a, const std::string &b) {
2397 // First compare by prefix: default -> vendor -> {everything else}
2398 constexpr int DEFAULT = 1;
2399 constexpr int VENDOR = 2;
2400 constexpr int OTHER = 3;
2401 int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
2402 (a.compare(0, 6, "vendor") == 0) ? VENDOR :
2403 OTHER);
2404 int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
2405 (b.compare(0, 6, "vendor") == 0) ? VENDOR :
2406 OTHER);
2407 if (aPrefix != bPrefix) {
2408 return aPrefix < bPrefix;
2409 }
2410 // If the prefix is the same, compare alphabetically
2411 return a < b;
2412 });
2413
Wonsik Kimffc868e2024-11-25 18:18:38 +00002414 if (__builtin_available(android 36, *)) {
2415 if (android::media::codec::provider_->in_process_sw_audio_codec_support()
2416 && nullptr != ApexCodec_GetComponentStore()) {
2417 names.push_back("__ApexCodecs__");
2418 }
2419 }
2420
Wonsik Kime8e98152022-12-16 16:04:17 -08002421 // Summarize to logcat.
2422 if (names.empty()) {
2423 LOG(INFO) << "No Codec2 services declared in the manifest.";
2424 } else {
2425 std::stringstream stringOutput;
2426 stringOutput << "Available Codec2 services:";
2427 for (std::string const& name : names) {
2428 stringOutput << " \"" << name << "\"";
2429 }
2430 LOG(INFO) << stringOutput.str();
2431 }
2432
2433 return names;
2434}
2435
2436std::vector<std::string> const& Codec2Client::GetServiceNames() {
2437 static std::vector<std::string> sServiceNames = CacheServiceNames();
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002438 return sServiceNames;
2439}
2440
Pawin Vongmasa36653902018-11-15 00:10:25 -08002441std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08002442 const char* name,
2443 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002444 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08002445 if (index == GetServiceNames().size()) {
2446 if (setAsPreferredCodec2ComponentStore) {
2447 LOG(WARNING) << "CreateFromService(" << name
2448 << ") -- preferred C2ComponentStore not set.";
2449 }
2450 return nullptr;
2451 }
2452 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
2453 if (setAsPreferredCodec2ComponentStore) {
2454 SetPreferredCodec2ComponentStore(
2455 std::make_shared<Client2Store>(client));
2456 LOG(INFO) << "CreateFromService(" << name
2457 << ") -- service set as preferred C2ComponentStore.";
2458 }
2459 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002460}
2461
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002462std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
2463 CreateFromAllServices() {
2464 std::vector<std::shared_ptr<Codec2Client>> clients(
2465 GetServiceNames().size());
2466 for (size_t i = GetServiceNames().size(); i > 0; ) {
2467 --i;
2468 clients[i] = _CreateFromIndex(i);
2469 }
2470 return clients;
2471}
2472
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002473std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002474 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08002475 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Wonsik Kime8e98152022-12-16 16:04:17 -08002476
Wonsik Kimffc868e2024-11-25 18:18:38 +00002477 if (name == "__ApexCodecs__") {
2478 if (__builtin_available(android 36, *)) {
2479 return std::make_shared<Codec2Client>(ApexCodec_GetComponentStore(), index);
2480 } else {
2481 LOG(FATAL) << "ApexCodecs not supported on Android version older than 36";
2482 }
2483 } else if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07002484 if (__builtin_available(android __ANDROID_API_S__, *)) {
2485 std::string instanceName =
2486 ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
2487 if (AServiceManager_isDeclared(instanceName.c_str())) {
2488 std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
2489 ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
2490 CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
2491 " inaccessible for unknown reasons.";
2492 LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
2493 std::shared_ptr<c2_aidl::IConfigurable> configurable;
2494 ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
2495 CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
2496 "does not have IConfigurable.";
2497 return std::make_shared<Codec2Client>(baseStore, configurable, index);
2498 } else {
2499 LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
2500 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002501 } else {
Wonsik Kim138db0d2023-11-02 16:02:01 -07002502 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
Wonsik Kime8e98152022-12-16 16:04:17 -08002503 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002504 } else {
2505 std::string instanceName = "android.hardware.media.c2/" + name;
2506 sp<HidlBase> baseStore = HidlBase::getService(name);
2507 CHECK(baseStore) << "Codec2 service \"" << name << "\""
2508 " inaccessible for unknown reasons.";
2509 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
2510 Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
2511 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
2512 "does not have IConfigurable.";
2513 sp<c2_hidl::IConfigurable> configurable =
2514 static_cast<sp<c2_hidl::IConfigurable>>(transResult);
2515 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Wonsik Kime8e98152022-12-16 16:04:17 -08002516 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07002517 return nullptr;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002518}
2519
2520c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002521 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002522 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002523 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
2524 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002525 c2_status_t status = C2_NO_INIT; // no IComponentStores present
2526
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002527 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08002528 static std::mutex key2IndexMutex;
2529 static std::map<std::string, size_t> key2Index;
2530
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002531 // By default try all stores. However, try the last known client first. If
2532 // the last known client fails, retry once. We do this by pushing the last
2533 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08002534 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002535 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002536 indices.push_front(--index);
2537 }
2538
2539 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002540 {
2541 std::scoped_lock lock{key2IndexMutex};
2542 auto it = key2Index.find(key);
2543 if (it != key2Index.end()) {
2544 indices.push_front(it->second);
2545 wasMapped = true;
2546 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002547 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002548
2549 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002550 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002551 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
2552 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08002553 status = predicate(client);
2554 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002555 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08002556 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002557 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002558 } else if (status == C2_NO_MEMORY) {
2559 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002560 } else if (status == C2_TRANSACTION_FAILED) {
2561 LOG(WARNING) << "\"" << key << "\" failed for service \""
2562 << client->getName()
2563 << "\" due to transaction failure. "
2564 << "(Service may have crashed.)"
2565 << (tries > 1 ? " Retrying..." : "");
2566 cache.invalidate();
2567 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002568 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002569 if (wasMapped) {
2570 LOG(INFO) << "\"" << key << "\" became invalid in service \""
2571 << client->getName() << "\". Retrying...";
2572 wasMapped = false;
2573 }
2574 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002575 }
2576 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002577 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08002578}
2579
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002580c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002581 const char* componentName,
2582 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002583 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07002584 std::shared_ptr<Codec2Client>* owner,
2585 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002586 std::string key{"create:"};
2587 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002588 c2_status_t status = ForAllServices(
2589 key,
2590 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002591 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002592 const std::shared_ptr<Codec2Client> &client)
2593 -> c2_status_t {
2594 c2_status_t status = client->createComponent(componentName,
2595 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002596 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002597 if (status == C2_OK) {
2598 if (owner) {
2599 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002600 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002601 } else if (status != C2_NOT_FOUND) {
2602 LOG(DEBUG) << "IComponentStore("
2603 << client->getServiceName()
2604 << ")::createComponent(\"" << componentName
2605 << "\") returned status = "
2606 << status << ".";
2607 }
2608 return status;
2609 });
2610 if (status != C2_OK) {
2611 LOG(DEBUG) << "Failed to create component \"" << componentName
2612 << "\" from all known services. "
2613 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002614 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09002615 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002616}
2617
Wonsik Kime8e98152022-12-16 16:04:17 -08002618std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002619 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07002620 std::shared_ptr<Codec2Client>* owner,
2621 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002622 std::string key{"create:"};
2623 key.append(interfaceName);
2624 std::shared_ptr<Interface> interface;
2625 c2_status_t status = ForAllServices(
2626 key,
2627 numberOfAttempts,
2628 [owner, &interface, interfaceName](
2629 const std::shared_ptr<Codec2Client> &client)
2630 -> c2_status_t {
2631 c2_status_t status = client->createInterface(interfaceName,
2632 &interface);
2633 if (status == C2_OK) {
2634 if (owner) {
2635 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002636 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002637 } else if (status != C2_NOT_FOUND) {
2638 LOG(DEBUG) << "IComponentStore("
2639 << client->getServiceName()
2640 << ")::createInterface(\"" << interfaceName
2641 << "\") returned status = "
2642 << status << ".";
2643 }
2644 return status;
2645 });
2646 if (status != C2_OK) {
2647 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
2648 << "\" from all known services. "
2649 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002650 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07002651 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002652}
2653
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002654std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
2655 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002656 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002657 for (Cache& cache : Cache::List()) {
2658 std::vector<C2Component::Traits> const& traits = cache.getTraits();
2659 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08002660 }
2661 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002662 }()};
2663 return sList;
2664}
Pawin Vongmasa36653902018-11-15 00:10:25 -08002665
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002666std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
2667 char const* serviceName) {
Sungtak Lee587aa322024-11-13 08:47:32 +00002668 if (!IsCodec2AidlInputSurfaceSelected()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002669 return nullptr;
2670 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002671 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002672 if (serviceName) {
2673 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002674 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002675 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
2676 << serviceName << "\"";
2677 }
2678 }
2679
2680 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07002681 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07002682 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
2683 if (client->createInputSurface(&inputSurface) == C2_OK) {
2684 return inputSurface;
2685 }
2686 }
2687 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
2688 "from all services...";
2689 for (Cache& cache : Cache::List()) {
2690 std::shared_ptr<Codec2Client> client = cache.getClient();
2691 if (client->createInputSurface(&inputSurface) == C2_OK) {
2692 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
2693 "service \"" << client->getServiceName() << "\"";
2694 return inputSurface;
2695 }
2696 }
2697 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
2698 "from all services";
2699 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002700}
2701
Sungtak Lee92bca442024-03-12 09:10:31 +00002702bool Codec2Client::IsAidlSelected() {
2703 return c2_aidl::utils::IsSelected();
2704}
2705
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002706// Codec2Client::Interface
Wonsik Kime8e98152022-12-16 16:04:17 -08002707Codec2Client::Interface::Interface(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002708 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002709 [base]() -> sp<c2_hidl::IConfigurable> {
2710 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002711 base->getConfigurable();
2712 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002713 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002714 nullptr;
2715 }()
2716 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002717 mHidlBase{base} {
2718}
2719
2720Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
2721 : Configurable{
2722 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2723 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2724 ::ndk::ScopedAStatus transStatus =
2725 base->getConfigurable(&aidlConfigurable);
2726 return transStatus.isOk() ? aidlConfigurable : nullptr;
2727 }()
2728 },
2729 mAidlBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002730}
2731
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002732// Codec2Client::Component
Wonsik Kime8e98152022-12-16 16:04:17 -08002733
2734class Codec2Client::Component::AidlDeathManager {
2735public:
2736 AidlDeathManager()
2737 : mSeq(0),
2738 mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
2739 }
2740
2741 ~AidlDeathManager() = default;
2742
2743 bool linkToDeath(
2744 const std::shared_ptr<Component> &comp,
2745 const std::shared_ptr<Listener> &listener,
2746 size_t *seqPtr) {
2747 std::unique_lock lock(mMutex);
2748 size_t seq = mSeq++;
2749 if (!mMap.try_emplace(seq, comp, listener).second) {
2750 return false;
2751 }
2752 if (STATUS_OK != AIBinder_linkToDeath(
2753 comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
2754 mMap.erase(seq);
2755 return false;
2756 }
2757 *seqPtr = seq;
2758 return true;
2759 }
2760
2761 void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
2762 std::unique_lock lock(mMutex);
2763 AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
2764 mMap.erase(seq);
2765 }
2766
2767private:
2768 std::mutex mMutex;
2769 size_t mSeq;
2770 typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
2771 std::map<size_t, Context> mMap;
2772 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
2773
2774 bool extractContext(size_t seq, Context *context) {
2775 std::unique_lock lock(mMutex);
2776 auto node = mMap.extract(seq);
2777 if (!node) {
2778 return false;
2779 }
2780 *context = node.mapped();
2781 return true;
2782 }
2783
2784 static void OnBinderDied(void *cookie) {
2785 size_t seq = size_t(cookie);
2786 Context context;
2787 if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
2788 return;
2789 }
2790 std::weak_ptr<Component> weakComponent;
2791 std::weak_ptr<Listener> weakListener;
2792 std::tie(weakComponent, weakListener) = context;
2793 if (std::shared_ptr<Listener> listener = weakListener.lock()) {
2794 listener->onDeath(weakComponent);
2795 } else {
2796 LOG(DEBUG) << "onDeath -- listener died.";
2797 }
2798 }
2799};
2800
2801Codec2Client::Component::Component(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002802 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002803 [base]() -> sp<c2_hidl::IConfigurable> {
2804 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002805 base->getInterface();
2806 if (!transResult1.isOk()) {
2807 return nullptr;
2808 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002809 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2810 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002811 getConfigurable();
2812 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002813 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002814 nullptr;
2815 }()
2816 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002817 mHidlBase1_0{base},
2818 mHidlBase1_1{HidlBase1_1::castFrom(base)},
2819 mHidlBase1_2{HidlBase1_2::castFrom(base)},
2820 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002821 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2822}
2823
Wonsik Kime8e98152022-12-16 16:04:17 -08002824Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002825 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002826 [base]() -> sp<c2_hidl::IConfigurable> {
2827 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002828 base->getInterface();
2829 if (!transResult1.isOk()) {
2830 return nullptr;
2831 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002832 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2833 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002834 getConfigurable();
2835 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002836 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002837 nullptr;
2838 }()
2839 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002840 mHidlBase1_0{base},
2841 mHidlBase1_1{base},
2842 mHidlBase1_2{HidlBase1_2::castFrom(base)},
2843 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Sungtak Lee8577dab2021-03-12 02:25:50 -08002844 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2845}
2846
Wonsik Kime8e98152022-12-16 16:04:17 -08002847Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
Sungtak Lee8577dab2021-03-12 02:25:50 -08002848 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002849 [base]() -> sp<c2_hidl::IConfigurable> {
2850 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08002851 base->getInterface();
2852 if (!transResult1.isOk()) {
2853 return nullptr;
2854 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002855 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2856 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08002857 getConfigurable();
2858 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002859 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08002860 nullptr;
2861 }()
2862 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002863 mHidlBase1_0{base},
2864 mHidlBase1_1{base},
2865 mHidlBase1_2{base},
2866 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2867 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2868}
2869
2870Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
2871 : Configurable{
2872 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2873 std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
2874 ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
2875 if (!transStatus.isOk()) {
2876 return nullptr;
2877 }
2878 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2879 transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
2880 return transStatus.isOk() ? aidlConfigurable : nullptr;
2881 }()
2882 },
2883 mAidlBase{base},
2884 mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002885 mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002886}
2887
Wonsik Kimffc868e2024-11-25 18:18:38 +00002888Codec2Client::Component::Component(ApexCodec_Component *base, const C2String &name)
2889 : Configurable{[base]() -> ApexCodec_Configurable * {
2890 if (__builtin_available(android 36, *)) {
2891 return ApexCodec_Component_getConfigurable(base);
2892 } else {
2893 return nullptr;
2894 }
2895 }(), name},
2896 mApexBase{base} {
2897}
2898
Pawin Vongmasa36653902018-11-15 00:10:25 -08002899Codec2Client::Component::~Component() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002900 if (mAidlDeathSeq) {
2901 GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
2902 }
Wonsik Kimffc868e2024-11-25 18:18:38 +00002903 if (mApexBase) {
2904 if (__builtin_available(android 36, *)) {
2905 ApexCodec_Component_destroy(mApexBase);
2906 }
2907 mApexBase = nullptr;
2908 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002909}
2910
2911c2_status_t Codec2Client::Component::createBlockPool(
2912 C2Allocator::id_t id,
2913 C2BlockPool::local_id_t* blockPoolId,
2914 std::shared_ptr<Codec2Client::Configurable>* configurable) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00002915 if (mApexBase) {
2916 std::shared_ptr<C2BlockPool> blockPool;
2917 CreateCodec2BlockPool(id, nullptr, &blockPool);
2918 *blockPoolId = blockPool->getLocalId();
2919 *configurable = nullptr;
2920 mBlockPools[*blockPoolId] = blockPool;
2921 return C2_OK;
2922 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002923 if (mAidlBase) {
2924 c2_aidl::IComponent::BlockPool aidlBlockPool;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002925 c2_status_t status = C2_OK;
2926
2927 // TODO: Temporary mapping for the current CCodecBufferChannel.
2928 // Handle this properly and remove this temporary allocator mapping.
2929 id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
2930 C2PlatformAllocatorStore::IGBA : id;
2931
Sungtak Leefffb5692024-01-18 11:22:38 +00002932 c2_aidl::IComponent::BlockPoolAllocator allocator;
2933 allocator.allocatorId = id;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002934 if (id == C2PlatformAllocatorStore::IGBA) {
2935 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2936 mGraphicBufferAllocators->create();
2937 ::ndk::ScopedFileDescriptor waitableFd;
2938 ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
2939 status = GetC2Status(ret, "Gba::getWaitableFd");
2940 if (status != C2_OK) {
2941 return status;
2942 }
Sungtak Leefffb5692024-01-18 11:22:38 +00002943 c2_aidl::IComponent::GbAllocator gbAllocator;
2944 gbAllocator.waitableFd = std::move(waitableFd);
2945 gbAllocator.igba =
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002946 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
Sungtak Leefffb5692024-01-18 11:22:38 +00002947 allocator.gbAllocator = std::move(gbAllocator);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002948 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2949 allocator, &aidlBlockPool);
2950 status = GetC2Status(transStatus, "createBlockPool");
2951 if (status != C2_OK) {
2952 return status;
2953 }
2954 mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
2955 } else {
2956 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
Sungtak Leefffb5692024-01-18 11:22:38 +00002957 allocator, &aidlBlockPool);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002958 status = GetC2Status(transStatus, "createBlockPool");
2959 if (status != C2_OK) {
2960 return status;
2961 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002962 }
2963 *blockPoolId = aidlBlockPool.blockPoolId;
2964 *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
2965 return C2_OK;
2966 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002967 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002968 Return<void> transStatus = mHidlBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002969 static_cast<uint32_t>(id),
2970 [&status, blockPoolId, configurable](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002971 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08002972 uint64_t pId,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002973 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002974 status = static_cast<c2_status_t>(s);
2975 configurable->reset();
2976 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002977 LOG(DEBUG) << "createBlockPool -- call failed: "
2978 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002979 return;
2980 }
2981 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002982 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002983 });
2984 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002985 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002986 return C2_TRANSACTION_FAILED;
2987 }
2988 return status;
2989}
2990
2991c2_status_t Codec2Client::Component::destroyBlockPool(
2992 C2BlockPool::local_id_t localId) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00002993 if (mApexBase) {
2994 mBlockPools.erase(localId);
2995 return C2_OK;
2996 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002997 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002998 mGraphicBufferAllocators->remove(localId);
Wonsik Kime8e98152022-12-16 16:04:17 -08002999 ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
3000 return GetC2Status(transStatus, "destroyBlockPool");
3001 }
3002 Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08003003 static_cast<uint64_t>(localId));
3004 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003005 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003006 return C2_TRANSACTION_FAILED;
3007 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003008 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003009}
3010
Wonsik Kimab34ed62019-01-31 15:28:46 -08003011void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08003012 const std::list<std::unique_ptr<C2Work>> &workItems) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003013 if (mApexBase) {
3014 // no-op
3015 return;
3016 } else if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003017 holdIgbaBlocks(workItems);
3018 } else {
3019 // Output bufferqueue-based blocks' lifetime management
3020 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
3021 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003022}
3023
3024c2_status_t Codec2Client::Component::queue(
3025 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003026 if (mApexBase) {
3027 mApexHandler->queue(*items);
3028 return C2_OK;
3029 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003030 if (mAidlBase) {
3031 c2_aidl::WorkBundle workBundle;
3032 if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
3033 LOG(ERROR) << "queue -- bad input.";
3034 return C2_TRANSACTION_FAILED;
3035 }
3036 ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
3037 return GetC2Status(transStatus, "queue");
3038 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003039 c2_hidl::WorkBundle workBundle;
Wonsik Kime8e98152022-12-16 16:04:17 -08003040 if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003041 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003042 return C2_TRANSACTION_FAILED;
3043 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003044 Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08003045 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003046 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003047 return C2_TRANSACTION_FAILED;
3048 }
3049 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003050 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003051 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003052 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003053 }
3054 return status;
3055}
3056
3057c2_status_t Codec2Client::Component::flush(
3058 C2Component::flush_mode_t mode,
3059 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
Wonsik Kime8e98152022-12-16 16:04:17 -08003060 (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
Wonsik Kimffc868e2024-11-25 18:18:38 +00003061 if (mApexBase) {
3062 if (__builtin_available(android 36, *)) {
3063 return (c2_status_t)ApexCodec_Component_flush(mApexBase);
3064 } else {
3065 return C2_OMITTED;
3066 }
3067 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003068 c2_status_t status = C2_OK;
3069 if (mAidlBase) {
3070 c2_aidl::WorkBundle workBundle;
3071 ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
3072 c2_status_t status = GetC2Status(transStatus, "flush");
3073 if (status != C2_OK) {
3074 return status;
3075 }
3076 if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
3077 LOG(DEBUG) << "flush -- flushedWork corrupted.";
3078 return C2_CORRUPTED;
3079 }
3080 } else {
3081 Return<void> transStatus = mHidlBase1_0->flush(
3082 [&status, flushedWork](
3083 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
3084 status = static_cast<c2_status_t>(s);
3085 if (status != C2_OK) {
3086 LOG(DEBUG) << "flush -- call failed: " << status << ".";
3087 return;
3088 }
3089 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
3090 status = C2_CORRUPTED;
3091 } else {
3092 status = C2_OK;
3093 }
3094 });
3095 if (!transStatus.isOk()) {
3096 LOG(ERROR) << "flush -- transaction failed.";
3097 return C2_TRANSACTION_FAILED;
3098 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003099 }
3100
3101 // Indices of flushed work items.
3102 std::vector<uint64_t> flushedIndices;
3103 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
3104 if (work) {
3105 if (work->worklets.empty()
3106 || !work->worklets.back()
3107 || (work->worklets.back()->output.flags &
3108 C2FrameData::FLAG_INCOMPLETE) == 0) {
3109 // input is complete
3110 flushedIndices.emplace_back(
3111 work->input.ordinal.frameIndex.peeku());
3112 }
3113 }
3114 }
3115
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003116 if (mAidlBase) {
3117 holdIgbaBlocks(*flushedWork);
3118 } else {
3119 // Output bufferqueue-based blocks' lifetime management
3120 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
3121 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003122
3123 return status;
3124}
3125
3126c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003127 if (mApexBase) {
3128 return C2_OMITTED;
3129 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003130 if (mAidlBase) {
3131 ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
3132 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
3133 return GetC2Status(transStatus, "drain");
3134 }
3135 Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08003136 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
3137 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003138 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003139 return C2_TRANSACTION_FAILED;
3140 }
3141 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003142 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003143 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003144 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003145 }
3146 return status;
3147}
3148
3149c2_status_t Codec2Client::Component::start() {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003150 if (mApexBase) {
3151 // no-op
3152 return C2_OK;
3153 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003154 if (mAidlBase) {
3155 ::ndk::ScopedAStatus transStatus = mAidlBase->start();
3156 return GetC2Status(transStatus, "start");
3157 }
3158 Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08003159 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003160 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003161 return C2_TRANSACTION_FAILED;
3162 }
3163 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003164 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003165 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003166 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003167 }
3168 return status;
3169}
3170
3171c2_status_t Codec2Client::Component::stop() {
Wonsik Kime8e98152022-12-16 16:04:17 -08003172 if (mAidlBase) {
3173 ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
3174 return GetC2Status(transStatus, "stop");
3175 }
3176 Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08003177 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003178 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003179 return C2_TRANSACTION_FAILED;
3180 }
3181 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003182 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003183 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003184 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003185 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003186 return status;
3187}
3188
3189c2_status_t Codec2Client::Component::reset() {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003190 if (mApexBase) {
3191 if (__builtin_available(android 36, *)) {
3192 return (c2_status_t)ApexCodec_Component_reset(mApexBase);
3193 } else {
3194 return C2_OMITTED;
3195 }
3196 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003197 if (mAidlBase) {
3198 ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
3199 return GetC2Status(transStatus, "reset");
3200 }
3201 Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08003202 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003203 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003204 return C2_TRANSACTION_FAILED;
3205 }
3206 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003207 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003208 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003209 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003210 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003211 return status;
3212}
3213
3214c2_status_t Codec2Client::Component::release() {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003215 if (mApexBase) {
3216 if (__builtin_available(android 36, *)) {
3217 return (c2_status_t)ApexCodec_Component_reset(mApexBase);
3218 } else {
3219 return C2_OMITTED;
3220 }
3221 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003222 if (mAidlBase) {
3223 ::ndk::ScopedAStatus transStatus = mAidlBase->release();
3224 return GetC2Status(transStatus, "release");
3225 }
3226 Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08003227 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003228 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003229 return C2_TRANSACTION_FAILED;
3230 }
3231 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003232 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003233 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003234 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003235 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08003236 return status;
3237}
3238
Pawin Vongmasabf69de92019-10-29 06:21:27 -07003239c2_status_t Codec2Client::Component::configureVideoTunnel(
3240 uint32_t avSyncHwId,
3241 native_handle_t** sidebandHandle) {
3242 *sidebandHandle = nullptr;
Wonsik Kimffc868e2024-11-25 18:18:38 +00003243 if (mApexBase) {
3244 // tunneling is not supported in APEX
3245 return C2_OMITTED;
3246 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003247 if (mAidlBase) {
3248 ::aidl::android::hardware::common::NativeHandle handle;
3249 ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
3250 c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
3251 if (status != C2_OK) {
3252 return status;
3253 }
3254 if (isAidlNativeHandleEmpty(handle)) {
3255 LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
3256 } else {
3257 *sidebandHandle = dupFromAidl(handle);
3258 }
3259 return C2_OK;
3260 }
3261 if (!mHidlBase1_1) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07003262 return C2_OMITTED;
3263 }
3264 c2_status_t status{};
Wonsik Kime8e98152022-12-16 16:04:17 -08003265 Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
Pawin Vongmasabf69de92019-10-29 06:21:27 -07003266 [&status, sidebandHandle](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003267 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07003268 status = static_cast<c2_status_t>(s);
3269 if (h.getNativeHandle()) {
3270 *sidebandHandle = native_handle_clone(h.getNativeHandle());
3271 }
3272 });
3273 if (!transStatus.isOk()) {
3274 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
3275 return C2_TRANSACTION_FAILED;
3276 }
3277 return status;
3278}
3279
Pawin Vongmasa36653902018-11-15 00:10:25 -08003280c2_status_t Codec2Client::Component::setOutputSurface(
3281 C2BlockPool::local_id_t blockPoolId,
3282 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07003283 uint32_t generation,
3284 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003285 if (mAidlBase) {
3286 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3287 mGraphicBufferAllocators->current();
3288 if (!gba) {
3289 LOG(ERROR) << "setOutputSurface for AIDL -- "
3290 "GraphicBufferAllocator was not created.";
3291 return C2_CORRUPTED;
3292 }
Sungtak Lee08b20b12024-08-21 18:33:08 +00003293 // Note: Consumer usage is set ahead of the HAL allocator(gba) being set.
3294 // This is same as HIDL.
3295 uint64_t consumerUsage = configConsumerUsage(surface);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003296 bool ret = gba->configure(surface, generation, maxDequeueCount);
Sungtak Lee08b20b12024-08-21 18:33:08 +00003297 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx",
3298 generation, (long long)consumerUsage);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003299 return ret ? C2_OK : C2_CORRUPTED;
3300 }
Sungtak Lee08515812019-06-05 11:16:32 -07003301 uint64_t bqId = 0;
3302 sp<IGraphicBufferProducer> nullIgbp;
3303 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08003304
Sungtak Lee08515812019-06-05 11:16:32 -07003305 sp<HGraphicBufferProducer2> igbp = surface ?
3306 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
3307 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08003308 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08003309 }
3310
Sungtak Leefb579022022-05-10 06:36:15 +00003311 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07003312 std::shared_ptr<SurfaceSyncObj> syncObj;
3313
Sungtak Lee08515812019-06-05 11:16:32 -07003314 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07003315 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07003316 } else if (surface->getUniqueId(&bqId) != OK) {
3317 LOG(ERROR) << "setOutputSurface -- "
3318 "cannot obtain bufferqueue id.";
3319 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07003320 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07003321 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08003322 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
3323 mHidlBase1_2 ? &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07003324 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08003325
Sungtak Lee08b20b12024-08-21 18:33:08 +00003326 uint64_t consumerUsage = configConsumerUsage(surface);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08003327 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
Sungtak Lee08b20b12024-08-21 18:33:08 +00003328 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07003329
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003330 Return<c2_hidl::Status> transStatus = syncObj ?
Wonsik Kime8e98152022-12-16 16:04:17 -08003331 mHidlBase1_2->setOutputSurfaceWithSyncObj(
Sungtak Leea714f112021-03-16 05:40:03 -07003332 static_cast<uint64_t>(blockPoolId),
3333 bqId == 0 ? nullHgbp : igbp, *syncObj) :
Wonsik Kime8e98152022-12-16 16:04:17 -08003334 mHidlBase1_0->setOutputSurface(
Sungtak Leea714f112021-03-16 05:40:03 -07003335 static_cast<uint64_t>(blockPoolId),
3336 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08003337
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00003338 mOutputBufferQueue->expireOldWaiters();
3339
Pawin Vongmasa36653902018-11-15 00:10:25 -08003340 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003341 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003342 return C2_TRANSACTION_FAILED;
3343 }
3344 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003345 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003346 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003347 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003348 }
Sungtak Leea714f112021-03-16 05:40:03 -07003349 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08003350 return status;
3351}
3352
3353status_t Codec2Client::Component::queueToOutputSurface(
3354 const C2ConstGraphicBlock& block,
3355 const QueueBufferInput& input,
3356 QueueBufferOutput* output) {
Arun Johnson7ba67072023-11-06 22:23:04 +00003357 ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003358 if (mAidlBase) {
3359 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3360 mGraphicBufferAllocators->current();
3361 if (gba) {
3362 return gba->displayBuffer(block, input, output);
3363 } else {
3364 return C2_NOT_FOUND;
3365 }
3366 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07003367 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08003368}
3369
Sungtak Lee08b20b12024-08-21 18:33:08 +00003370uint64_t Codec2Client::Component::configConsumerUsage(
3371 const sp<IGraphicBufferProducer>& surface) {
3372 // set consumer bits
3373 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
3374 // can be set atomically?
3375 uint64_t consumerUsage = kDefaultConsumerUsage;
3376 {
3377 if (surface) {
3378 uint64_t usage = 0;
3379 status_t err = surface->getConsumerUsage(&usage);
3380 if (err != NO_ERROR) {
3381 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
3382 err, asString(err));
3383 } else {
3384 // Note: we are adding the default usage because components must support
3385 // producing output frames that can be displayed an all output surfaces.
3386
3387 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
3388 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
3389 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
3390 // through the sideband channel.
3391
3392 consumerUsage = usage | kDefaultConsumerUsage;
3393 }
3394 }
3395
3396 C2StreamUsageTuning::output outputUsage{
3397 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
3398 std::vector<std::unique_ptr<C2SettingResult>> failures;
3399 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
3400 if (err != C2_OK) {
3401 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
3402 err, asString(err));
3403 }
3404 }
3405 return consumerUsage;
3406}
3407
Brian Lindahlc953b462023-01-27 16:21:43 -07003408void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003409 if (mAidlBase) {
3410 // TODO b/311348680
3411 return;
3412 }
Brian Lindahlc953b462023-01-27 16:21:43 -07003413 mOutputBufferQueue->pollForRenderedFrames(delta);
3414}
3415
Sungtak Leea714f112021-03-16 05:40:03 -07003416void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
3417 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003418 if (mAidlBase) {
3419 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3420 mGraphicBufferAllocators->current();
3421 if (gba) {
3422 gba->updateMaxDequeueBufferCount(maxDequeueCount);
3423 }
3424 return;
3425 }
Sungtak Leea714f112021-03-16 05:40:03 -07003426 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
3427}
3428
Sungtak Leec7da7a02022-05-05 08:45:33 +00003429void Codec2Client::Component::stopUsingOutputSurface(
3430 C2BlockPool::local_id_t blockPoolId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08003431 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003432 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3433 mGraphicBufferAllocators->current();
3434 if (gba) {
3435 gba->reset();
3436 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003437 return;
3438 }
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003439 std::scoped_lock lock(mOutputMutex);
3440 mOutputBufferQueue->stop();
Wonsik Kime8e98152022-12-16 16:04:17 -08003441 Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00003442 static_cast<uint64_t>(blockPoolId), nullptr);
3443 if (!transStatus.isOk()) {
3444 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
3445 } else {
3446 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003447 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00003448 if (status != C2_OK) {
3449 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
3450 << status << ".";
3451 }
3452 }
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00003453 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00003454}
3455
Sungtak Lee214ce612023-11-01 10:01:13 +00003456void Codec2Client::Component::onBufferReleasedFromOutputSurface(
3457 uint32_t generation) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003458 if (mAidlBase) {
3459 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3460 mGraphicBufferAllocators->current();
3461 if (gba) {
3462 gba->onBufferReleased(generation);
3463 }
3464 return;
3465 }
Sungtak Lee6700cc92023-11-22 18:04:05 +00003466 mOutputBufferQueue->onBufferReleased(generation);
Sungtak Lee214ce612023-11-01 10:01:13 +00003467}
3468
Sungtak Lee1720e4c2024-07-31 21:15:26 +00003469void Codec2Client::Component::onBufferAttachedToOutputSurface(
3470 uint32_t generation) {
3471 if (mAidlBase) {
3472 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3473 mGraphicBufferAllocators->current();
3474 if (gba) {
3475 gba->onBufferAttached(generation);
3476 }
3477 return;
3478 }
3479 mOutputBufferQueue->onBufferAttached(generation);
3480}
3481
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00003482void Codec2Client::Component::holdIgbaBlocks(
3483 const std::list<std::unique_ptr<C2Work>>& workList) {
3484 if (!mAidlBase) {
3485 return;
3486 }
3487 std::shared_ptr<AidlGraphicBufferAllocator> gba =
3488 mGraphicBufferAllocators->current();
3489 if (!gba) {
3490 return;
3491 }
3492 std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
3493 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
3494 for (const std::unique_ptr<C2Work>& work : workList) {
3495 if (!work) [[unlikely]] {
3496 continue;
3497 }
3498 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
3499 if (!worklet) {
3500 continue;
3501 }
3502 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
3503 if (buffer) {
3504 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
3505 std::shared_ptr<_C2BlockPoolData> poolData =
3506 _C2BlockFactory::GetGraphicBlockPoolData(block);
3507 _C2BlockFactory::RegisterIgba(poolData, igba);
3508 }
3509 }
3510 }
3511 }
3512 }
3513}
3514
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003515c2_status_t Codec2Client::Component::connectToInputSurface(
3516 const std::shared_ptr<InputSurface>& inputSurface,
3517 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003518 if (mApexBase) {
3519 // FIXME
3520 return C2_OMITTED;
3521 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003522 if (mAidlBase) {
3523 // FIXME
3524 return C2_OMITTED;
3525 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003526 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08003527 Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003528 inputSurface->mBase,
3529 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003530 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003531 status = static_cast<c2_status_t>(s);
3532 if (status != C2_OK) {
3533 LOG(DEBUG) << "connectToInputSurface -- call failed: "
3534 << status << ".";
3535 return;
3536 }
3537 *connection = std::make_shared<InputSurfaceConnection>(c);
3538 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08003539 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003540 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003541 return C2_TRANSACTION_FAILED;
3542 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003543 return status;
3544}
3545
3546c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08003547 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003548 const sp<HGraphicBufferSource>& source,
3549 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003550 if (mApexBase) {
3551 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
3552 return C2_OMITTED;
3553 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003554 if (mAidlBase) {
3555 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
3556 return C2_OMITTED;
3557 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003558 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08003559 Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003560 producer, source,
3561 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003562 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003563 status = static_cast<c2_status_t>(s);
3564 if (status != C2_OK) {
3565 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
3566 << status << ".";
3567 return;
3568 }
3569 *connection = std::make_shared<InputSurfaceConnection>(c);
3570 });
3571 if (!transStatus.isOk()) {
3572 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
3573 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08003574 }
3575 return status;
3576}
3577
3578c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kimffc868e2024-11-25 18:18:38 +00003579 if (mApexBase) {
3580 // FIXME
3581 return C2_OMITTED;
3582 }
Wonsik Kime8e98152022-12-16 16:04:17 -08003583 if (mAidlBase) {
3584 // FIXME
3585 return C2_OMITTED;
3586 }
3587 Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08003588 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003589 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003590 return C2_TRANSACTION_FAILED;
3591 }
3592 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003593 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003594 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003595 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
3596 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003597 }
3598 return status;
3599}
3600
Wonsik Kime8e98152022-12-16 16:04:17 -08003601Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
3602 // This object never gets destructed
3603 static AidlDeathManager *sManager = new AidlDeathManager();
3604 return sManager;
3605}
3606
Wonsik Kimffc868e2024-11-25 18:18:38 +00003607c2_status_t Codec2Client::Component::initApexHandler(
3608 const std::shared_ptr<Listener> &listener,
3609 const std::shared_ptr<Component> &comp) {
3610 if (!mApexBase) {
3611 return C2_BAD_STATE;
3612 }
3613 mApexHandler = std::make_unique<ApexHandler>(mApexBase, listener, comp);
3614 return C2_OK;
3615}
3616
Pawin Vongmasa36653902018-11-15 00:10:25 -08003617c2_status_t Codec2Client::Component::setDeathListener(
3618 const std::shared_ptr<Component>& component,
3619 const std::shared_ptr<Listener>& listener) {
3620
3621 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
3622 std::weak_ptr<Component> component;
3623 std::weak_ptr<Listener> base;
3624
3625 virtual void serviceDied(
3626 uint64_t /* cookie */,
3627 const wp<::android::hidl::base::V1_0::IBase>& /* who */
3628 ) override {
3629 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
3630 listener->onDeath(component);
3631 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003632 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003633 }
3634 }
3635 };
3636
Wonsik Kime8e98152022-12-16 16:04:17 -08003637 if (component->mAidlBase) {
3638 size_t seq;
3639 if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
3640 component->mAidlDeathSeq = seq;
3641 }
3642 return C2_OK;
3643 }
3644
Pawin Vongmasa36653902018-11-15 00:10:25 -08003645 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
3646 deathRecipient->base = listener;
3647 deathRecipient->component = component;
3648
3649 component->mDeathRecipient = deathRecipient;
Wonsik Kime8e98152022-12-16 16:04:17 -08003650 Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08003651 component->mDeathRecipient, 0);
3652 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003653 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003654 return C2_TRANSACTION_FAILED;
3655 }
3656 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003657 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08003658 return C2_CORRUPTED;
3659 }
3660 return C2_OK;
3661}
3662
3663// Codec2Client::InputSurface
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003664Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003665 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003666 [base]() -> sp<c2_hidl::IConfigurable> {
3667 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003668 base->getConfigurable();
3669 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003670 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003671 nullptr;
3672 }()
3673 },
3674 mBase{base},
3675 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08003676 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
3677 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003678 base->getGraphicBufferProducer();
3679 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08003680 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003681 nullptr;
3682 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08003683}
3684
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003685sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08003686 Codec2Client::InputSurface::getGraphicBufferProducer() const {
3687 return mGraphicBufferProducer;
3688}
3689
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003690sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08003691 return mBase;
3692}
3693
3694// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08003695Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003696 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003697 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003698 [base]() -> sp<c2_hidl::IConfigurable> {
3699 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003700 base->getConfigurable();
3701 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003702 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08003703 nullptr;
3704 }()
3705 },
3706 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08003707}
3708
3709c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08003710 Return<c2_hidl::Status> transResult = mBase->disconnect();
3711 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08003712}
3713
3714} // namespace android