blob: 6348e423d126c0e57d1950228d776449a51583b9 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002 * Copyright 2018 The Android Open Source Project
Pawin Vongmasa36653902018-11-15 00:10:25 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "Codec2Client"
Arun Johnson7ba67072023-11-06 22:23:04 +000019#define ATRACE_TAG ATRACE_TAG_VIDEO
Pawin Vongmasa1c75a232019-01-09 04:41:52 -080020#include <android-base/logging.h>
Arun Johnson7ba67072023-11-06 22:23:04 +000021#include <utils/Trace.h>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000022
23#include <codec2/aidl/GraphicBufferAllocator.h>
Sungtak Lee587aa322024-11-13 08:47:32 +000024#include <codec2/common/HalSelection.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <codec2/hidl/client.h>
Sungtak Lee587aa322024-11-13 08:47:32 +000026
Pawin Vongmasabf69de92019-10-29 06:21:27 -070027#include <C2Debug.h>
28#include <C2BufferPriv.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080029#include <C2Config.h> // for C2StreamUsageTuning
Pawin Vongmasabf69de92019-10-29 06:21:27 -070030#include <C2PlatformSupport.h>
31
32#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
33#include <android/hardware/media/c2/1.0/IComponent.h>
34#include <android/hardware/media/c2/1.0/IComponentInterface.h>
35#include <android/hardware/media/c2/1.0/IComponentListener.h>
36#include <android/hardware/media/c2/1.0/IComponentStore.h>
37#include <android/hardware/media/c2/1.0/IConfigurable.h>
38#include <android/hidl/manager/1.2/IServiceManager.h>
39
Wonsik Kime8e98152022-12-16 16:04:17 -080040#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
41#include <aidl/android/hardware/media/c2/BnComponentListener.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080042#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
43#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
44#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
45#include <aidl/android/hardware/media/c2/IComponent.h>
46#include <aidl/android/hardware/media/c2/IComponentInterface.h>
47#include <aidl/android/hardware/media/c2/IComponentStore.h>
48#include <aidl/android/hardware/media/c2/IConfigurable.h>
49#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080050#include <aidl/android/hardware/media/c2/StructDescriptor.h>
Wonsik Kimc8fc2c32022-12-12 14:43:00 -080051
Wonsik Kime8e98152022-12-16 16:04:17 -080052#include <aidlcommonsupport/NativeHandle.h>
Wonsik Kim138db0d2023-11-02 16:02:01 -070053#include <android/api-level.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080054#include <android/binder_auto_utils.h>
55#include <android/binder_ibinder.h>
56#include <android/binder_manager.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070057#include <android-base/properties.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080058#include <android-base/stringprintf.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070059#include <bufferpool/ClientManager.h>
Wonsik Kime8e98152022-12-16 16:04:17 -080060#include <bufferpool2/ClientManager.h>
61#include <codec2/aidl/BufferTypes.h>
Wonsik Kim1caded02022-12-09 13:03:11 -080062#include <codec2/aidl/ParamTypes.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070063#include <codec2/hidl/1.0/types.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070064#include <codec2/hidl/1.1/types.h>
Sungtak Lee8577dab2021-03-12 02:25:50 -080065#include <codec2/hidl/1.2/types.h>
Sungtak Leea714f112021-03-16 05:40:03 -070066#include <codec2/hidl/output.h>
Pawin Vongmasabf69de92019-10-29 06:21:27 -070067
68#include <cutils/native_handle.h>
69#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
70#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080071#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
Pawin Vongmasabf69de92019-10-29 06:21:27 -070072#include <hidl/HidlSupport.h>
Lajos Molnar78aa7c92021-02-18 21:39:01 -080073#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
74#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
Pawin Vongmasa36653902018-11-15 00:10:25 -080075
76#include <deque>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070077#include <iterator>
Pawin Vongmasa36653902018-11-15 00:10:25 -080078#include <limits>
79#include <map>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070080#include <mutex>
Sungtak Leeaa71b5c2023-11-04 09:21:15 +000081#include <optional>
Pawin Vongmasa892c81d2019-03-12 00:56:50 -070082#include <sstream>
83#include <thread>
Pawin Vongmasa36653902018-11-15 00:10:25 -080084#include <type_traits>
85#include <vector>
86
Pawin Vongmasa36653902018-11-15 00:10:25 -080087namespace android {
88
89using ::android::hardware::hidl_vec;
90using ::android::hardware::hidl_string;
91using ::android::hardware::Return;
92using ::android::hardware::Void;
Pawin Vongmasa36653902018-11-15 00:10:25 -080093
Pawin Vongmasaef939bf2019-03-03 04:44:59 -080094using HGraphicBufferProducer1 = ::android::hardware::graphics::bufferqueue::
95 V1_0::IGraphicBufferProducer;
96using HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
97 V2_0::IGraphicBufferProducer;
98using B2HGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
99 V2_0::utils::B2HGraphicBufferProducer;
100using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
101 V2_0::utils::H2BGraphicBufferProducer;
Sungtak Leea714f112021-03-16 05:40:03 -0700102using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
Pawin Vongmasaef939bf2019-03-03 04:44:59 -0800103
Sungtak Leeaa71b5c2023-11-04 09:21:15 +0000104using AidlGraphicBufferAllocator = ::aidl::android::hardware::media::c2::
105 implementation::GraphicBufferAllocator;
106
Wonsik Kime8e98152022-12-16 16:04:17 -0800107namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800108namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
109namespace c2_aidl = ::aidl::android::hardware::media::c2;
110namespace c2_hidl_base = ::android::hardware::media::c2;
111namespace c2_hidl = ::android::hardware::media::c2::V1_2;
112
113using c2_hidl::utils::operator<<;
114
Pawin Vongmasa36653902018-11-15 00:10:25 -0800115namespace /* unnamed */ {
116
117// c2_status_t value that corresponds to hwbinder transaction failure.
118constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
119
Lajos Molnar78aa7c92021-02-18 21:39:01 -0800120// By default prepare buffer to be displayed on any of the common surfaces
121constexpr uint64_t kDefaultConsumerUsage =
122 (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
123
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700124// Searches for a name in GetServiceNames() and returns the index found. If the
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700125// name is not found, the returned index will be equal to
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700126// GetServiceNames().size().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700127size_t getServiceIndex(char const* name) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700128 std::vector<std::string> const& names = Codec2Client::GetServiceNames();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700129 size_t i = 0;
130 for (; i < names.size(); ++i) {
131 if (name == names[i]) {
132 break;
133 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800134 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700135 return i;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800136}
137
Pawin Vongmasa83d2c552020-03-05 04:36:08 -0800138class Client2Store : public C2ComponentStore {
139 std::shared_ptr<Codec2Client> mClient;
140
141public:
142 Client2Store(std::shared_ptr<Codec2Client> const& client)
143 : mClient(client) { }
144
145 virtual ~Client2Store() = default;
146
147 virtual c2_status_t config_sm(
148 std::vector<C2Param*> const &params,
149 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
150 return mClient->config(params, C2_MAY_BLOCK, failures);
151 };
152
153 virtual c2_status_t copyBuffer(
154 std::shared_ptr<C2GraphicBuffer>,
155 std::shared_ptr<C2GraphicBuffer>) {
156 return C2_OMITTED;
157 }
158
159 virtual c2_status_t createComponent(
160 C2String, std::shared_ptr<C2Component>* const component) {
161 component->reset();
162 return C2_OMITTED;
163 }
164
165 virtual c2_status_t createInterface(
166 C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
167 interface->reset();
168 return C2_OMITTED;
169 }
170
171 virtual c2_status_t query_sm(
172 std::vector<C2Param*> const& stackParams,
173 std::vector<C2Param::Index> const& heapParamIndices,
174 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
175 return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
176 }
177
178 virtual c2_status_t querySupportedParams_nb(
179 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
180 return mClient->querySupportedParams(params);
181 }
182
183 virtual c2_status_t querySupportedValues_sm(
184 std::vector<C2FieldSupportedValuesQuery>& fields) const {
185 return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
186 }
187
188 virtual C2String getName() const {
189 return mClient->getName();
190 }
191
192 virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
193 return mClient->getParamReflector();
194 }
195
196 virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
197 return std::vector<std::shared_ptr<C2Component::Traits const>>();
198 }
199};
200
Wonsik Kime8e98152022-12-16 16:04:17 -0800201c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
202 if (!transStatus.isOk()) {
203 if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
204 c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
205 LOG(DEBUG) << method << " -- call failed: " << status << ".";
206 return status;
207 } else {
208 LOG(ERROR) << method << " -- transaction failed.";
209 return C2_TRANSACTION_FAILED;
210 }
211 }
212 return C2_OK;
213}
214
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700215} // unnamed namespace
216
217// This class caches a Codec2Client object and its component traits. The client
218// will be created the first time it is needed, and it can be refreshed if the
219// service dies (by calling invalidate()). The first time listComponents() is
220// called from the client, the result will be cached.
221class Codec2Client::Cache {
222 // Cached client
223 std::shared_ptr<Codec2Client> mClient;
224 mutable std::mutex mClientMutex;
225
226 // Cached component traits
227 std::vector<C2Component::Traits> mTraits;
228 std::once_flag mTraitsInitializationFlag;
229
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700230 // The index of the service. This is based on GetServiceNames().
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700231 size_t mIndex;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700232 // Called by s() exactly once to initialize the cache. The index must be a
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700233 // valid index into the vector returned by GetServiceNames(). Calling
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700234 // init(index) will associate the cache to the service with name
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700235 // GetServiceNames()[index].
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700236 void init(size_t index) {
237 mIndex = index;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700238 }
239
240public:
241 Cache() = default;
242
243 // Initializes mClient if needed, then returns mClient.
244 // If the service is unavailable but listed in the manifest, this function
245 // will block indefinitely.
246 std::shared_ptr<Codec2Client> getClient() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700247 std::scoped_lock lock{mClientMutex};
248 if (!mClient) {
249 mClient = Codec2Client::_CreateFromIndex(mIndex);
250 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -0700251 CHECK(mClient) << "Failed to create Codec2Client to service \""
252 << GetServiceNames()[mIndex] << "\". (Index = "
253 << mIndex << ").";
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700254 return mClient;
255 }
256
257 // Causes a subsequent call to getClient() to create a new client. This
258 // function should be called after the service dies.
259 //
260 // Note: This function is called only by ForAllServices().
261 void invalidate() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700262 std::scoped_lock lock{mClientMutex};
263 mClient = nullptr;
264 }
265
266 // Returns a list of traits for components supported by the service. This
267 // list is cached.
268 std::vector<C2Component::Traits> const& getTraits() {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700269 std::call_once(mTraitsInitializationFlag, [this]() {
270 bool success{false};
271 // Spin until _listComponents() is successful.
272 while (true) {
273 std::shared_ptr<Codec2Client> client = getClient();
274 mTraits = client->_listComponents(&success);
275 if (success) {
276 break;
277 }
Pawin Vongmasa21617db2020-04-24 06:16:42 -0700278 invalidate();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700279 using namespace std::chrono_literals;
280 static constexpr auto kServiceRetryPeriod = 5s;
281 LOG(INFO) << "Failed to retrieve component traits from service "
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700282 "\"" << GetServiceNames()[mIndex] << "\". "
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700283 "Retrying...";
284 std::this_thread::sleep_for(kServiceRetryPeriod);
285 }
286 });
287 return mTraits;
288 }
289
290 // List() returns the list of all caches.
291 static std::vector<Cache>& List() {
292 static std::vector<Cache> sCaches{[]() {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -0700293 size_t numServices = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -0700294 std::vector<Cache> caches(numServices);
295 for (size_t i = 0; i < numServices; ++i) {
296 caches[i].init(i);
297 }
298 return caches;
299 }()};
300 return sCaches;
301 }
302};
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800303// Codec2ConfigurableClient::HidlImpl
Pawin Vongmasa36653902018-11-15 00:10:25 -0800304
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800305struct Codec2ConfigurableClient::HidlImpl : public Codec2ConfigurableClient::ImplBase {
306 typedef c2_hidl::IConfigurable Base;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800308 // base cannot be null.
309 explicit HidlImpl(const sp<Base>& base);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800310
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800311 const C2String& getName() const override {
312 return mName;
313 }
314
315 c2_status_t query(
316 const std::vector<C2Param*>& stackParams,
317 const std::vector<C2Param::Index> &heapParamIndices,
318 c2_blocking_t mayBlock,
319 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
320
321 c2_status_t config(
322 const std::vector<C2Param*> &params,
323 c2_blocking_t mayBlock,
324 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
325
326 c2_status_t querySupportedParams(
327 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
328 ) const override;
329
330 c2_status_t querySupportedValues(
331 std::vector<C2FieldSupportedValuesQuery>& fields,
332 c2_blocking_t mayBlock) const override;
333
334private:
335 sp<Base> mBase;
336 const C2String mName;
337};
338
339Codec2ConfigurableClient::HidlImpl::HidlImpl(const sp<Base>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800340 : mBase{base},
341 mName{[base]() -> C2String {
342 C2String outName;
343 Return<void> transStatus = base->getName(
344 [&outName](const hidl_string& name) {
345 outName = name.c_str();
346 });
347 return transStatus.isOk() ? outName : "";
348 }()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349}
350
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800351c2_status_t Codec2ConfigurableClient::HidlImpl::query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800352 const std::vector<C2Param*> &stackParams,
353 const std::vector<C2Param::Index> &heapParamIndices,
354 c2_blocking_t mayBlock,
355 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800356 hidl_vec<c2_hidl::ParamIndex> indices(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800357 stackParams.size() + heapParamIndices.size());
358 size_t numIndices = 0;
359 for (C2Param* const& stackParam : stackParams) {
360 if (!stackParam) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800361 LOG(WARNING) << "query -- null stack param encountered.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 continue;
363 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800364 indices[numIndices++] = static_cast<c2_hidl::ParamIndex>(stackParam->index());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 }
366 size_t numStackIndices = numIndices;
367 for (const C2Param::Index& index : heapParamIndices) {
368 indices[numIndices++] =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800369 static_cast<c2_hidl::ParamIndex>(static_cast<uint32_t>(index));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800370 }
371 indices.resize(numIndices);
372 if (heapParams) {
373 heapParams->reserve(heapParams->size() + numIndices);
374 }
375 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800376 Return<void> transStatus = mBase->query(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 indices,
378 mayBlock == C2_MAY_BLOCK,
379 [&status, &numStackIndices, &stackParams, heapParams](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800380 c2_hidl::Status s, const c2_hidl::Params& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800381 status = static_cast<c2_status_t>(s);
382 if (status != C2_OK && status != C2_BAD_INDEX) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800383 LOG(DEBUG) << "query -- call failed: "
384 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800385 return;
386 }
387 std::vector<C2Param*> paramPointers;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800388 if (!c2_hidl::utils::parseParamsBlob(&paramPointers, p)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800389 LOG(ERROR) << "query -- error while parsing params.";
390 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800391 return;
392 }
393 size_t i = 0;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800394 for (auto it = paramPointers.begin();
395 it != paramPointers.end(); ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800396 C2Param* paramPointer = *it;
397 if (numStackIndices > 0) {
398 --numStackIndices;
399 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800400 LOG(WARNING) << "query -- null stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800401 ++it;
402 continue;
403 }
404 for (; i < stackParams.size() && !stackParams[i]; ) {
405 ++i;
406 }
407 if (i >= stackParams.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800408 LOG(ERROR) << "query -- unexpected error.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800409 status = C2_CORRUPTED;
410 return;
411 }
412 if (stackParams[i]->index() != paramPointer->index()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800413 LOG(WARNING) << "query -- param skipped: "
414 "index = "
415 << stackParams[i]->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800416 stackParams[i++]->invalidate();
417 continue;
418 }
419 if (!stackParams[i++]->updateFrom(*paramPointer)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800420 LOG(WARNING) << "query -- param update failed: "
421 "index = "
422 << paramPointer->index() << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800423 }
424 } else {
425 if (!paramPointer) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800426 LOG(WARNING) << "query -- null heap param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800427 ++it;
428 continue;
429 }
430 if (!heapParams) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800431 LOG(WARNING) << "query -- "
432 "unexpected extra stack param.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800434 heapParams->emplace_back(
435 C2Param::Copy(*paramPointer));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 }
437 }
438 ++it;
439 }
440 });
441 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800442 LOG(ERROR) << "query -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800443 return C2_TRANSACTION_FAILED;
444 }
445 return status;
446}
447
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800448c2_status_t Codec2ConfigurableClient::HidlImpl::config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 const std::vector<C2Param*> &params,
450 c2_blocking_t mayBlock,
451 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800452 c2_hidl::Params hidlParams;
453 if (!c2_hidl::utils::createParamsBlob(&hidlParams, params)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800454 LOG(ERROR) << "config -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800455 return C2_TRANSACTION_FAILED;
456 }
457 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800458 Return<void> transStatus = mBase->config(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459 hidlParams,
460 mayBlock == C2_MAY_BLOCK,
461 [&status, &params, failures](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800462 c2_hidl::Status s,
463 const hidl_vec<c2_hidl::SettingResult> f,
464 const c2_hidl::Params& o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800465 status = static_cast<c2_status_t>(s);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800466 if (status != C2_OK && status != C2_BAD_INDEX) {
467 LOG(DEBUG) << "config -- call failed: "
468 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 }
470 size_t i = failures->size();
471 failures->resize(i + f.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800472 for (const c2_hidl::SettingResult& sf : f) {
473 if (!c2_hidl::utils::objcpy(&(*failures)[i++], sf)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800474 LOG(ERROR) << "config -- "
475 << "invalid SettingResult returned.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800476 return;
477 }
478 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800479 if (!c2_hidl::utils::updateParamsFromBlob(params, o)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800480 LOG(ERROR) << "config -- "
481 << "failed to parse returned params.";
482 status = C2_CORRUPTED;
483 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800484 });
485 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800486 LOG(ERROR) << "config -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800487 return C2_TRANSACTION_FAILED;
488 }
489 return status;
490}
491
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800492c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800493 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
494 // TODO: Cache and query properly!
495 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800496 Return<void> transStatus = mBase->querySupportedParams(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497 std::numeric_limits<uint32_t>::min(),
498 std::numeric_limits<uint32_t>::max(),
499 [&status, params](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800500 c2_hidl::Status s,
501 const hidl_vec<c2_hidl::ParamDescriptor>& p) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800502 status = static_cast<c2_status_t>(s);
503 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800504 LOG(DEBUG) << "querySupportedParams -- call failed: "
505 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800506 return;
507 }
508 size_t i = params->size();
509 params->resize(i + p.size());
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800510 for (const c2_hidl::ParamDescriptor& sp : p) {
511 if (!c2_hidl::utils::objcpy(&(*params)[i++], sp)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800512 LOG(ERROR) << "querySupportedParams -- "
513 << "invalid returned ParamDescriptor.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800514 return;
515 }
516 }
517 });
518 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800519 LOG(ERROR) << "querySupportedParams -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800520 return C2_TRANSACTION_FAILED;
521 }
522 return status;
523}
524
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800525c2_status_t Codec2ConfigurableClient::HidlImpl::querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800526 std::vector<C2FieldSupportedValuesQuery>& fields,
527 c2_blocking_t mayBlock) const {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800528 hidl_vec<c2_hidl::FieldSupportedValuesQuery> inFields(fields.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800529 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800530 if (!c2_hidl::utils::objcpy(&inFields[i], fields[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800531 LOG(ERROR) << "querySupportedValues -- bad input";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800532 return C2_TRANSACTION_FAILED;
533 }
534 }
535
536 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800537 Return<void> transStatus = mBase->querySupportedValues(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 inFields,
539 mayBlock == C2_MAY_BLOCK,
540 [&status, &inFields, &fields](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800541 c2_hidl::Status s,
542 const hidl_vec<c2_hidl::FieldSupportedValuesQueryResult>& r) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800543 status = static_cast<c2_status_t>(s);
544 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800545 LOG(DEBUG) << "querySupportedValues -- call failed: "
546 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800547 return;
548 }
549 if (r.size() != fields.size()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800550 LOG(ERROR) << "querySupportedValues -- "
551 "input and output lists "
552 "have different sizes.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800553 status = C2_CORRUPTED;
554 return;
555 }
556 for (size_t i = 0; i < fields.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800557 if (!c2_hidl::utils::objcpy(&fields[i], inFields[i], r[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800558 LOG(ERROR) << "querySupportedValues -- "
559 "invalid returned value.";
560 status = C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800561 return;
562 }
563 }
564 });
565 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800566 LOG(ERROR) << "querySupportedValues -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800567 return C2_TRANSACTION_FAILED;
568 }
569 return status;
570}
571
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800572// Codec2ConfigurableClient::AidlImpl
573
574struct Codec2ConfigurableClient::AidlImpl : public Codec2ConfigurableClient::ImplBase {
575 typedef c2_aidl::IConfigurable Base;
576
577 // base cannot be null.
578 explicit AidlImpl(const std::shared_ptr<Base>& base);
579
580 const C2String& getName() const override {
581 return mName;
582 }
583
584 c2_status_t query(
585 const std::vector<C2Param*>& stackParams,
586 const std::vector<C2Param::Index> &heapParamIndices,
587 c2_blocking_t mayBlock,
588 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
589
590 c2_status_t config(
591 const std::vector<C2Param*> &params,
592 c2_blocking_t mayBlock,
593 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
594
595 c2_status_t querySupportedParams(
596 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
597 ) const override;
598
599 c2_status_t querySupportedValues(
600 std::vector<C2FieldSupportedValuesQuery>& fields,
601 c2_blocking_t mayBlock) const override;
602
603private:
604 std::shared_ptr<Base> mBase;
605 const C2String mName;
606};
607
608Codec2ConfigurableClient::AidlImpl::AidlImpl(const std::shared_ptr<Base>& base)
609 : mBase{base},
610 mName{[base]() -> C2String {
611 std::string outName;
612 ndk::ScopedAStatus status = base->getName(&outName);
613 return status.isOk() ? outName : "";
614 }()} {
615}
616
617c2_status_t Codec2ConfigurableClient::AidlImpl::query(
618 const std::vector<C2Param*> &stackParams,
619 const std::vector<C2Param::Index> &heapParamIndices,
620 c2_blocking_t mayBlock,
621 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800622 std::vector<int> indices(
623 stackParams.size() + heapParamIndices.size());
624 size_t numIndices = 0;
625 for (C2Param* const& stackParam : stackParams) {
626 if (!stackParam) {
627 LOG(WARNING) << "query -- null stack param encountered.";
628 continue;
629 }
630 indices[numIndices++] = int(stackParam->index());
631 }
632 size_t numStackIndices = numIndices;
633 for (const C2Param::Index& index : heapParamIndices) {
634 indices[numIndices++] = int(static_cast<uint32_t>(index));
635 }
636 indices.resize(numIndices);
637 if (heapParams) {
638 heapParams->reserve(heapParams->size() + numIndices);
639 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000640 c2_aidl::IConfigurable::QueryResult result;
Wonsik Kim1caded02022-12-09 13:03:11 -0800641 ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800642 c2_status_t status = GetC2Status(transStatus, "query");
643 if (status != C2_OK) {
644 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800645 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000646 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800647
Wonsik Kim1caded02022-12-09 13:03:11 -0800648 std::vector<C2Param*> paramPointers;
Sungtak Lee932255f2024-01-03 10:57:45 +0000649 if (!c2_aidl::utils::ParseParamsBlob(&paramPointers, result.params)) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800650 LOG(ERROR) << "query -- error while parsing params.";
651 return C2_CORRUPTED;
652 }
653 size_t i = 0;
Wonsik Kim095e72e2024-02-27 11:33:21 -0800654 size_t numQueried = 0;
Wonsik Kim977176c2023-12-18 17:14:20 -0800655 for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800656 C2Param* paramPointer = *it;
657 if (numStackIndices > 0) {
658 --numStackIndices;
659 if (!paramPointer) {
660 LOG(DEBUG) << "query -- null stack param.";
661 ++it;
662 continue;
663 }
664 for (; i < stackParams.size() && !stackParams[i]; ) {
665 ++i;
666 }
667 if (i >= stackParams.size()) {
668 LOG(ERROR) << "query -- unexpected error.";
669 status = C2_CORRUPTED;
670 break;
671 }
672 if (stackParams[i]->index() != paramPointer->index()) {
673 LOG(DEBUG) << "query -- param skipped: "
674 "index = "
675 << stackParams[i]->index() << ".";
676 stackParams[i++]->invalidate();
677 // this means that the param could not be queried.
678 // signalling C2_BAD_INDEX to the client.
679 status = C2_BAD_INDEX;
680 continue;
681 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800682 if (stackParams[i++]->updateFrom(*paramPointer)) {
Wonsik Kim095e72e2024-02-27 11:33:21 -0800683 ++numQueried;
Wonsik Kim977176c2023-12-18 17:14:20 -0800684 } else {
Wonsik Kim1caded02022-12-09 13:03:11 -0800685 LOG(WARNING) << "query -- param update failed: "
686 "index = "
687 << paramPointer->index() << ".";
688 }
689 } else {
690 if (!paramPointer) {
691 LOG(DEBUG) << "query -- null heap param.";
692 ++it;
693 continue;
694 }
695 if (!heapParams) {
696 LOG(WARNING) << "query -- "
697 "unexpected extra stack param.";
698 } else {
699 heapParams->emplace_back(C2Param::Copy(*paramPointer));
Wonsik Kim095e72e2024-02-27 11:33:21 -0800700 ++numQueried;
Wonsik Kim1caded02022-12-09 13:03:11 -0800701 }
702 }
703 ++it;
704 }
Wonsik Kim977176c2023-12-18 17:14:20 -0800705 if (status == C2_OK && indices.size() != numQueried) {
706 status = C2_BAD_INDEX;
707 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800708 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800709}
710
711c2_status_t Codec2ConfigurableClient::AidlImpl::config(
712 const std::vector<C2Param*> &params,
713 c2_blocking_t mayBlock,
714 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800715 c2_aidl::Params aidlParams;
716 if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
717 LOG(ERROR) << "config -- bad input.";
718 return C2_TRANSACTION_FAILED;
719 }
720 c2_aidl::IConfigurable::ConfigResult result;
721 ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800722 c2_status_t status = GetC2Status(transStatus, "config");
723 if (status != C2_OK) {
724 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800725 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000726 status = static_cast<c2_status_t>(result.status.status);
Wonsik Kim1caded02022-12-09 13:03:11 -0800727 size_t i = failures->size();
728 failures->resize(i + result.failures.size());
729 for (const c2_aidl::SettingResult& sf : result.failures) {
730 if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
731 LOG(ERROR) << "config -- invalid SettingResult returned.";
732 return C2_CORRUPTED;
733 }
734 }
735 if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
736 LOG(ERROR) << "config -- "
737 << "failed to parse returned params.";
738 status = C2_CORRUPTED;
739 }
740 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800741}
742
743c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
744 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800745 // TODO: Cache and query properly!
746 std::vector<c2_aidl::ParamDescriptor> result;
747 ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
748 std::numeric_limits<uint32_t>::min(),
749 std::numeric_limits<uint32_t>::max(),
750 &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800751 c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
752 if (status != C2_OK) {
753 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800754 }
Wonsik Kim1caded02022-12-09 13:03:11 -0800755 size_t i = params->size();
756 params->resize(i + result.size());
757 for (const c2_aidl::ParamDescriptor& sp : result) {
758 if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
759 LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
760 return C2_CORRUPTED;
761 }
762 }
763 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800764}
765
766c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
767 std::vector<C2FieldSupportedValuesQuery>& fields,
768 c2_blocking_t mayBlock) const {
Wonsik Kim1caded02022-12-09 13:03:11 -0800769 std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
770 for (size_t i = 0; i < fields.size(); ++i) {
771 if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
772 LOG(ERROR) << "querySupportedValues -- bad input";
773 return C2_TRANSACTION_FAILED;
774 }
775 }
776
Sungtak Lee932255f2024-01-03 10:57:45 +0000777 c2_aidl::IConfigurable::QuerySupportedValuesResult result;
778
Wonsik Kim1caded02022-12-09 13:03:11 -0800779 ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
780 inFields, (mayBlock == C2_MAY_BLOCK), &result);
Wonsik Kime8e98152022-12-16 16:04:17 -0800781 c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
782 if (status != C2_OK) {
783 return status;
Wonsik Kim1caded02022-12-09 13:03:11 -0800784 }
Sungtak Lee932255f2024-01-03 10:57:45 +0000785 status = static_cast<c2_status_t>(result.status.status);
786 if (result.values.size() != fields.size()) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800787 LOG(ERROR) << "querySupportedValues -- "
788 "input and output lists "
789 "have different sizes.";
790 return C2_CORRUPTED;
791 }
792 for (size_t i = 0; i < fields.size(); ++i) {
Sungtak Lee932255f2024-01-03 10:57:45 +0000793 if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result.values[i])) {
Wonsik Kim1caded02022-12-09 13:03:11 -0800794 LOG(ERROR) << "querySupportedValues -- "
795 "invalid returned value.";
796 return C2_CORRUPTED;
797 }
798 }
799 return status;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800800}
801
802// Codec2ConfigurableClient
803
804Codec2ConfigurableClient::Codec2ConfigurableClient(const sp<HidlBase> &hidlBase)
805 : mImpl(new Codec2ConfigurableClient::HidlImpl(hidlBase)) {
806}
807
808Codec2ConfigurableClient::Codec2ConfigurableClient(
809 const std::shared_ptr<AidlBase> &aidlBase)
810 : mImpl(new Codec2ConfigurableClient::AidlImpl(aidlBase)) {
811}
812
813const C2String& Codec2ConfigurableClient::getName() const {
814 return mImpl->getName();
815}
816
817c2_status_t Codec2ConfigurableClient::query(
818 const std::vector<C2Param*>& stackParams,
819 const std::vector<C2Param::Index> &heapParamIndices,
820 c2_blocking_t mayBlock,
821 std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
822 return mImpl->query(stackParams, heapParamIndices, mayBlock, heapParams);
823}
824
825c2_status_t Codec2ConfigurableClient::config(
826 const std::vector<C2Param*> &params,
827 c2_blocking_t mayBlock,
828 std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
829 return mImpl->config(params, mayBlock, failures);
830}
831
832c2_status_t Codec2ConfigurableClient::querySupportedParams(
833 std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
834 return mImpl->querySupportedParams(params);
835}
836
837c2_status_t Codec2ConfigurableClient::querySupportedValues(
838 std::vector<C2FieldSupportedValuesQuery>& fields,
839 c2_blocking_t mayBlock) const {
840 return mImpl->querySupportedValues(fields, mayBlock);
841}
842
843
Pawin Vongmasa36653902018-11-15 00:10:25 -0800844// Codec2Client::Component::HidlListener
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800845struct Codec2Client::Component::HidlListener : public c2_hidl::IComponentListener {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800846 std::weak_ptr<Component> component;
847 std::weak_ptr<Listener> base;
848
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800849 virtual Return<void> onWorkDone(const c2_hidl::WorkBundle& workBundle) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800850 std::list<std::unique_ptr<C2Work>> workItems;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800851 if (!c2_hidl::utils::objcpy(&workItems, workBundle)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800852 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800853 return Void();
854 }
855 // release input buffers potentially held by the component from queue
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800856 std::shared_ptr<Codec2Client::Component> strongComponent =
857 component.lock();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800858 if (strongComponent) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800859 strongComponent->handleOnWorkDone(workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800860 }
861 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
Wonsik Kimab34ed62019-01-31 15:28:46 -0800862 listener->onWorkDone(component, workItems);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800863 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800864 LOG(DEBUG) << "onWorkDone -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800865 }
866 return Void();
867 }
868
869 virtual Return<void> onTripped(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800870 const hidl_vec<c2_hidl::SettingResult>& settingResults) override {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800871 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
872 settingResults.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800873 for (size_t i = 0; i < settingResults.size(); ++i) {
874 std::unique_ptr<C2SettingResult> c2SettingResult;
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800875 if (!c2_hidl::utils::objcpy(&c2SettingResult, settingResults[i])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800876 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877 return Void();
878 }
879 c2SettingResults[i] = std::move(c2SettingResult);
880 }
881 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
882 listener->onTripped(component, c2SettingResults);
883 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800884 LOG(DEBUG) << "onTripped -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800885 }
886 return Void();
887 }
888
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800889 virtual Return<void> onError(c2_hidl::Status s, uint32_t errorCode) override {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800890 LOG(DEBUG) << "onError --"
891 << " status = " << s
892 << ", errorCode = " << errorCode
893 << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800894 if (std::shared_ptr<Listener> listener = base.lock()) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -0800895 listener->onError(component, s == c2_hidl::Status::OK ?
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896 errorCode : static_cast<c2_status_t>(s));
897 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800898 LOG(DEBUG) << "onError -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -0800899 }
900 return Void();
901 }
902
903 virtual Return<void> onFramesRendered(
904 const hidl_vec<RenderedFrame>& renderedFrames) override {
905 std::shared_ptr<Listener> listener = base.lock();
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800906 if (!listener) {
907 LOG(DEBUG) << "onFramesRendered -- listener died.";
908 return Void();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800909 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800910 for (const RenderedFrame& renderedFrame : renderedFrames) {
911 listener->onFrameRendered(
912 renderedFrame.bufferQueueId,
913 renderedFrame.slotId,
914 renderedFrame.timestampNs);
915 }
916 return Void();
917 }
918
919 virtual Return<void> onInputBuffersReleased(
920 const hidl_vec<InputBuffer>& inputBuffers) override {
921 std::shared_ptr<Listener> listener = base.lock();
922 if (!listener) {
923 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
924 return Void();
925 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800926 for (const InputBuffer& inputBuffer : inputBuffers) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800927 LOG(VERBOSE) << "onInputBuffersReleased --"
928 " received death notification of"
929 " input buffer:"
930 " frameIndex = " << inputBuffer.frameIndex
931 << ", bufferIndex = " << inputBuffer.arrayIndex
932 << ".";
Wonsik Kimab34ed62019-01-31 15:28:46 -0800933 listener->onInputBufferDone(
934 inputBuffer.frameIndex, inputBuffer.arrayIndex);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800935 }
936 return Void();
937 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -0800938
Pawin Vongmasa36653902018-11-15 00:10:25 -0800939};
940
Wonsik Kime8e98152022-12-16 16:04:17 -0800941// Codec2Client::Component::AidlListener
942struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
943 std::weak_ptr<Component> component;
944 std::weak_ptr<Listener> base;
945
946 virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
947 std::list<std::unique_ptr<C2Work>> workItems;
948 if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
949 LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
950 return ::ndk::ScopedAStatus::ok();
951 }
952 // release input buffers potentially held by the component from queue
953 std::shared_ptr<Codec2Client::Component> strongComponent =
954 component.lock();
955 if (strongComponent) {
956 strongComponent->handleOnWorkDone(workItems);
957 }
958 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
959 listener->onWorkDone(component, workItems);
960 } else {
961 LOG(DEBUG) << "onWorkDone -- listener died.";
962 }
963 return ::ndk::ScopedAStatus::ok();
964 }
965
966 virtual ::ndk::ScopedAStatus onTripped(
967 const std::vector<c2_aidl::SettingResult>& settingResults) override {
968 std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
969 settingResults.size());
970 for (size_t i = 0; i < settingResults.size(); ++i) {
971 std::unique_ptr<C2SettingResult> c2SettingResult;
972 if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
973 LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
974 return ::ndk::ScopedAStatus::ok();
975 }
976 c2SettingResults[i] = std::move(c2SettingResult);
977 }
978 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
979 listener->onTripped(component, c2SettingResults);
980 } else {
981 LOG(DEBUG) << "onTripped -- listener died.";
982 }
983 return ::ndk::ScopedAStatus::ok();
984 }
985
986 virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
987 LOG(DEBUG) << "onError --"
988 << " status = " << s.status
989 << ", errorCode = " << errorCode
990 << ".";
991 if (std::shared_ptr<Listener> listener = base.lock()) {
992 listener->onError(component, s.status == c2_aidl::Status::OK ?
993 errorCode : static_cast<c2_status_t>(s.status));
994 } else {
995 LOG(DEBUG) << "onError -- listener died.";
996 }
997 return ::ndk::ScopedAStatus::ok();
998 }
999
1000 virtual ::ndk::ScopedAStatus onFramesRendered(
1001 const std::vector<RenderedFrame>& renderedFrames) override {
1002 std::shared_ptr<Listener> listener = base.lock();
1003 if (!listener) {
1004 LOG(DEBUG) << "onFramesRendered -- listener died.";
1005 return ::ndk::ScopedAStatus::ok();
1006 }
1007 for (const RenderedFrame& renderedFrame : renderedFrames) {
1008 listener->onFrameRendered(
1009 renderedFrame.bufferQueueId,
1010 renderedFrame.slotId,
1011 renderedFrame.timestampNs);
1012 }
1013 return ::ndk::ScopedAStatus::ok();
1014 }
1015
1016 virtual ::ndk::ScopedAStatus onInputBuffersReleased(
1017 const std::vector<InputBuffer>& inputBuffers) override {
1018 std::shared_ptr<Listener> listener = base.lock();
1019 if (!listener) {
1020 LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
1021 return ::ndk::ScopedAStatus::ok();
1022 }
1023 for (const InputBuffer& inputBuffer : inputBuffers) {
1024 LOG(VERBOSE) << "onInputBuffersReleased --"
1025 " received death notification of"
1026 " input buffer:"
1027 " frameIndex = " << inputBuffer.frameIndex
1028 << ", bufferIndex = " << inputBuffer.arrayIndex
1029 << ".";
1030 listener->onInputBufferDone(
1031 inputBuffer.frameIndex, inputBuffer.arrayIndex);
1032 }
1033 return ::ndk::ScopedAStatus::ok();
1034 }
1035
1036};
1037
1038// Codec2Client::Component::HidlBufferPoolSender
1039struct Codec2Client::Component::HidlBufferPoolSender :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001040 hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
Wonsik Kime8e98152022-12-16 16:04:17 -08001041 HidlBufferPoolSender()
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001042 : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
1043 }
1044};
1045
Wonsik Kime8e98152022-12-16 16:04:17 -08001046// Codec2Client::Component::AidlBufferPoolSender
1047struct Codec2Client::Component::AidlBufferPoolSender :
1048 c2_aidl::utils::DefaultBufferPoolSender {
1049 AidlBufferPoolSender()
1050 : c2_aidl::utils::DefaultBufferPoolSender() {
1051 }
1052};
1053
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001054// Codec2Client::Component::OutputBufferQueue
1055struct Codec2Client::Component::OutputBufferQueue :
Sungtak Leea714f112021-03-16 05:40:03 -07001056 hardware::media::c2::OutputBufferQueue {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001057 OutputBufferQueue()
Sungtak Leea714f112021-03-16 05:40:03 -07001058 : hardware::media::c2::OutputBufferQueue() {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001059 }
1060};
1061
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001062// The class holds GraphicBufferAllocator and the associated id of
1063// HAL side BlockPool.
1064// This is tightly coupled with BlockPool creation and destruction.
1065// The life cycle inside class will be as follows.
1066//
1067// On createBlockPool client request.
1068// 1. this::create() creates a GraphicBufferAllocator and set it as
1069// the current.
1070// 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
1071// the GraphicBufferAllocator created in #1.
1072// 3. this::setCurrentId() associates the id returned in #2 to the current
1073//
1074// On destroyBlockPool cliet request
1075// 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
1076// from HAL process.
1077// 2. this::remove() destroys GraphicBufferAllocator which is associatted
1078// with the C2BlockPool in #1.
1079//
1080struct Codec2Client::Component::GraphicBufferAllocators {
1081private:
1082 std::optional<C2BlockPool::local_id_t> mCurrentId;
1083 std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
1084
1085 // A new BlockPool is created before the old BlockPool is destroyed.
1086 // This holds the reference of the old BlockPool when a new BlockPool is
1087 // created until the old BlockPool is explicitly requested for destruction.
1088 std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
1089 std::mutex mMutex;
1090
1091public:
1092 // Creates a GraphicBufferAllocator which will be passed to HAL
1093 // for creating C2BlockPool. And the created GraphicBufferAllocator
1094 // will be used afterwards by current().
1095 std::shared_ptr<AidlGraphicBufferAllocator> create() {
1096 std::unique_lock<std::mutex> l(mMutex);
1097 if (mCurrent) {
1098 // If this is not stopped.
1099 mCurrent->reset();
1100 if (mCurrentId.has_value()) {
1101 mOlds.emplace(mCurrentId.value(), mCurrent);
1102 }
1103 mCurrentId.reset();
1104 mCurrent.reset();
1105 }
1106 // TODO: integrate initial value with CCodec/CCodecBufferChannel
1107 mCurrent =
1108 AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
1109 ALOGD("GraphicBufferAllocator created");
1110 return mCurrent;
1111 }
1112
1113 // Associates the blockpool Id returned from HAL to the
1114 // current GraphicBufferAllocator.
1115 void setCurrentId(C2BlockPool::local_id_t id) {
1116 std::unique_lock<std::mutex> l(mMutex);
1117 CHECK(!mCurrentId.has_value());
1118 mCurrentId = id;
1119 }
1120
1121 // Returns the current GraphicBufferAllocator.
1122 std::shared_ptr<AidlGraphicBufferAllocator> current() {
1123 std::unique_lock<std::mutex> l(mMutex);
1124 return mCurrent;
1125 }
1126
1127 // Removes the GraphicBufferAllocator associated with given \p id.
1128 void remove(C2BlockPool::local_id_t id) {
1129 std::unique_lock<std::mutex> l(mMutex);
1130 mOlds.erase(id);
1131 if (mCurrentId == id) {
1132 if (mCurrent) {
1133 mCurrent->reset();
1134 mCurrent.reset();
1135 }
1136 mCurrentId.reset();
1137 }
1138 }
1139};
1140
Pawin Vongmasa36653902018-11-15 00:10:25 -08001141// Codec2Client
Wonsik Kime8e98152022-12-16 16:04:17 -08001142Codec2Client::Codec2Client(sp<HidlBase> const& base,
Sungtak Leef4b39512023-05-10 07:17:22 +00001143 sp<c2_hidl::IConfigurable> const& configurable,
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001144 size_t serviceIndex)
Sungtak Leef4b39512023-05-10 07:17:22 +00001145 : Configurable{configurable},
Wonsik Kime8e98152022-12-16 16:04:17 -08001146 mHidlBase1_0{base},
1147 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1148 mHidlBase1_2{HidlBase1_2::castFrom(base)},
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001149 mServiceIndex{serviceIndex} {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001150 Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
Pawin Vongmasa36653902018-11-15 00:10:25 -08001151 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001152 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001153 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08001154 mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001155 }
1156}
1157
Wonsik Kime8e98152022-12-16 16:04:17 -08001158Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
1159 std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
1160 size_t serviceIndex)
1161 : Configurable{configurable},
1162 mAidlBase{base},
1163 mServiceIndex{serviceIndex} {
1164 ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
1165 if (!transStatus.isOk()) {
1166 LOG(ERROR) << "getPoolClientManager -- transaction failed.";
1167 mAidlHostPoolManager.reset();
1168 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001169}
1170
Wonsik Kime8e98152022-12-16 16:04:17 -08001171sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
1172 return mHidlBase1_0;
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001173}
1174
Wonsik Kime8e98152022-12-16 16:04:17 -08001175sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
1176 return mHidlBase1_0;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001177}
1178
Wonsik Kime8e98152022-12-16 16:04:17 -08001179sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
1180 return mHidlBase1_1;
1181}
1182
1183sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
1184 return mHidlBase1_2;
1185}
1186
1187::ndk::SpAIBinder Codec2Client::getAidlBase() const {
1188 return mAidlBase ? mAidlBase->asBinder() : nullptr;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001189}
1190
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001191std::string const& Codec2Client::getServiceName() const {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001192 return GetServiceNames()[mServiceIndex];
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001193}
1194
Pawin Vongmasa36653902018-11-15 00:10:25 -08001195c2_status_t Codec2Client::createComponent(
1196 const C2String& name,
1197 const std::shared_ptr<Codec2Client::Listener>& listener,
1198 std::shared_ptr<Codec2Client::Component>* const component) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001199 if (mAidlBase) {
1200 std::shared_ptr<Component::AidlListener> aidlListener =
1201 Component::AidlListener::make<Component::AidlListener>();
1202 aidlListener->base = listener;
1203 std::shared_ptr<c2_aidl::IComponent> aidlComponent;
1204 ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
1205 name,
1206 aidlListener,
1207 bufferpool2_aidl::implementation::ClientManager::getInstance(),
1208 &aidlComponent);
1209 c2_status_t status = GetC2Status(transStatus, "createComponent");
1210 if (status != C2_OK) {
1211 return status;
1212 } else if (!aidlComponent) {
1213 LOG(ERROR) << "createComponent(" << name.c_str()
1214 << ") -- null component.";
1215 return C2_CORRUPTED;
1216 }
1217 *component = std::make_shared<Codec2Client::Component>(aidlComponent);
1218 status = (*component)->setDeathListener((*component), listener);
1219 if (status != C2_OK) {
1220 LOG(ERROR) << "createComponent(" << name.c_str()
1221 << ") -- failed to set up death listener: "
1222 << status << ".";
1223 }
1224 (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00001225 aidlListener->component = *component;
Wonsik Kime8e98152022-12-16 16:04:17 -08001226 return status;
1227 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001228
Pawin Vongmasa36653902018-11-15 00:10:25 -08001229 c2_status_t status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001230 sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001231 hidlListener->base = listener;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001232 Return<void> transStatus;
Wonsik Kime8e98152022-12-16 16:04:17 -08001233 if (mHidlBase1_2) {
1234 transStatus = mHidlBase1_2->createComponent_1_2(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001235 name,
1236 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001237 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasa36653902018-11-15 00:10:25 -08001238 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001239 c2_hidl::Status s,
1240 const sp<c2_hidl::IComponent>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001241 status = static_cast<c2_status_t>(s);
1242 if (status != C2_OK) {
1243 return;
1244 }
1245 *component = std::make_shared<Codec2Client::Component>(c);
1246 hidlListener->component = *component;
Sungtak Lee8577dab2021-03-12 02:25:50 -08001247 });
1248 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001249 else if (mHidlBase1_1) {
1250 transStatus = mHidlBase1_1->createComponent_1_1(
Sungtak Lee8577dab2021-03-12 02:25:50 -08001251 name,
1252 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001253 bufferpool_hidl::implementation::ClientManager::getInstance(),
Sungtak Lee8577dab2021-03-12 02:25:50 -08001254 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001255 c2_hidl::Status s,
1256 const sp<c2_hidl_base::V1_1::IComponent>& c) {
Sungtak Lee8577dab2021-03-12 02:25:50 -08001257 status = static_cast<c2_status_t>(s);
1258 if (status != C2_OK) {
1259 return;
1260 }
1261 *component = std::make_shared<Codec2Client::Component>(c);
1262 hidlListener->component = *component;
1263 });
Wonsik Kime8e98152022-12-16 16:04:17 -08001264 } else if (mHidlBase1_0) { // ver1_0
1265 transStatus = mHidlBase1_0->createComponent(
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001266 name,
1267 hidlListener,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001268 bufferpool_hidl::implementation::ClientManager::getInstance(),
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001269 [&status, component, hidlListener](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001270 c2_hidl::Status s,
1271 const sp<c2_hidl_base::V1_0::IComponent>& c) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001272 status = static_cast<c2_status_t>(s);
1273 if (status != C2_OK) {
1274 return;
1275 }
1276 *component = std::make_shared<Codec2Client::Component>(c);
1277 hidlListener->component = *component;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001278 });
Sungtak Lee8577dab2021-03-12 02:25:50 -08001279 } else {
1280 status = C2_CORRUPTED;
1281 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001282 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001283 LOG(ERROR) << "createComponent(" << name.c_str()
1284 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001285 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001286 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001287 if (status == C2_NOT_FOUND) {
1288 LOG(VERBOSE) << "createComponent(" << name.c_str()
1289 << ") -- component not found.";
1290 } else {
1291 LOG(ERROR) << "createComponent(" << name.c_str()
1292 << ") -- call failed: " << status << ".";
1293 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001294 return status;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001295 } else if (!*component) {
1296 LOG(ERROR) << "createComponent(" << name.c_str()
1297 << ") -- null component.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001298 return C2_CORRUPTED;
1299 }
1300
1301 status = (*component)->setDeathListener(*component, listener);
1302 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001303 LOG(ERROR) << "createComponent(" << name.c_str()
1304 << ") -- failed to set up death listener: "
1305 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001306 }
1307
Wonsik Kime8e98152022-12-16 16:04:17 -08001308 (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001309 return status;
1310}
1311
1312c2_status_t Codec2Client::createInterface(
1313 const C2String& name,
1314 std::shared_ptr<Codec2Client::Interface>* const interface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001315 if (mAidlBase) {
1316 std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
1317 ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
1318 name,
1319 &aidlInterface);
1320 c2_status_t status = GetC2Status(transStatus, "createInterface");
1321 if (status != C2_OK) {
1322 return status;
1323 } else if (!aidlInterface) {
1324 LOG(ERROR) << "createInterface(" << name.c_str()
1325 << ") -- null interface.";
1326 return C2_CORRUPTED;
1327 }
1328 interface->reset(new Codec2Client::Interface(aidlInterface));
1329 return C2_OK;
1330 }
1331
Pawin Vongmasa36653902018-11-15 00:10:25 -08001332 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001333 Return<void> transStatus = mHidlBase1_0->createInterface(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001334 name,
1335 [&status, interface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001336 c2_hidl::Status s,
1337 const sp<c2_hidl::IComponentInterface>& i) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001338 status = static_cast<c2_status_t>(s);
1339 if (status != C2_OK) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001340 return;
1341 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001342 *interface = std::make_shared<Interface>(i);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001343 });
1344 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001345 LOG(ERROR) << "createInterface(" << name.c_str()
1346 << ") -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001347 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001348 } else if (status != C2_OK) {
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001349 if (status == C2_NOT_FOUND) {
1350 LOG(VERBOSE) << "createInterface(" << name.c_str()
1351 << ") -- component not found.";
1352 } else {
1353 LOG(ERROR) << "createInterface(" << name.c_str()
1354 << ") -- call failed: " << status << ".";
1355 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001356 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001357 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001358
Pawin Vongmasa36653902018-11-15 00:10:25 -08001359 return status;
1360}
1361
1362c2_status_t Codec2Client::createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001363 std::shared_ptr<InputSurface>* const inputSurface) {
Wonsik Kime8e98152022-12-16 16:04:17 -08001364 if (mAidlBase) {
1365 // FIXME
1366 return C2_OMITTED;
1367 }
1368
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001369 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08001370 Return<void> transStatus = mHidlBase1_0->createInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001371 [&status, inputSurface](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001372 c2_hidl::Status s,
1373 const sp<c2_hidl::IInputSurface>& i) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001374 status = static_cast<c2_status_t>(s);
1375 if (status != C2_OK) {
1376 return;
1377 }
1378 *inputSurface = std::make_shared<InputSurface>(i);
1379 });
1380 if (!transStatus.isOk()) {
1381 LOG(ERROR) << "createInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001382 return C2_TRANSACTION_FAILED;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001383 } else if (status != C2_OK) {
1384 LOG(DEBUG) << "createInputSurface -- call failed: "
1385 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001386 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001387 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001388}
1389
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001390std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
1391 return Cache::List()[mServiceIndex].getTraits();
1392}
1393
1394std::vector<C2Component::Traits> Codec2Client::_listComponents(
1395 bool* success) const {
1396 std::vector<C2Component::Traits> traits;
1397 std::string const& serviceName = getServiceName();
Wonsik Kime8e98152022-12-16 16:04:17 -08001398
1399 if (mAidlBase) {
1400 std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
1401 ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
1402 if (!transStatus.isOk()) {
1403 LOG(ERROR) << "_listComponents -- transaction failed.";
1404 *success = false;
1405 } else {
1406 traits.resize(aidlTraits.size());
1407 *success = true;
1408 for (size_t i = 0; i < aidlTraits.size(); ++i) {
1409 if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
1410 LOG(ERROR) << "_listComponents -- corrupted output.";
1411 *success = false;
1412 traits.clear();
1413 break;
1414 }
1415 traits[i].owner = serviceName;
1416 }
1417 }
1418 return traits;
1419 }
1420 Return<void> transStatus = mHidlBase1_0->listComponents(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001421 [&traits, &serviceName](c2_hidl::Status s,
1422 const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
1423 if (s != c2_hidl::Status::OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001424 LOG(DEBUG) << "_listComponents -- call failed: "
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001425 << static_cast<c2_status_t>(s) << ".";
1426 return;
1427 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001428 traits.resize(t.size());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001429 for (size_t i = 0; i < t.size(); ++i) {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001430 if (!c2_hidl::utils::objcpy(&traits[i], t[i])) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001431 LOG(ERROR) << "_listComponents -- corrupted output.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001432 return;
1433 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001434 traits[i].owner = serviceName;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001435 }
1436 });
1437 if (!transStatus.isOk()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001438 LOG(ERROR) << "_listComponents -- transaction failed.";
1439 *success = false;
1440 } else {
1441 *success = true;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001442 }
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001443 return traits;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001444}
1445
1446c2_status_t Codec2Client::copyBuffer(
1447 const std::shared_ptr<C2Buffer>& src,
1448 const std::shared_ptr<C2Buffer>& dst) {
1449 // TODO: Implement?
1450 (void)src;
1451 (void)dst;
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001452 LOG(ERROR) << "copyBuffer not implemented";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001453 return C2_OMITTED;
1454}
1455
Wonsik Kime8e98152022-12-16 16:04:17 -08001456std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001457 // TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
1458 // should reflect the HAL API.
Wonsik Kime8e98152022-12-16 16:04:17 -08001459 struct HidlSimpleParamReflector : public C2ParamReflector {
1460 std::unique_ptr<C2StructDescriptor> describe(
1461 C2Param::CoreIndex coreIndex) const override {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001462 hidl_vec<c2_hidl::ParamIndex> indices(1);
1463 indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001464 std::unique_ptr<C2StructDescriptor> descriptor;
1465 Return<void> transStatus = mBase->getStructDescriptors(
1466 indices,
1467 [&descriptor](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001468 c2_hidl::Status s,
1469 const hidl_vec<c2_hidl::StructDescriptor>& sd) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001470 c2_status_t status = static_cast<c2_status_t>(s);
1471 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001472 LOG(DEBUG) << "SimpleParamReflector -- "
1473 "getStructDescriptors() failed: "
1474 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001475 descriptor.reset();
1476 return;
1477 }
1478 if (sd.size() != 1) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001479 LOG(DEBUG) << "SimpleParamReflector -- "
1480 "getStructDescriptors() "
1481 "returned vector of size "
1482 << sd.size() << ". "
1483 "It should be 1.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001484 descriptor.reset();
1485 return;
1486 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001487 if (!c2_hidl::utils::objcpy(&descriptor, sd[0])) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001488 LOG(DEBUG) << "SimpleParamReflector -- "
1489 "getStructDescriptors() returned "
1490 "corrupted data.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001491 descriptor.reset();
1492 return;
1493 }
1494 });
Wonsik Kim492fecd2020-11-19 11:14:11 -08001495 if (!transStatus.isOk()) {
1496 LOG(DEBUG) << "SimpleParamReflector -- transaction failed: "
1497 << transStatus.description();
1498 descriptor.reset();
1499 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001500 return descriptor;
1501 }
1502
Wonsik Kime8e98152022-12-16 16:04:17 -08001503 HidlSimpleParamReflector(sp<HidlBase> base)
Pawin Vongmasa36653902018-11-15 00:10:25 -08001504 : mBase(base) { }
1505
Wonsik Kime8e98152022-12-16 16:04:17 -08001506 sp<HidlBase> mBase;
1507 };
1508 struct AidlSimpleParamReflector : public C2ParamReflector {
1509 std::unique_ptr<C2StructDescriptor> describe(
1510 C2Param::CoreIndex coreIndex) const override {
1511 std::vector<c2_aidl::StructDescriptor> aidlDesc;
1512 std::unique_ptr<C2StructDescriptor> descriptor;
1513 ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
1514 {int32_t(coreIndex.coreIndex())},
1515 &aidlDesc);
1516 c2_status_t status = GetC2Status(transStatus, "describe");
1517 if (status != C2_OK) {
1518 descriptor.reset();
1519 } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
1520 LOG(ERROR) << "describe -- conversion failed.";
1521 descriptor.reset();
1522 }
1523 return descriptor;
1524 }
1525
1526 AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
1527 : mBase(base) { }
1528
1529 std::shared_ptr<AidlBase> mBase;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001530 };
1531
Wonsik Kime8e98152022-12-16 16:04:17 -08001532 if (mAidlBase) {
1533 return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
1534 }
1535 return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001536};
1537
Wonsik Kime8e98152022-12-16 16:04:17 -08001538std::vector<std::string> Codec2Client::CacheServiceNames() {
1539 std::vector<std::string> names;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001540
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001541 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001542 if (__builtin_available(android __ANDROID_API_S__, *)) {
1543 // Get AIDL service names
1544 AServiceManager_forEachDeclaredInstance(
1545 AidlBase::descriptor, &names, [](const char *name, void *context) {
1546 std::vector<std::string> *names = (std::vector<std::string> *)context;
1547 names->emplace_back(name);
1548 });
1549 } else {
1550 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
1551 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001552 } else {
1553 // Get HIDL service names
1554 using ::android::hardware::media::c2::V1_0::IComponentStore;
1555 using ::android::hidl::manager::V1_2::IServiceManager;
1556 while (true) {
1557 sp<IServiceManager> serviceManager = IServiceManager::getService();
1558 CHECK(serviceManager) << "Hardware service manager is not running.";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001559
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001560 Return<void> transResult;
1561 transResult = serviceManager->listManifestByInterface(
1562 IComponentStore::descriptor,
1563 [&names](
1564 hidl_vec<hidl_string> const& instanceNames) {
1565 names.insert(names.end(), instanceNames.begin(), instanceNames.end());
1566 });
1567 if (transResult.isOk()) {
1568 break;
1569 }
1570 LOG(ERROR) << "Could not retrieve the list of service instances of "
1571 << IComponentStore::descriptor
1572 << ". Retrying...";
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001573 }
Wonsik Kime8e98152022-12-16 16:04:17 -08001574 }
1575 // Sort service names in each category.
1576 std::stable_sort(
1577 names.begin(), names.end(),
1578 [](const std::string &a, const std::string &b) {
1579 // First compare by prefix: default -> vendor -> {everything else}
1580 constexpr int DEFAULT = 1;
1581 constexpr int VENDOR = 2;
1582 constexpr int OTHER = 3;
1583 int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
1584 (a.compare(0, 6, "vendor") == 0) ? VENDOR :
1585 OTHER);
1586 int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
1587 (b.compare(0, 6, "vendor") == 0) ? VENDOR :
1588 OTHER);
1589 if (aPrefix != bPrefix) {
1590 return aPrefix < bPrefix;
1591 }
1592 // If the prefix is the same, compare alphabetically
1593 return a < b;
1594 });
1595
1596 // Summarize to logcat.
1597 if (names.empty()) {
1598 LOG(INFO) << "No Codec2 services declared in the manifest.";
1599 } else {
1600 std::stringstream stringOutput;
1601 stringOutput << "Available Codec2 services:";
1602 for (std::string const& name : names) {
1603 stringOutput << " \"" << name << "\"";
1604 }
1605 LOG(INFO) << stringOutput.str();
1606 }
1607
1608 return names;
1609}
1610
1611std::vector<std::string> const& Codec2Client::GetServiceNames() {
1612 static std::vector<std::string> sServiceNames = CacheServiceNames();
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001613 return sServiceNames;
1614}
1615
Pawin Vongmasa36653902018-11-15 00:10:25 -08001616std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001617 const char* name,
1618 bool setAsPreferredCodec2ComponentStore) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001619 size_t index = getServiceIndex(name);
Pawin Vongmasa83d2c552020-03-05 04:36:08 -08001620 if (index == GetServiceNames().size()) {
1621 if (setAsPreferredCodec2ComponentStore) {
1622 LOG(WARNING) << "CreateFromService(" << name
1623 << ") -- preferred C2ComponentStore not set.";
1624 }
1625 return nullptr;
1626 }
1627 std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
1628 if (setAsPreferredCodec2ComponentStore) {
1629 SetPreferredCodec2ComponentStore(
1630 std::make_shared<Client2Store>(client));
1631 LOG(INFO) << "CreateFromService(" << name
1632 << ") -- service set as preferred C2ComponentStore.";
1633 }
1634 return client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001635}
1636
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001637std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
1638 CreateFromAllServices() {
1639 std::vector<std::shared_ptr<Codec2Client>> clients(
1640 GetServiceNames().size());
1641 for (size_t i = GetServiceNames().size(); i > 0; ) {
1642 --i;
1643 clients[i] = _CreateFromIndex(i);
1644 }
1645 return clients;
1646}
1647
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001648std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001649 std::string const& name = GetServiceNames()[index];
Pawin Vongmasa9aac3042020-03-05 02:30:32 -08001650 LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
Wonsik Kime8e98152022-12-16 16:04:17 -08001651
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001652 if (c2_aidl::utils::IsSelected()) {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001653 if (__builtin_available(android __ANDROID_API_S__, *)) {
1654 std::string instanceName =
1655 ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
1656 if (AServiceManager_isDeclared(instanceName.c_str())) {
1657 std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
1658 ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
1659 CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
1660 " inaccessible for unknown reasons.";
1661 LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
1662 std::shared_ptr<c2_aidl::IConfigurable> configurable;
1663 ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
1664 CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
1665 "does not have IConfigurable.";
1666 return std::make_shared<Codec2Client>(baseStore, configurable, index);
1667 } else {
1668 LOG(ERROR) << "Codec2 AIDL service \"" << name << "\" is not declared";
1669 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001670 } else {
Wonsik Kim138db0d2023-11-02 16:02:01 -07001671 LOG(FATAL) << "C2 AIDL cannot be selected on Android version older than 35";
Wonsik Kime8e98152022-12-16 16:04:17 -08001672 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001673 } else {
1674 std::string instanceName = "android.hardware.media.c2/" + name;
1675 sp<HidlBase> baseStore = HidlBase::getService(name);
1676 CHECK(baseStore) << "Codec2 service \"" << name << "\""
1677 " inaccessible for unknown reasons.";
1678 LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
1679 Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
1680 CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
1681 "does not have IConfigurable.";
1682 sp<c2_hidl::IConfigurable> configurable =
1683 static_cast<sp<c2_hidl::IConfigurable>>(transResult);
1684 return std::make_shared<Codec2Client>(baseStore, configurable, index);
Wonsik Kime8e98152022-12-16 16:04:17 -08001685 }
Wonsik Kimb613d4b2023-09-01 14:01:36 -07001686 return nullptr;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001687}
1688
1689c2_status_t Codec2Client::ForAllServices(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001690 const std::string &key,
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001691 size_t numberOfAttempts,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001692 std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
1693 predicate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001694 c2_status_t status = C2_NO_INIT; // no IComponentStores present
1695
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001696 // Cache the mapping key -> index of Codec2Client in Cache::List().
Pawin Vongmasa36653902018-11-15 00:10:25 -08001697 static std::mutex key2IndexMutex;
1698 static std::map<std::string, size_t> key2Index;
1699
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001700 // By default try all stores. However, try the last known client first. If
1701 // the last known client fails, retry once. We do this by pushing the last
1702 // known client in front of the list of all clients.
Pawin Vongmasa36653902018-11-15 00:10:25 -08001703 std::deque<size_t> indices;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001704 for (size_t index = Cache::List().size(); index > 0; ) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001705 indices.push_front(--index);
1706 }
1707
1708 bool wasMapped = false;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001709 {
1710 std::scoped_lock lock{key2IndexMutex};
1711 auto it = key2Index.find(key);
1712 if (it != key2Index.end()) {
1713 indices.push_front(it->second);
1714 wasMapped = true;
1715 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001716 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001717
1718 for (size_t index : indices) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001719 Cache& cache = Cache::List()[index];
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001720 for (size_t tries = numberOfAttempts; tries > 0; --tries) {
1721 std::shared_ptr<Codec2Client> client{cache.getClient()};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001722 status = predicate(client);
1723 if (status == C2_OK) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001724 std::scoped_lock lock{key2IndexMutex};
Pawin Vongmasa36653902018-11-15 00:10:25 -08001725 key2Index[key] = index; // update last known client index
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001726 return C2_OK;
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001727 } else if (status == C2_NO_MEMORY) {
1728 return C2_NO_MEMORY;
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001729 } else if (status == C2_TRANSACTION_FAILED) {
1730 LOG(WARNING) << "\"" << key << "\" failed for service \""
1731 << client->getName()
1732 << "\" due to transaction failure. "
1733 << "(Service may have crashed.)"
1734 << (tries > 1 ? " Retrying..." : "");
1735 cache.invalidate();
1736 continue;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001737 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001738 if (wasMapped) {
1739 LOG(INFO) << "\"" << key << "\" became invalid in service \""
1740 << client->getName() << "\". Retrying...";
1741 wasMapped = false;
1742 }
1743 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001744 }
1745 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001746 return status; // return the last status from a valid client
Pawin Vongmasa36653902018-11-15 00:10:25 -08001747}
1748
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001749c2_status_t Codec2Client::CreateComponentByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001750 const char* componentName,
1751 const std::shared_ptr<Listener>& listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001752 std::shared_ptr<Component>* component,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001753 std::shared_ptr<Codec2Client>* owner,
1754 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001755 std::string key{"create:"};
1756 key.append(componentName);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001757 c2_status_t status = ForAllServices(
1758 key,
1759 numberOfAttempts,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001760 [owner, component, componentName, &listener](
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001761 const std::shared_ptr<Codec2Client> &client)
1762 -> c2_status_t {
1763 c2_status_t status = client->createComponent(componentName,
1764 listener,
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001765 component);
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001766 if (status == C2_OK) {
1767 if (owner) {
1768 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001769 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001770 } else if (status != C2_NOT_FOUND) {
1771 LOG(DEBUG) << "IComponentStore("
1772 << client->getServiceName()
1773 << ")::createComponent(\"" << componentName
1774 << "\") returned status = "
1775 << status << ".";
1776 }
1777 return status;
1778 });
1779 if (status != C2_OK) {
1780 LOG(DEBUG) << "Failed to create component \"" << componentName
1781 << "\" from all known services. "
1782 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001783 }
Chih-Yu Huangb8fe0792020-12-07 17:14:55 +09001784 return status;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001785}
1786
Wonsik Kime8e98152022-12-16 16:04:17 -08001787std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
Pawin Vongmasa36653902018-11-15 00:10:25 -08001788 const char* interfaceName,
Pawin Vongmasa23c90c82019-09-03 00:44:42 -07001789 std::shared_ptr<Codec2Client>* owner,
1790 size_t numberOfAttempts) {
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001791 std::string key{"create:"};
1792 key.append(interfaceName);
1793 std::shared_ptr<Interface> interface;
1794 c2_status_t status = ForAllServices(
1795 key,
1796 numberOfAttempts,
1797 [owner, &interface, interfaceName](
1798 const std::shared_ptr<Codec2Client> &client)
1799 -> c2_status_t {
1800 c2_status_t status = client->createInterface(interfaceName,
1801 &interface);
1802 if (status == C2_OK) {
1803 if (owner) {
1804 *owner = client;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001805 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001806 } else if (status != C2_NOT_FOUND) {
1807 LOG(DEBUG) << "IComponentStore("
1808 << client->getServiceName()
1809 << ")::createInterface(\"" << interfaceName
1810 << "\") returned status = "
1811 << status << ".";
1812 }
1813 return status;
1814 });
1815 if (status != C2_OK) {
1816 LOG(DEBUG) << "Failed to create interface \"" << interfaceName
1817 << "\" from all known services. "
1818 "Last returned status = " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08001819 }
Pawin Vongmasa1e7015a2019-10-09 02:15:50 -07001820 return interface;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001821}
1822
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001823std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
1824 static std::vector<C2Component::Traits> sList{[]() {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001825 std::vector<C2Component::Traits> list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001826 for (Cache& cache : Cache::List()) {
1827 std::vector<C2Component::Traits> const& traits = cache.getTraits();
1828 list.insert(list.end(), traits.begin(), traits.end());
Pawin Vongmasa36653902018-11-15 00:10:25 -08001829 }
1830 return list;
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001831 }()};
1832 return sList;
1833}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001834
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001835std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
1836 char const* serviceName) {
Sungtak Lee587aa322024-11-13 08:47:32 +00001837 if (!IsCodec2AidlInputSurfaceSelected()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001838 return nullptr;
1839 }
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001840 size_t index = GetServiceNames().size();
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001841 if (serviceName) {
1842 index = getServiceIndex(serviceName);
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001843 if (index == GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001844 LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
1845 << serviceName << "\"";
1846 }
1847 }
1848
1849 std::shared_ptr<Codec2Client::InputSurface> inputSurface;
Pawin Vongmasa270dd6a2019-04-06 04:41:15 -07001850 if (index != GetServiceNames().size()) {
Pawin Vongmasa892c81d2019-03-12 00:56:50 -07001851 std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
1852 if (client->createInputSurface(&inputSurface) == C2_OK) {
1853 return inputSurface;
1854 }
1855 }
1856 LOG(INFO) << "CreateInputSurface -- attempting to create an input surface "
1857 "from all services...";
1858 for (Cache& cache : Cache::List()) {
1859 std::shared_ptr<Codec2Client> client = cache.getClient();
1860 if (client->createInputSurface(&inputSurface) == C2_OK) {
1861 LOG(INFO) << "CreateInputSurface -- input surface obtained from "
1862 "service \"" << client->getServiceName() << "\"";
1863 return inputSurface;
1864 }
1865 }
1866 LOG(WARNING) << "CreateInputSurface -- failed to create an input surface "
1867 "from all services";
1868 return nullptr;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001869}
1870
Sungtak Lee92bca442024-03-12 09:10:31 +00001871bool Codec2Client::IsAidlSelected() {
1872 return c2_aidl::utils::IsSelected();
1873}
1874
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001875// Codec2Client::Interface
Wonsik Kime8e98152022-12-16 16:04:17 -08001876Codec2Client::Interface::Interface(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001877 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001878 [base]() -> sp<c2_hidl::IConfigurable> {
1879 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001880 base->getConfigurable();
1881 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001882 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001883 nullptr;
1884 }()
1885 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001886 mHidlBase{base} {
1887}
1888
1889Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
1890 : Configurable{
1891 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
1892 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
1893 ::ndk::ScopedAStatus transStatus =
1894 base->getConfigurable(&aidlConfigurable);
1895 return transStatus.isOk() ? aidlConfigurable : nullptr;
1896 }()
1897 },
1898 mAidlBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08001899}
1900
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001901// Codec2Client::Component
Wonsik Kime8e98152022-12-16 16:04:17 -08001902
1903class Codec2Client::Component::AidlDeathManager {
1904public:
1905 AidlDeathManager()
1906 : mSeq(0),
1907 mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
1908 }
1909
1910 ~AidlDeathManager() = default;
1911
1912 bool linkToDeath(
1913 const std::shared_ptr<Component> &comp,
1914 const std::shared_ptr<Listener> &listener,
1915 size_t *seqPtr) {
1916 std::unique_lock lock(mMutex);
1917 size_t seq = mSeq++;
1918 if (!mMap.try_emplace(seq, comp, listener).second) {
1919 return false;
1920 }
1921 if (STATUS_OK != AIBinder_linkToDeath(
1922 comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
1923 mMap.erase(seq);
1924 return false;
1925 }
1926 *seqPtr = seq;
1927 return true;
1928 }
1929
1930 void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
1931 std::unique_lock lock(mMutex);
1932 AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
1933 mMap.erase(seq);
1934 }
1935
1936private:
1937 std::mutex mMutex;
1938 size_t mSeq;
1939 typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
1940 std::map<size_t, Context> mMap;
1941 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
1942
1943 bool extractContext(size_t seq, Context *context) {
1944 std::unique_lock lock(mMutex);
1945 auto node = mMap.extract(seq);
1946 if (!node) {
1947 return false;
1948 }
1949 *context = node.mapped();
1950 return true;
1951 }
1952
1953 static void OnBinderDied(void *cookie) {
1954 size_t seq = size_t(cookie);
1955 Context context;
1956 if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
1957 return;
1958 }
1959 std::weak_ptr<Component> weakComponent;
1960 std::weak_ptr<Listener> weakListener;
1961 std::tie(weakComponent, weakListener) = context;
1962 if (std::shared_ptr<Listener> listener = weakListener.lock()) {
1963 listener->onDeath(weakComponent);
1964 } else {
1965 LOG(DEBUG) << "onDeath -- listener died.";
1966 }
1967 }
1968};
1969
1970Codec2Client::Component::Component(const sp<HidlBase>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001971 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001972 [base]() -> sp<c2_hidl::IConfigurable> {
1973 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001974 base->getInterface();
1975 if (!transResult1.isOk()) {
1976 return nullptr;
1977 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001978 Return<sp<c2_hidl::IConfigurable>> transResult2 =
1979 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001980 getConfigurable();
1981 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001982 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08001983 nullptr;
1984 }()
1985 },
Wonsik Kime8e98152022-12-16 16:04:17 -08001986 mHidlBase1_0{base},
1987 mHidlBase1_1{HidlBase1_1::castFrom(base)},
1988 mHidlBase1_2{HidlBase1_2::castFrom(base)},
1989 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001990 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
1991}
1992
Wonsik Kime8e98152022-12-16 16:04:17 -08001993Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001994 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08001995 [base]() -> sp<c2_hidl::IConfigurable> {
1996 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Pawin Vongmasabf69de92019-10-29 06:21:27 -07001997 base->getInterface();
1998 if (!transResult1.isOk()) {
1999 return nullptr;
2000 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002001 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2002 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002003 getConfigurable();
2004 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002005 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002006 nullptr;
2007 }()
2008 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002009 mHidlBase1_0{base},
2010 mHidlBase1_1{base},
2011 mHidlBase1_2{HidlBase1_2::castFrom(base)},
2012 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
Sungtak Lee8577dab2021-03-12 02:25:50 -08002013 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2014}
2015
Wonsik Kime8e98152022-12-16 16:04:17 -08002016Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
Sungtak Lee8577dab2021-03-12 02:25:50 -08002017 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002018 [base]() -> sp<c2_hidl::IConfigurable> {
2019 Return<sp<c2_hidl::IComponentInterface>> transResult1 =
Sungtak Lee8577dab2021-03-12 02:25:50 -08002020 base->getInterface();
2021 if (!transResult1.isOk()) {
2022 return nullptr;
2023 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002024 Return<sp<c2_hidl::IConfigurable>> transResult2 =
2025 static_cast<sp<c2_hidl::IComponentInterface>>(transResult1)->
Sungtak Lee8577dab2021-03-12 02:25:50 -08002026 getConfigurable();
2027 return transResult2.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002028 static_cast<sp<c2_hidl::IConfigurable>>(transResult2) :
Sungtak Lee8577dab2021-03-12 02:25:50 -08002029 nullptr;
2030 }()
2031 },
Wonsik Kime8e98152022-12-16 16:04:17 -08002032 mHidlBase1_0{base},
2033 mHidlBase1_1{base},
2034 mHidlBase1_2{base},
2035 mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
2036 mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
2037}
2038
2039Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
2040 : Configurable{
2041 [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
2042 std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
2043 ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
2044 if (!transStatus.isOk()) {
2045 return nullptr;
2046 }
2047 std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
2048 transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
2049 return transStatus.isOk() ? aidlConfigurable : nullptr;
2050 }()
2051 },
2052 mAidlBase{base},
2053 mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002054 mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002055}
2056
2057Codec2Client::Component::~Component() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002058 if (mAidlDeathSeq) {
2059 GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
2060 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002061}
2062
2063c2_status_t Codec2Client::Component::createBlockPool(
2064 C2Allocator::id_t id,
2065 C2BlockPool::local_id_t* blockPoolId,
2066 std::shared_ptr<Codec2Client::Configurable>* configurable) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002067 if (mAidlBase) {
2068 c2_aidl::IComponent::BlockPool aidlBlockPool;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002069 c2_status_t status = C2_OK;
2070
2071 // TODO: Temporary mapping for the current CCodecBufferChannel.
2072 // Handle this properly and remove this temporary allocator mapping.
2073 id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
2074 C2PlatformAllocatorStore::IGBA : id;
2075
Sungtak Leefffb5692024-01-18 11:22:38 +00002076 c2_aidl::IComponent::BlockPoolAllocator allocator;
2077 allocator.allocatorId = id;
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002078 if (id == C2PlatformAllocatorStore::IGBA) {
2079 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2080 mGraphicBufferAllocators->create();
2081 ::ndk::ScopedFileDescriptor waitableFd;
2082 ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
2083 status = GetC2Status(ret, "Gba::getWaitableFd");
2084 if (status != C2_OK) {
2085 return status;
2086 }
Sungtak Leefffb5692024-01-18 11:22:38 +00002087 c2_aidl::IComponent::GbAllocator gbAllocator;
2088 gbAllocator.waitableFd = std::move(waitableFd);
2089 gbAllocator.igba =
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002090 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
Sungtak Leefffb5692024-01-18 11:22:38 +00002091 allocator.gbAllocator = std::move(gbAllocator);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002092 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
2093 allocator, &aidlBlockPool);
2094 status = GetC2Status(transStatus, "createBlockPool");
2095 if (status != C2_OK) {
2096 return status;
2097 }
2098 mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
2099 } else {
2100 ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
Sungtak Leefffb5692024-01-18 11:22:38 +00002101 allocator, &aidlBlockPool);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002102 status = GetC2Status(transStatus, "createBlockPool");
2103 if (status != C2_OK) {
2104 return status;
2105 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002106 }
2107 *blockPoolId = aidlBlockPool.blockPoolId;
2108 *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
2109 return C2_OK;
2110 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002111 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002112 Return<void> transStatus = mHidlBase1_0->createBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002113 static_cast<uint32_t>(id),
2114 [&status, blockPoolId, configurable](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002115 c2_hidl::Status s,
Pawin Vongmasa36653902018-11-15 00:10:25 -08002116 uint64_t pId,
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002117 const sp<c2_hidl::IConfigurable>& c) {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002118 status = static_cast<c2_status_t>(s);
2119 configurable->reset();
2120 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002121 LOG(DEBUG) << "createBlockPool -- call failed: "
2122 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002123 return;
2124 }
2125 *blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002126 *configurable = std::make_shared<Configurable>(c);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002127 });
2128 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002129 LOG(ERROR) << "createBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002130 return C2_TRANSACTION_FAILED;
2131 }
2132 return status;
2133}
2134
2135c2_status_t Codec2Client::Component::destroyBlockPool(
2136 C2BlockPool::local_id_t localId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002137 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002138 mGraphicBufferAllocators->remove(localId);
Wonsik Kime8e98152022-12-16 16:04:17 -08002139 ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
2140 return GetC2Status(transStatus, "destroyBlockPool");
2141 }
2142 Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002143 static_cast<uint64_t>(localId));
2144 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002145 LOG(ERROR) << "destroyBlockPool -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002146 return C2_TRANSACTION_FAILED;
2147 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002148 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002149}
2150
Wonsik Kimab34ed62019-01-31 15:28:46 -08002151void Codec2Client::Component::handleOnWorkDone(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002152 const std::list<std::unique_ptr<C2Work>> &workItems) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002153 if (mAidlBase) {
2154 holdIgbaBlocks(workItems);
2155 } else {
2156 // Output bufferqueue-based blocks' lifetime management
2157 mOutputBufferQueue->holdBufferQueueBlocks(workItems);
2158 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002159}
2160
2161c2_status_t Codec2Client::Component::queue(
2162 std::list<std::unique_ptr<C2Work>>* const items) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002163 if (mAidlBase) {
2164 c2_aidl::WorkBundle workBundle;
2165 if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
2166 LOG(ERROR) << "queue -- bad input.";
2167 return C2_TRANSACTION_FAILED;
2168 }
2169 ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
2170 return GetC2Status(transStatus, "queue");
2171 }
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002172 c2_hidl::WorkBundle workBundle;
Wonsik Kime8e98152022-12-16 16:04:17 -08002173 if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002174 LOG(ERROR) << "queue -- bad input.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002175 return C2_TRANSACTION_FAILED;
2176 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002177 Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002178 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002179 LOG(ERROR) << "queue -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002180 return C2_TRANSACTION_FAILED;
2181 }
2182 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002183 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002184 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002185 LOG(DEBUG) << "queue -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002186 }
2187 return status;
2188}
2189
2190c2_status_t Codec2Client::Component::flush(
2191 C2Component::flush_mode_t mode,
2192 std::list<std::unique_ptr<C2Work>>* const flushedWork) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002193 (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
2194 c2_status_t status = C2_OK;
2195 if (mAidlBase) {
2196 c2_aidl::WorkBundle workBundle;
2197 ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
2198 c2_status_t status = GetC2Status(transStatus, "flush");
2199 if (status != C2_OK) {
2200 return status;
2201 }
2202 if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
2203 LOG(DEBUG) << "flush -- flushedWork corrupted.";
2204 return C2_CORRUPTED;
2205 }
2206 } else {
2207 Return<void> transStatus = mHidlBase1_0->flush(
2208 [&status, flushedWork](
2209 c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
2210 status = static_cast<c2_status_t>(s);
2211 if (status != C2_OK) {
2212 LOG(DEBUG) << "flush -- call failed: " << status << ".";
2213 return;
2214 }
2215 if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
2216 status = C2_CORRUPTED;
2217 } else {
2218 status = C2_OK;
2219 }
2220 });
2221 if (!transStatus.isOk()) {
2222 LOG(ERROR) << "flush -- transaction failed.";
2223 return C2_TRANSACTION_FAILED;
2224 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002225 }
2226
2227 // Indices of flushed work items.
2228 std::vector<uint64_t> flushedIndices;
2229 for (const std::unique_ptr<C2Work> &work : *flushedWork) {
2230 if (work) {
2231 if (work->worklets.empty()
2232 || !work->worklets.back()
2233 || (work->worklets.back()->output.flags &
2234 C2FrameData::FLAG_INCOMPLETE) == 0) {
2235 // input is complete
2236 flushedIndices.emplace_back(
2237 work->input.ordinal.frameIndex.peeku());
2238 }
2239 }
2240 }
2241
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002242 if (mAidlBase) {
2243 holdIgbaBlocks(*flushedWork);
2244 } else {
2245 // Output bufferqueue-based blocks' lifetime management
2246 mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
2247 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002248
2249 return status;
2250}
2251
2252c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002253 if (mAidlBase) {
2254 ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
2255 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2256 return GetC2Status(transStatus, "drain");
2257 }
2258 Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002259 mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
2260 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002261 LOG(ERROR) << "drain -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002262 return C2_TRANSACTION_FAILED;
2263 }
2264 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002265 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002266 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002267 LOG(DEBUG) << "drain -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002268 }
2269 return status;
2270}
2271
2272c2_status_t Codec2Client::Component::start() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002273 if (mAidlBase) {
2274 ::ndk::ScopedAStatus transStatus = mAidlBase->start();
2275 return GetC2Status(transStatus, "start");
2276 }
2277 Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002278 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002279 LOG(ERROR) << "start -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002280 return C2_TRANSACTION_FAILED;
2281 }
2282 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002283 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002284 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002285 LOG(DEBUG) << "start -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002286 }
2287 return status;
2288}
2289
2290c2_status_t Codec2Client::Component::stop() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002291 if (mAidlBase) {
2292 ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
2293 return GetC2Status(transStatus, "stop");
2294 }
2295 Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002296 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002297 LOG(ERROR) << "stop -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002298 return C2_TRANSACTION_FAILED;
2299 }
2300 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002301 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002302 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002303 LOG(DEBUG) << "stop -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002304 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002305 return status;
2306}
2307
2308c2_status_t Codec2Client::Component::reset() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002309 if (mAidlBase) {
2310 ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
2311 return GetC2Status(transStatus, "reset");
2312 }
2313 Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002314 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002315 LOG(ERROR) << "reset -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002316 return C2_TRANSACTION_FAILED;
2317 }
2318 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002319 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002320 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002321 LOG(DEBUG) << "reset -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002322 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002323 return status;
2324}
2325
2326c2_status_t Codec2Client::Component::release() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002327 if (mAidlBase) {
2328 ::ndk::ScopedAStatus transStatus = mAidlBase->release();
2329 return GetC2Status(transStatus, "release");
2330 }
2331 Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002332 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002333 LOG(ERROR) << "release -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002334 return C2_TRANSACTION_FAILED;
2335 }
2336 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002337 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002338 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002339 LOG(DEBUG) << "release -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002340 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08002341 return status;
2342}
2343
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002344c2_status_t Codec2Client::Component::configureVideoTunnel(
2345 uint32_t avSyncHwId,
2346 native_handle_t** sidebandHandle) {
2347 *sidebandHandle = nullptr;
Wonsik Kime8e98152022-12-16 16:04:17 -08002348 if (mAidlBase) {
2349 ::aidl::android::hardware::common::NativeHandle handle;
2350 ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
2351 c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
2352 if (status != C2_OK) {
2353 return status;
2354 }
2355 if (isAidlNativeHandleEmpty(handle)) {
2356 LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
2357 } else {
2358 *sidebandHandle = dupFromAidl(handle);
2359 }
2360 return C2_OK;
2361 }
2362 if (!mHidlBase1_1) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002363 return C2_OMITTED;
2364 }
2365 c2_status_t status{};
Wonsik Kime8e98152022-12-16 16:04:17 -08002366 Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002367 [&status, sidebandHandle](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002368 c2_hidl::Status s, hardware::hidl_handle const& h) {
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002369 status = static_cast<c2_status_t>(s);
2370 if (h.getNativeHandle()) {
2371 *sidebandHandle = native_handle_clone(h.getNativeHandle());
2372 }
2373 });
2374 if (!transStatus.isOk()) {
2375 LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
2376 return C2_TRANSACTION_FAILED;
2377 }
2378 return status;
2379}
2380
Pawin Vongmasa36653902018-11-15 00:10:25 -08002381c2_status_t Codec2Client::Component::setOutputSurface(
2382 C2BlockPool::local_id_t blockPoolId,
2383 const sp<IGraphicBufferProducer>& surface,
Sungtak Leedb14cba2021-04-10 00:50:23 -07002384 uint32_t generation,
2385 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002386 if (mAidlBase) {
2387 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2388 mGraphicBufferAllocators->current();
2389 if (!gba) {
2390 LOG(ERROR) << "setOutputSurface for AIDL -- "
2391 "GraphicBufferAllocator was not created.";
2392 return C2_CORRUPTED;
2393 }
Sungtak Lee08b20b12024-08-21 18:33:08 +00002394 // Note: Consumer usage is set ahead of the HAL allocator(gba) being set.
2395 // This is same as HIDL.
2396 uint64_t consumerUsage = configConsumerUsage(surface);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002397 bool ret = gba->configure(surface, generation, maxDequeueCount);
Sungtak Lee08b20b12024-08-21 18:33:08 +00002398 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx",
2399 generation, (long long)consumerUsage);
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002400 return ret ? C2_OK : C2_CORRUPTED;
2401 }
Sungtak Lee08515812019-06-05 11:16:32 -07002402 uint64_t bqId = 0;
2403 sp<IGraphicBufferProducer> nullIgbp;
2404 sp<HGraphicBufferProducer2> nullHgbp;
Pawin Vongmasa3866c7e2019-01-31 05:21:29 -08002405
Sungtak Lee08515812019-06-05 11:16:32 -07002406 sp<HGraphicBufferProducer2> igbp = surface ?
2407 surface->getHalInterface<HGraphicBufferProducer2>() : nullHgbp;
2408 if (surface && !igbp) {
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002409 igbp = new B2HGraphicBufferProducer2(surface);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002410 }
2411
Sungtak Leefb579022022-05-10 06:36:15 +00002412 std::scoped_lock lock(mOutputMutex);
Sungtak Leea714f112021-03-16 05:40:03 -07002413 std::shared_ptr<SurfaceSyncObj> syncObj;
2414
Sungtak Lee08515812019-06-05 11:16:32 -07002415 if (!surface) {
Sungtak Leedb14cba2021-04-10 00:50:23 -07002416 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002417 } else if (surface->getUniqueId(&bqId) != OK) {
2418 LOG(ERROR) << "setOutputSurface -- "
2419 "cannot obtain bufferqueue id.";
2420 bqId = 0;
Sungtak Leedb14cba2021-04-10 00:50:23 -07002421 mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002422 } else {
Wonsik Kime8e98152022-12-16 16:04:17 -08002423 mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
2424 mHidlBase1_2 ? &syncObj : nullptr);
Sungtak Lee08515812019-06-05 11:16:32 -07002425 }
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002426
Sungtak Lee08b20b12024-08-21 18:33:08 +00002427 uint64_t consumerUsage = configConsumerUsage(surface);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002428 ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
Sungtak Lee08b20b12024-08-21 18:33:08 +00002429 generation, (long long)consumerUsage, syncObj ? " sync" : "");
Sungtak Lee08515812019-06-05 11:16:32 -07002430
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002431 Return<c2_hidl::Status> transStatus = syncObj ?
Wonsik Kime8e98152022-12-16 16:04:17 -08002432 mHidlBase1_2->setOutputSurfaceWithSyncObj(
Sungtak Leea714f112021-03-16 05:40:03 -07002433 static_cast<uint64_t>(blockPoolId),
2434 bqId == 0 ? nullHgbp : igbp, *syncObj) :
Wonsik Kime8e98152022-12-16 16:04:17 -08002435 mHidlBase1_0->setOutputSurface(
Sungtak Leea714f112021-03-16 05:40:03 -07002436 static_cast<uint64_t>(blockPoolId),
2437 bqId == 0 ? nullHgbp : igbp);
Lajos Molnar78aa7c92021-02-18 21:39:01 -08002438
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002439 mOutputBufferQueue->expireOldWaiters();
2440
Pawin Vongmasa36653902018-11-15 00:10:25 -08002441 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002442 LOG(ERROR) << "setOutputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002443 return C2_TRANSACTION_FAILED;
2444 }
2445 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002446 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002447 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002448 LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002449 }
Sungtak Leea714f112021-03-16 05:40:03 -07002450 ALOGD("Surface configure completed");
Pawin Vongmasa36653902018-11-15 00:10:25 -08002451 return status;
2452}
2453
2454status_t Codec2Client::Component::queueToOutputSurface(
2455 const C2ConstGraphicBlock& block,
2456 const QueueBufferInput& input,
2457 QueueBufferOutput* output) {
Arun Johnson7ba67072023-11-06 22:23:04 +00002458 ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002459 if (mAidlBase) {
2460 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2461 mGraphicBufferAllocators->current();
2462 if (gba) {
2463 return gba->displayBuffer(block, input, output);
2464 } else {
2465 return C2_NOT_FOUND;
2466 }
2467 }
Pawin Vongmasabf69de92019-10-29 06:21:27 -07002468 return mOutputBufferQueue->outputBuffer(block, input, output);
Pawin Vongmasa36653902018-11-15 00:10:25 -08002469}
2470
Sungtak Lee08b20b12024-08-21 18:33:08 +00002471uint64_t Codec2Client::Component::configConsumerUsage(
2472 const sp<IGraphicBufferProducer>& surface) {
2473 // set consumer bits
2474 // TODO: should this get incorporated into setOutputSurface method so that consumer bits
2475 // can be set atomically?
2476 uint64_t consumerUsage = kDefaultConsumerUsage;
2477 {
2478 if (surface) {
2479 uint64_t usage = 0;
2480 status_t err = surface->getConsumerUsage(&usage);
2481 if (err != NO_ERROR) {
2482 ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
2483 err, asString(err));
2484 } else {
2485 // Note: we are adding the default usage because components must support
2486 // producing output frames that can be displayed an all output surfaces.
2487
2488 // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
2489 // is meaningful in a tunneled scenario; on one hand output buffers exist, but
2490 // they do not exist inside of C2 scope. Any buffer usage shall be communicated
2491 // through the sideband channel.
2492
2493 consumerUsage = usage | kDefaultConsumerUsage;
2494 }
2495 }
2496
2497 C2StreamUsageTuning::output outputUsage{
2498 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
2499 std::vector<std::unique_ptr<C2SettingResult>> failures;
2500 c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
2501 if (err != C2_OK) {
2502 ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
2503 err, asString(err));
2504 }
2505 }
2506 return consumerUsage;
2507}
2508
Brian Lindahlc953b462023-01-27 16:21:43 -07002509void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002510 if (mAidlBase) {
2511 // TODO b/311348680
2512 return;
2513 }
Brian Lindahlc953b462023-01-27 16:21:43 -07002514 mOutputBufferQueue->pollForRenderedFrames(delta);
2515}
2516
Sungtak Leea714f112021-03-16 05:40:03 -07002517void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
2518 int maxDequeueCount) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002519 if (mAidlBase) {
2520 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2521 mGraphicBufferAllocators->current();
2522 if (gba) {
2523 gba->updateMaxDequeueBufferCount(maxDequeueCount);
2524 }
2525 return;
2526 }
Sungtak Leea714f112021-03-16 05:40:03 -07002527 mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
2528}
2529
Sungtak Leec7da7a02022-05-05 08:45:33 +00002530void Codec2Client::Component::stopUsingOutputSurface(
2531 C2BlockPool::local_id_t blockPoolId) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002532 if (mAidlBase) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002533 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2534 mGraphicBufferAllocators->current();
2535 if (gba) {
2536 gba->reset();
2537 }
Wonsik Kime8e98152022-12-16 16:04:17 -08002538 return;
2539 }
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002540 std::scoped_lock lock(mOutputMutex);
2541 mOutputBufferQueue->stop();
Wonsik Kime8e98152022-12-16 16:04:17 -08002542 Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
Sungtak Leec7da7a02022-05-05 08:45:33 +00002543 static_cast<uint64_t>(blockPoolId), nullptr);
2544 if (!transStatus.isOk()) {
2545 LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
2546 } else {
2547 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002548 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Sungtak Leec7da7a02022-05-05 08:45:33 +00002549 if (status != C2_OK) {
2550 LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
2551 << status << ".";
2552 }
2553 }
Sungtak Lee8e2e2c62023-01-17 18:29:34 +00002554 mOutputBufferQueue->expireOldWaiters();
Sungtak Leec7da7a02022-05-05 08:45:33 +00002555}
2556
Sungtak Lee214ce612023-11-01 10:01:13 +00002557void Codec2Client::Component::onBufferReleasedFromOutputSurface(
2558 uint32_t generation) {
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002559 if (mAidlBase) {
2560 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2561 mGraphicBufferAllocators->current();
2562 if (gba) {
2563 gba->onBufferReleased(generation);
2564 }
2565 return;
2566 }
Sungtak Lee6700cc92023-11-22 18:04:05 +00002567 mOutputBufferQueue->onBufferReleased(generation);
Sungtak Lee214ce612023-11-01 10:01:13 +00002568}
2569
Sungtak Lee1720e4c2024-07-31 21:15:26 +00002570void Codec2Client::Component::onBufferAttachedToOutputSurface(
2571 uint32_t generation) {
2572 if (mAidlBase) {
2573 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2574 mGraphicBufferAllocators->current();
2575 if (gba) {
2576 gba->onBufferAttached(generation);
2577 }
2578 return;
2579 }
2580 mOutputBufferQueue->onBufferAttached(generation);
2581}
2582
Sungtak Leeaa71b5c2023-11-04 09:21:15 +00002583void Codec2Client::Component::holdIgbaBlocks(
2584 const std::list<std::unique_ptr<C2Work>>& workList) {
2585 if (!mAidlBase) {
2586 return;
2587 }
2588 std::shared_ptr<AidlGraphicBufferAllocator> gba =
2589 mGraphicBufferAllocators->current();
2590 if (!gba) {
2591 return;
2592 }
2593 std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
2594 c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
2595 for (const std::unique_ptr<C2Work>& work : workList) {
2596 if (!work) [[unlikely]] {
2597 continue;
2598 }
2599 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
2600 if (!worklet) {
2601 continue;
2602 }
2603 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
2604 if (buffer) {
2605 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
2606 std::shared_ptr<_C2BlockPoolData> poolData =
2607 _C2BlockFactory::GetGraphicBlockPoolData(block);
2608 _C2BlockFactory::RegisterIgba(poolData, igba);
2609 }
2610 }
2611 }
2612 }
2613 }
2614}
2615
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002616c2_status_t Codec2Client::Component::connectToInputSurface(
2617 const std::shared_ptr<InputSurface>& inputSurface,
2618 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002619 if (mAidlBase) {
2620 // FIXME
2621 return C2_OMITTED;
2622 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002623 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002624 Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002625 inputSurface->mBase,
2626 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002627 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002628 status = static_cast<c2_status_t>(s);
2629 if (status != C2_OK) {
2630 LOG(DEBUG) << "connectToInputSurface -- call failed: "
2631 << status << ".";
2632 return;
2633 }
2634 *connection = std::make_shared<InputSurfaceConnection>(c);
2635 });
Pawin Vongmasa36653902018-11-15 00:10:25 -08002636 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002637 LOG(ERROR) << "connectToInputSurface -- transaction failed";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002638 return C2_TRANSACTION_FAILED;
2639 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002640 return status;
2641}
2642
2643c2_status_t Codec2Client::Component::connectToOmxInputSurface(
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002644 const sp<HGraphicBufferProducer1>& producer,
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002645 const sp<HGraphicBufferSource>& source,
2646 std::shared_ptr<InputSurfaceConnection>* connection) {
Wonsik Kime8e98152022-12-16 16:04:17 -08002647 if (mAidlBase) {
2648 LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
2649 return C2_OMITTED;
2650 }
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002651 c2_status_t status;
Wonsik Kime8e98152022-12-16 16:04:17 -08002652 Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002653 producer, source,
2654 [&status, connection](
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002655 c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002656 status = static_cast<c2_status_t>(s);
2657 if (status != C2_OK) {
2658 LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
2659 << status << ".";
2660 return;
2661 }
2662 *connection = std::make_shared<InputSurfaceConnection>(c);
2663 });
2664 if (!transStatus.isOk()) {
2665 LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
2666 return C2_TRANSACTION_FAILED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08002667 }
2668 return status;
2669}
2670
2671c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
Wonsik Kime8e98152022-12-16 16:04:17 -08002672 if (mAidlBase) {
2673 // FIXME
2674 return C2_OMITTED;
2675 }
2676 Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
Pawin Vongmasa36653902018-11-15 00:10:25 -08002677 if (!transStatus.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002678 LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002679 return C2_TRANSACTION_FAILED;
2680 }
2681 c2_status_t status =
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002682 static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002683 if (status != C2_OK) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002684 LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
2685 << status << ".";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002686 }
2687 return status;
2688}
2689
Wonsik Kime8e98152022-12-16 16:04:17 -08002690Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
2691 // This object never gets destructed
2692 static AidlDeathManager *sManager = new AidlDeathManager();
2693 return sManager;
2694}
2695
Pawin Vongmasa36653902018-11-15 00:10:25 -08002696c2_status_t Codec2Client::Component::setDeathListener(
2697 const std::shared_ptr<Component>& component,
2698 const std::shared_ptr<Listener>& listener) {
2699
2700 struct HidlDeathRecipient : public hardware::hidl_death_recipient {
2701 std::weak_ptr<Component> component;
2702 std::weak_ptr<Listener> base;
2703
2704 virtual void serviceDied(
2705 uint64_t /* cookie */,
2706 const wp<::android::hidl::base::V1_0::IBase>& /* who */
2707 ) override {
2708 if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
2709 listener->onDeath(component);
2710 } else {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002711 LOG(DEBUG) << "onDeath -- listener died.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002712 }
2713 }
2714 };
2715
Wonsik Kime8e98152022-12-16 16:04:17 -08002716 if (component->mAidlBase) {
2717 size_t seq;
2718 if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
2719 component->mAidlDeathSeq = seq;
2720 }
2721 return C2_OK;
2722 }
2723
Pawin Vongmasa36653902018-11-15 00:10:25 -08002724 sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
2725 deathRecipient->base = listener;
2726 deathRecipient->component = component;
2727
2728 component->mDeathRecipient = deathRecipient;
Wonsik Kime8e98152022-12-16 16:04:17 -08002729 Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
Pawin Vongmasa36653902018-11-15 00:10:25 -08002730 component->mDeathRecipient, 0);
2731 if (!transResult.isOk()) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002732 LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002733 return C2_TRANSACTION_FAILED;
2734 }
2735 if (!static_cast<bool>(transResult)) {
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002736 LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
Pawin Vongmasa36653902018-11-15 00:10:25 -08002737 return C2_CORRUPTED;
2738 }
2739 return C2_OK;
2740}
2741
2742// Codec2Client::InputSurface
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002743Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002744 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002745 [base]() -> sp<c2_hidl::IConfigurable> {
2746 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002747 base->getConfigurable();
2748 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002749 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002750 nullptr;
2751 }()
2752 },
2753 mBase{base},
2754 mGraphicBufferProducer{new
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002755 H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
2756 Return<sp<HGraphicBufferProducer2>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002757 base->getGraphicBufferProducer();
2758 return transResult.isOk() ?
Pawin Vongmasaef939bf2019-03-03 04:44:59 -08002759 static_cast<sp<HGraphicBufferProducer2>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002760 nullptr;
2761 }())} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002762}
2763
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002764sp<IGraphicBufferProducer>
Pawin Vongmasa36653902018-11-15 00:10:25 -08002765 Codec2Client::InputSurface::getGraphicBufferProducer() const {
2766 return mGraphicBufferProducer;
2767}
2768
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002769sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002770 return mBase;
2771}
2772
2773// Codec2Client::InputSurfaceConnection
Pawin Vongmasa36653902018-11-15 00:10:25 -08002774Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002775 const sp<c2_hidl::IInputSurfaceConnection>& base)
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002776 : Configurable{
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002777 [base]() -> sp<c2_hidl::IConfigurable> {
2778 Return<sp<c2_hidl::IConfigurable>> transResult =
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002779 base->getConfigurable();
2780 return transResult.isOk() ?
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002781 static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
Pawin Vongmasa1c75a232019-01-09 04:41:52 -08002782 nullptr;
2783 }()
2784 },
2785 mBase{base} {
Pawin Vongmasa36653902018-11-15 00:10:25 -08002786}
2787
2788c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
Wonsik Kimc8fc2c32022-12-12 14:43:00 -08002789 Return<c2_hidl::Status> transResult = mBase->disconnect();
2790 return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
Pawin Vongmasa36653902018-11-15 00:10:25 -08002791}
2792
2793} // namespace android