blob: d40b469c5250e8fa169ac01fc2147db5ec865938 [file] [log] [blame]
Sungtak Leefce527c2021-03-20 01:24:41 -07001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "C2FenceFactory"
Sungtak Lee4da75232023-09-06 18:08:09 +000019#include <poll.h>
20
21#include <android-base/unique_fd.h>
Lubin Yin92427a52022-04-18 16:57:39 -070022#include <cutils/native_handle.h>
Sungtak Leefce527c2021-03-20 01:24:41 -070023#include <utils/Log.h>
Lubin Yin92427a52022-04-18 16:57:39 -070024#include <ui/Fence.h>
Sungtak Leefce527c2021-03-20 01:24:41 -070025
26#include <C2FenceFactory.h>
27#include <C2SurfaceSyncObj.h>
28
Lubin Yin92427a52022-04-18 16:57:39 -070029#define MAX_FENCE_FDS 1
30
Sungtak Leefce527c2021-03-20 01:24:41 -070031class C2Fence::Impl {
32public:
Lubin Yin92427a52022-04-18 16:57:39 -070033 enum type_t : uint32_t {
34 INVALID_FENCE,
35 NULL_FENCE,
36 SURFACE_FENCE,
37 SYNC_FENCE,
Sungtak Lee4da75232023-09-06 18:08:09 +000038 PIPE_FENCE,
Lubin Yin92427a52022-04-18 16:57:39 -070039 };
40
Sungtak Leefce527c2021-03-20 01:24:41 -070041 virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;
42
43 virtual bool valid() const = 0;
44
45 virtual bool ready() const = 0;
46
47 virtual int fd() const = 0;
48
49 virtual bool isHW() const = 0;
50
Lubin Yin92427a52022-04-18 16:57:39 -070051 virtual type_t type() const = 0;
52
53 /**
54 * Create a native handle for the fence so it can be marshalled.
55 * The native handle must store fence type in the first integer.
56 *
57 * \return a valid native handle if the fence can be marshalled, otherwise return null.
58 */
59 virtual native_handle_t *createNativeHandle() const = 0;
60
Sungtak Leefce527c2021-03-20 01:24:41 -070061 virtual ~Impl() = default;
62
63 Impl() = default;
Lubin Yin92427a52022-04-18 16:57:39 -070064
65 static type_t GetTypeFromNativeHandle(const native_handle_t* nh) {
66 if (nh && nh->numFds >= 0 && nh->numFds <= MAX_FENCE_FDS && nh->numInts > 0) {
67 return static_cast<type_t>(nh->data[nh->numFds]);
68 }
69 return INVALID_FENCE;
70 }
Sungtak Leefce527c2021-03-20 01:24:41 -070071};
72
73c2_status_t C2Fence::wait(c2_nsecs_t timeoutNs) {
74 if (mImpl) {
75 return mImpl->wait(timeoutNs);
76 }
77 // null fence is always signalled.
78 return C2_OK;
79}
80
81bool C2Fence::valid() const {
82 if (mImpl) {
83 return mImpl->valid();
84 }
85 // null fence is always valid.
86 return true;
87}
88
89bool C2Fence::ready() const {
90 if (mImpl) {
91 return mImpl->ready();
92 }
93 // null fence is always signalled.
94 return true;
95}
96
97int C2Fence::fd() const {
98 if (mImpl) {
99 return mImpl->fd();
100 }
101 // null fence does not have fd.
102 return -1;
103}
104
105bool C2Fence::isHW() const {
106 if (mImpl) {
107 return mImpl->isHW();
108 }
109 return false;
110}
111
112/**
113 * Fence implementation for C2BufferQueueBlockPool based block allocation.
114 * The implementation supports all C2Fence interface except fd().
115 */
116class _C2FenceFactory::SurfaceFenceImpl: public C2Fence::Impl {
117public:
118 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
119 if (mPtr) {
120 return mPtr->waitForChange(mWaitId, timeoutNs);
121 }
122 return C2_OK;
123 }
124
125 virtual bool valid() const {
126 return mPtr;
127 }
128
129 virtual bool ready() const {
130 uint32_t status;
131 if (mPtr) {
132 mPtr->lock();
133 status = mPtr->getWaitIdLocked();
134 mPtr->unlock();
135
136 return status != mWaitId;
137 }
138 return true;
139 }
140
141 virtual int fd() const {
142 // does not support fd, since this is shared mem and futex based
143 return -1;
144 }
145
146 virtual bool isHW() const {
147 return false;
148 }
149
Lubin Yin92427a52022-04-18 16:57:39 -0700150 virtual type_t type() const {
151 return SURFACE_FENCE;
152 }
153
154 virtual native_handle_t *createNativeHandle() const {
Lajos Molnara272dd72022-05-25 11:05:08 -0700155 ALOGD("Cannot create native handle from surface fence");
Lubin Yin92427a52022-04-18 16:57:39 -0700156 return nullptr;
157 }
158
Sungtak Leefce527c2021-03-20 01:24:41 -0700159 virtual ~SurfaceFenceImpl() {};
160
161 SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
162 mSyncMem(syncMem),
163 mPtr(syncMem ? syncMem->mem() : nullptr),
164 mWaitId(syncMem ? waitId : 0) {}
165private:
166 const std::shared_ptr<const C2SurfaceSyncMemory> mSyncMem; // This is for life-cycle guarantee
167 C2SyncVariables *const mPtr;
168 const uint32_t mWaitId;
169};
170
171C2Fence::C2Fence(std::shared_ptr<Impl> impl) : mImpl(impl) {}
172
173C2Fence _C2FenceFactory::CreateSurfaceFence(
174 std::shared_ptr<C2SurfaceSyncMemory> syncMem,
175 uint32_t waitId) {
176 if (syncMem) {
177 C2Fence::Impl *p
178 = new _C2FenceFactory::SurfaceFenceImpl(syncMem, waitId);
179 if (p->valid()) {
180 return C2Fence(std::shared_ptr<C2Fence::Impl>(p));
181 } else {
182 delete p;
183 }
184 }
185 return C2Fence();
186}
Lubin Yin92427a52022-04-18 16:57:39 -0700187
188using namespace android;
189
190class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
191public:
192 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
Lubin Yin164f9f82022-06-14 16:10:10 -0700193 int64_t timeoutMs = timeoutNs / 1000000;
Lubin Yin92427a52022-04-18 16:57:39 -0700194 if (timeoutMs > INT_MAX) {
195 timeoutMs = INT_MAX;
196 }
Lubin Yin92427a52022-04-18 16:57:39 -0700197 switch (mFence->wait((int)timeoutMs)) {
198 case NO_ERROR:
199 return C2_OK;
200 case -ETIME:
201 return C2_TIMED_OUT;
202 default:
203 return C2_CORRUPTED;
204 }
205 }
206
207 virtual bool valid() const {
Uma Mehta1ac98782022-09-28 16:47:35 +0530208 return (mFence && (mFence->getStatus() != Fence::Status::Invalid));
Lubin Yin92427a52022-04-18 16:57:39 -0700209 }
210
211 virtual bool ready() const {
212 return mFence->getStatus() == Fence::Status::Signaled;
213 }
214
215 virtual int fd() const {
216 return mFence->dup();
217 }
218
Uma Mehta1ac98782022-09-28 16:47:35 +0530219 std::vector<int> fds() const {
220 std::vector<int> retFds;
221 for (int index = 0; index < mListFences.size(); index++) {
222 retFds.push_back(mListFences[index]->dup());
223 }
224 return retFds;
225 }
226
Lubin Yin92427a52022-04-18 16:57:39 -0700227 virtual bool isHW() const {
228 return true;
229 }
230
231 virtual type_t type() const {
232 return SYNC_FENCE;
233 }
234
235 virtual native_handle_t *createNativeHandle() const {
Uma Mehta1ac98782022-09-28 16:47:35 +0530236 std::vector<int> nativeFds = fds();
237 nativeFds.push_back(fd());
238 native_handle_t* nh = native_handle_create(nativeFds.size(), 1);
Lubin Yin92427a52022-04-18 16:57:39 -0700239 if (!nh) {
240 ALOGE("Failed to allocate native handle for sync fence");
Uma Mehta1ac98782022-09-28 16:47:35 +0530241 for (int fd : nativeFds) {
242 close(fd);
243 }
Lubin Yin92427a52022-04-18 16:57:39 -0700244 return nullptr;
245 }
Uma Mehta1ac98782022-09-28 16:47:35 +0530246
247 for (int i = 0; i < nativeFds.size(); i++) {
248 nh->data[i] = nativeFds[i];
249 }
250 nh->data[nativeFds.size()] = type();
Lubin Yin92427a52022-04-18 16:57:39 -0700251 return nh;
252 }
253
254 virtual ~SyncFenceImpl() {};
255
256 SyncFenceImpl(int fenceFd) :
Uma Mehta1ac98782022-09-28 16:47:35 +0530257 mFence(sp<Fence>::make(fenceFd)) {
258 mListFences.clear();
259 if (mFence) {
260 mListFences.push_back(mFence);
261 }
262 }
263
264 SyncFenceImpl(const std::vector<int>& fenceFds, int mergedFd) {
265 mListFences.clear();
266
267 for (int fenceFd : fenceFds) {
268 if (fenceFd < 0) {
269 continue;
270 } else {
271 mListFences.push_back(sp<Fence>::make(fenceFd));
272 if (!mListFences.back()) {
273 mFence.clear();
274 break;
275 }
276 if (mergedFd == -1) {
277 mFence = (mFence == nullptr) ? (mListFences.back()) :
278 (Fence::merge("syncFence", mFence, mListFences.back()));
279 }
280 }
281 }
282 if (mergedFd != -1)
283 {
284 mFence = sp<Fence>::make(mergedFd);
285 }
286 if (!mFence) {
287 mListFences.clear();
288 }
289 }
Lubin Yin92427a52022-04-18 16:57:39 -0700290
291 static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(const native_handle_t* nh) {
Uma Mehta1ac98782022-09-28 16:47:35 +0530292 if (!nh || nh->numFds < 1 || nh->numInts < 1) {
Lubin Yin92427a52022-04-18 16:57:39 -0700293 ALOGE("Invalid handle for sync fence");
294 return nullptr;
295 }
Uma Mehta1ac98782022-09-28 16:47:35 +0530296 std::vector<int> fds;
297 for (int i = 0; i < nh->numFds-1; i++) {
298 fds.push_back(dup(nh->data[i]));
299 }
300 std::shared_ptr<SyncFenceImpl> p = (nh->numFds == 1)?
301 (std::make_shared<SyncFenceImpl>(fds.back())):
302 (std::make_shared<SyncFenceImpl>(fds, (dup(nh->data[nh->numFds-1]))));
Lubin Yin92427a52022-04-18 16:57:39 -0700303 if (!p) {
304 ALOGE("Failed to allocate sync fence impl");
Uma Mehta1ac98782022-09-28 16:47:35 +0530305 for (int fd : fds) {
306 close(fd);
307 }
Lubin Yin92427a52022-04-18 16:57:39 -0700308 }
309 return p;
310 }
311
312private:
Uma Mehta1ac98782022-09-28 16:47:35 +0530313 std::vector<sp<Fence>> mListFences;
314 sp<Fence> mFence; //merged fence in case mListFences size > 0
Lubin Yin92427a52022-04-18 16:57:39 -0700315};
316
Uma Mehta1ac98782022-09-28 16:47:35 +0530317std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence) {
318 std::vector<int> retFds;
319 if ((fence.mImpl) && (fence.mImpl->type() == C2Fence::Impl::SYNC_FENCE)) {
320 retFds = static_cast<_C2FenceFactory::SyncFenceImpl *>(fence.mImpl.get())->fds();
321 }
322 return retFds;
323}
324
Lubin Yin92427a52022-04-18 16:57:39 -0700325C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) {
326 std::shared_ptr<C2Fence::Impl> p;
327 if (fenceFd >= 0) {
328 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFd);
329 if (!p) {
330 ALOGE("Failed to allocate sync fence impl");
331 close(fenceFd);
Uma Mehta1ac98782022-09-28 16:47:35 +0530332 } else if (!p->valid()) {
Lubin Yin92427a52022-04-18 16:57:39 -0700333 p.reset();
334 }
335 } else {
336 ALOGE("Create sync fence from invalid fd");
337 }
338 return C2Fence(p);
339}
340
Uma Mehta1ac98782022-09-28 16:47:35 +0530341C2Fence _C2FenceFactory::CreateMultipleFdSyncFence(const std::vector<int>& fenceFds) {
342 std::shared_ptr<C2Fence::Impl> p;
343 if (fenceFds.size() > 0) {
344 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFds, -1);
345 if (!p) {
346 ALOGE("Failed to allocate sync fence impl closing FDs");
347 for (int fenceFd : fenceFds) {
348 close(fenceFd);
349 }
350 } else if (!p->valid()) {
351 ALOGE("Invalid sync fence created");
352 p.reset();
353 }
354 } else {
355 ALOGE("Create sync fence from invalid fd list of size 0");
356 }
357 return C2Fence(p);
358}
359
Sungtak Lee4da75232023-09-06 18:08:09 +0000360/**
361 * Fence implementation for notifying # of events available based on
362 * file descriptors created by pipe()/pipe2(). The writing end of the
363 * file descriptors is used to create the implementation.
364 * The implementation supports all C2Fence interface.
365 */
366class _C2FenceFactory::PipeFenceImpl: public C2Fence::Impl {
367private:
368 bool waitEvent(c2_nsecs_t timeoutNs, bool *hangUp, bool *event) const {
369 if (!mValid) {
370 *hangUp = true;
371 return true;
372 }
373
374 struct pollfd pfd;
375 pfd.fd = mPipeFd.get();
376 pfd.events = POLLIN;
377 pfd.revents = 0;
378 struct timespec ts;
379 if (timeoutNs >= 0) {
380 ts.tv_sec = int(timeoutNs / 1000000000);
381 ts.tv_nsec = timeoutNs;
382 } else {
383 ALOGD("polling for indefinite duration requested, but changed to wait for %d sec",
384 kPipeFenceWaitLimitSecs);
385 ts.tv_sec = kPipeFenceWaitLimitSecs;
386 ts.tv_nsec = 0;
387 }
388 int ret = ::ppoll(&pfd, 1, &ts, nullptr);
389 if (ret >= 0) {
390 if (pfd.revents) {
391 if (pfd.revents & ~POLLIN) {
392 // Mostly this means the writing end fd was closed.
393 *hangUp = true;
394 mValid = false;
395 ALOGD("PipeFenceImpl: pipe fd hangup or err event returned");
396 }
397 *event = true;
398 return true;
399 }
400 // event not ready yet.
401 return true;
402 }
403 if (errno == EINTR) {
404 // poll() was cancelled by signal or inner kernel status.
405 return false;
406 }
407 // Since poll error happened here, treat the error is irrecoverable.
408 ALOGE("PipeFenceImpl: poll() error %d", errno);
409 *hangUp = true;
410 mValid = false;
411 return true;
412 }
413
414public:
415 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
416 if (!mValid) {
417 return C2_BAD_STATE;
418 }
419 bool hangUp = false;
420 bool event = false;
421 if (waitEvent(timeoutNs, &hangUp, &event)) {
422 if (hangUp) {
423 return C2_BAD_STATE;
424 }
425 if (event) {
426 return C2_OK;
427 }
428 return C2_TIMED_OUT;
429 } else {
430 return C2_CANCELED;
431 }
432 }
433
434 virtual bool valid() const {
435 if (!mValid) {
436 return false;
437 }
438 bool hangUp = false;
439 bool event = false;
440 if (waitEvent(0, &event, &event)) {
441 if (hangUp) {
442 return false;
443 }
444 }
445 return true;
446 }
447
448 virtual bool ready() const {
449 if (!mValid) {
450 return false;
451 }
452 bool hangUp = false;
453 bool event = false;
454 if (waitEvent(0, &hangUp, &event)) {
455 if (event) {
456 return true;
457 }
458 }
459 return false;
460 }
461
462 virtual int fd() const {
463 if (!mValid) {
464 return -1;
465 }
466 return ::dup(mPipeFd.get());
467 }
468
469 virtual bool isHW() const {
470 return false;
471 }
472
473 virtual type_t type() const {
474 return PIPE_FENCE;
475 }
476
477 virtual native_handle_t *createNativeHandle() const {
478 // This is not supported.
479 return nullptr;
480 }
481
482 virtual ~PipeFenceImpl() = default;
483
484 PipeFenceImpl(int fd) : mPipeFd(fd) {
485 mValid = (mPipeFd.get() >= 0);
486 }
487
488private:
489 friend struct _C2FenceFactory;
490 static constexpr int kPipeFenceWaitLimitSecs = 5;
491
492 mutable std::atomic<bool> mValid;
493 ::android::base::unique_fd mPipeFd;
494};
495
496C2Fence _C2FenceFactory::CreatePipeFence(int fd) {
497 std::shared_ptr<_C2FenceFactory::PipeFenceImpl> impl =
498 std::make_shared<_C2FenceFactory::PipeFenceImpl>(fd);
499 std::shared_ptr<C2Fence::Impl> p = std::static_pointer_cast<C2Fence::Impl>(impl);
500 if (!p) {
501 ALOGE("PipeFence creation failure");
502 } else if (!impl->mValid) {
503 p.reset();
504 }
505 return C2Fence(p);
506}
507
Lubin Yin92427a52022-04-18 16:57:39 -0700508native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
509 return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
510}
511
512C2Fence _C2FenceFactory::CreateFromNativeHandle(const native_handle_t* handle) {
513 if (!handle) {
514 return C2Fence();
515 }
516 C2Fence::Impl::type_t type = C2Fence::Impl::GetTypeFromNativeHandle(handle);
517 std::shared_ptr<C2Fence::Impl> p;
518 switch (type) {
519 case C2Fence::Impl::SYNC_FENCE:
520 p = SyncFenceImpl::CreateFromNativeHandle(handle);
521 break;
522 default:
Lajos Molnara272dd72022-05-25 11:05:08 -0700523 ALOGD("Unsupported fence type %d", type);
524 // return a null-fence in this case
Lubin Yin92427a52022-04-18 16:57:39 -0700525 break;
526 }
527 if (p && !p->valid()) {
528 p.reset();
529 }
530 return C2Fence(p);
531}
532