1 /*
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"
19 #include <poll.h>
20
21 #include <android-base/unique_fd.h>
22 #include <cutils/native_handle.h>
23 #include <utils/Log.h>
24 #include <utils/SystemClock.h>
25 #include <ui/Fence.h>
26
27 #include <C2FenceFactory.h>
28 #include <C2SurfaceSyncObj.h>
29
30 #include <utility>
31
32 // support up to 32 sync fds (and an optional merged fd), and 1 int
33 #define MAX_FENCE_FDS 33
34 #define MAX_FENCE_INTS 1
35
36 class C2Fence::Impl {
37 public:
38 // These enums are not part of the ABI, so can be changed.
39 enum type_t : int32_t {
40 INVALID_FENCE = -1,
41 NULL_FENCE = 0,
42 SURFACE_FENCE = 2,
43
44 SYNC_FENCE = 3,
45 PIPE_FENCE = 4,
46 };
47
48 // magic numbers for native handles
49 enum : int32_t {
50 SYNC_FENCE_DEPRECATED_MAGIC = 3,
51 SYNC_FENCE_UNORDERED_MAGIC = '\302fsu',
52 SYNC_FENCE_MAGIC = '\302fso',
53 };
54
55 virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;
56
57 virtual bool valid() const = 0;
58
59 virtual bool ready() const = 0;
60
61 virtual int fd() const = 0;
62
63 virtual bool isHW() const = 0;
64
65 virtual type_t type() const = 0;
66
67 /**
68 * Create a native handle for the fence so it can be marshalled.
69 * All native handles must store fence type in the last integer.
70 * The created native handle (if not null) must be closed by the caller.
71 *
72 * \return a valid native handle if the fence can be marshalled, otherwise return null.
73 */
74 virtual native_handle_t *createNativeHandle() const = 0;
75
76 virtual ~Impl() = default;
77
78 Impl() = default;
79
80 /**
81 * Get the type of the fence from the native handle.
82 *
83 * \param nh the native handle to get the type from.
84 * \return the type of the fence, or INVALID_FENCE if the native handle is
85 * invalid or malformed.
86 */
GetTypeFromNativeHandle(const native_handle_t * nh)87 static type_t GetTypeFromNativeHandle(const native_handle_t* nh) {
88 if (!nh || nh->numFds < 0 || nh->numFds > MAX_FENCE_FDS
89 || nh->numInts < 1 || nh->numInts > MAX_FENCE_INTS) {
90 return INVALID_FENCE;
91 }
92
93 // the magic number for Codec 2.0 native handles is the last integer
94 switch (nh->data[nh->numFds + nh->numInts - 1]) {
95 case SYNC_FENCE_MAGIC:
96 case SYNC_FENCE_UNORDERED_MAGIC:
97 case SYNC_FENCE_DEPRECATED_MAGIC:
98 return SYNC_FENCE;
99
100 default:
101 return INVALID_FENCE;
102 }
103 }
104 };
105
wait(c2_nsecs_t timeoutNs)106 c2_status_t C2Fence::wait(c2_nsecs_t timeoutNs) {
107 if (mImpl) {
108 return mImpl->wait(timeoutNs);
109 }
110 // null fence is always signalled.
111 return C2_OK;
112 }
113
valid() const114 bool C2Fence::valid() const {
115 if (mImpl) {
116 return mImpl->valid();
117 }
118 // null fence is always valid.
119 return true;
120 }
121
ready() const122 bool C2Fence::ready() const {
123 if (mImpl) {
124 return mImpl->ready();
125 }
126 // null fence is always signalled.
127 return true;
128 }
129
fd() const130 int C2Fence::fd() const {
131 if (mImpl) {
132 return mImpl->fd();
133 }
134 // null fence does not have fd.
135 return -1;
136 }
137
isHW() const138 bool C2Fence::isHW() const {
139 if (mImpl) {
140 return mImpl->isHW();
141 }
142 return false;
143 }
144
145 /**
146 * Fence implementation for C2BufferQueueBlockPool based block allocation.
147 * The implementation supports all C2Fence interface except fd().
148 */
149 class _C2FenceFactory::SurfaceFenceImpl: public C2Fence::Impl {
150 public:
wait(c2_nsecs_t timeoutNs)151 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
152 if (mPtr) {
153 return mPtr->waitForChange(mWaitId, timeoutNs);
154 }
155 return C2_OK;
156 }
157
valid() const158 virtual bool valid() const {
159 return mPtr;
160 }
161
ready() const162 virtual bool ready() const {
163 uint32_t status;
164 if (mPtr) {
165 mPtr->lock();
166 status = mPtr->getWaitIdLocked();
167 mPtr->unlock();
168
169 return status != mWaitId;
170 }
171 return true;
172 }
173
fd() const174 virtual int fd() const {
175 // does not support fd, since this is shared mem and futex based
176 return -1;
177 }
178
isHW() const179 virtual bool isHW() const {
180 return false;
181 }
182
type() const183 virtual type_t type() const {
184 return SURFACE_FENCE;
185 }
186
createNativeHandle() const187 virtual native_handle_t *createNativeHandle() const {
188 ALOGD("Cannot create native handle from surface fence");
189 return nullptr;
190 }
191
~SurfaceFenceImpl()192 virtual ~SurfaceFenceImpl() {};
193
SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t waitId)194 SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
195 mSyncMem(syncMem),
196 mPtr(syncMem ? syncMem->mem() : nullptr),
197 mWaitId(syncMem ? waitId : 0) {}
198 private:
199 const std::shared_ptr<const C2SurfaceSyncMemory> mSyncMem; // This is for life-cycle guarantee
200 C2SyncVariables *const mPtr;
201 const uint32_t mWaitId;
202 };
203
C2Fence(std::shared_ptr<Impl> impl)204 C2Fence::C2Fence(std::shared_ptr<Impl> impl) : mImpl(impl) {}
205
CreateSurfaceFence(std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t waitId)206 C2Fence _C2FenceFactory::CreateSurfaceFence(
207 std::shared_ptr<C2SurfaceSyncMemory> syncMem,
208 uint32_t waitId) {
209 if (syncMem) {
210 C2Fence::Impl *p
211 = new _C2FenceFactory::SurfaceFenceImpl(syncMem, waitId);
212 if (p->valid()) {
213 return C2Fence(std::shared_ptr<C2Fence::Impl>(p));
214 } else {
215 delete p;
216 }
217 }
218 return C2Fence();
219 }
220
221 using namespace android;
222
223 /**
224 * Implementation for a sync fence.
225 *
226 * A sync fence is fundamentally a fence that is created from an android sync
227 * fd (which represents a HW fence).
228 *
229 * The native handle layout for a single sync fence is:
230 * fd[0] - sync fd
231 * int[0] - magic (SYNC_FENCE_MAGIC (=`\302fso'))
232 *
233 * Note: Between Android T and 24Q3, the magic number was erroneously
234 * SYNC_FENCE (=3).
235 *
236 * Multi(ple) Sync Fences
237 *
238 * Since Android 24Q3, this implementation also supports a sequence of
239 * sync fences. When this is the case, there is an expectation that the last
240 * sync fence being ready will guarantee that all other sync fences are
241 * also ready. (This guarantees backward compatibility to a single fd sync fence,
242 * and mFence will be that final fence.)
243 *
244 * It is furthermore recommended that the fences be in order - either by
245 * expected signaling time, or by the order in which they need to be ready. The
246 * specific ordering is not specified or enforced, but it could be an
247 * implementation requirement of the specific use case in the future.
248 *
249 * This implementation also supports an unordered set of sync fences. In this
250 * case, it will merge all the fences into a single merged fence, which will
251 * be the backward compatible singular fence (stored in mFence).
252 *
253 * The native handle layout for an unordered multi-fence sync fence (from Android
254 * 24Q3) is:
255 *
256 * fd[0] - sync fd 1
257 * ...
258 * fd[n-1] - sync fd N
259 * fd[n] - merged fence fd
260 * int[0] - magic (SYNC_FENCE_UNORDERED_MAGIC (='\302fsu'))
261 *
262 * The native handle layout for an ordered multi-fence sync fence (from Android
263 * 24Q3) is:
264 *
265 * fd[0] - sync fd 1
266 * ...
267 * fd[n-1] - sync fd N
268 * int[0] - magic (SYNC_FENCE_MAGIC (='\302fso'))
269 */
270 class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
271 public:
wait(c2_nsecs_t timeoutNs)272 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
273 int64_t timeoutMs = timeoutNs / 1000000;
274 if (timeoutMs > INT_MAX) {
275 timeoutMs = INT_MAX;
276 }
277 switch (mFence->wait((int)timeoutMs)) {
278 case NO_ERROR:
279 return C2_OK;
280 case -ETIME:
281 return C2_TIMED_OUT;
282 default:
283 return C2_CORRUPTED;
284 }
285 }
286
valid() const287 virtual bool valid() const {
288 return (mFence && (mFence->getStatus() != Fence::Status::Invalid));
289 }
290
ready() const291 virtual bool ready() const {
292 return mFence->getStatus() == Fence::Status::Signaled;
293 }
294
fd() const295 virtual int fd() const {
296 return mFence->dup();
297 }
298
299 /**
300 * Returns a duped list of fds used when creating this fence. It will
301 * not return the internally created merged fence fd.
302 */
fds() const303 std::vector<int> fds() const {
304 std::vector<int> retFds;
305 for (int index = 0; index < mListFences.size(); index++) {
306 retFds.push_back(mListFences[index]->dup());
307 }
308 // ensure that at least one fd is returned
309 if (mListFences.empty()) {
310 retFds.push_back(mFence->dup());
311 }
312 return retFds;
313 }
314
isHW() const315 virtual bool isHW() const {
316 return true;
317 }
318
type() const319 virtual type_t type() const {
320 return SYNC_FENCE;
321 }
322
createNativeHandle() const323 virtual native_handle_t *createNativeHandle() const {
324 std::vector<int> nativeFds = fds();
325 int32_t magic = SYNC_FENCE_MAGIC;
326
327 // Also parcel the singular fence if it is not already part of the list.
328 // If this was a single-fd fence, mListFences will be empty, but fds()
329 // already returned that a list with that single fd.
330 if (!mListFences.empty() && mListFences.back() != mFence) {
331 nativeFds.push_back(fd());
332 if (!mListFences.empty()) {
333 magic = SYNC_FENCE_UNORDERED_MAGIC;
334 }
335 }
336
337 native_handle_t* nh = native_handle_create(nativeFds.size(), 1);
338 if (!nh) {
339 ALOGE("Failed to allocate native handle for sync fence");
340 for (int fd : nativeFds) {
341 close(fd);
342 }
343 return nullptr;
344 }
345
346 for (int i = 0; i < nativeFds.size(); i++) {
347 nh->data[i] = nativeFds[i];
348 }
349 nh->data[nativeFds.size()] = magic;
350 return nh;
351 }
352
~SyncFenceImpl()353 virtual ~SyncFenceImpl() {};
354
355 /**
356 * Constructs a SyncFenceImpl from a single sync fd. No error checking is
357 * performed on the fd here as we cannot make this a null fence.
358 *
359 * \param fenceFd the fence fd to create the SyncFenceImpl from.
360 */
SyncFenceImpl(int fenceFd)361 SyncFenceImpl(int fenceFd) :
362 mFence(sp<Fence>::make(fenceFd)) {
363 }
364
SyncFenceImpl(const sp<Fence> & fence)365 SyncFenceImpl(const sp<Fence> &fence) :
366 mFence(fence) {
367 }
368
369 /**
370 * Constructs a SyncFenceImpl from a list of sync fds.
371 *
372 * \param fenceFds the list of fence fds to create the SyncFenceImpl from.
373 * \param finalFence the singular fence for this multi-fd fence. This can
374 * be either the last fence in fences or a sepearate (merged) fence.
375 */
SyncFenceImpl(const std::vector<sp<Fence>> & fences,const sp<Fence> & finalFence)376 SyncFenceImpl(const std::vector<sp<Fence>>& fences, const sp<Fence> &finalFence) :
377 mListFences(fences),
378 mFence(finalFence) {
379 }
380
381 /**
382 * Creates a SyncFenceImpl from a native handle.
383 *
384 * \param nh the native handle to create the SyncFenceImpl from.
385 * \param takeOwnership if true, the SyncFenceImpl will take ownership of the
386 * file descriptors in the native handle. Otherwise,
387 * the SyncFenceImpl will dup the file descriptors.
388 *
389 * \return a shared_ptr to the SyncFenceImpl, or nullptr if the native
390 * handle is invalid or malformed.
391 */
CreateFromNativeHandle(const native_handle_t * nh,bool takeOwnership)392 static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(
393 const native_handle_t* nh, bool takeOwnership) {
394 // we should only call this method if _C2FenceFactory::GetTypeFromNativeHandle
395 // returned SYNC_FENCE, but do these checks anyways to avoid overflows
396 // in case that does not happen.
397 if (!nh) {
398 ALOGE("Invalid handle for a sync fence (nullptr)");
399 return nullptr;
400 } else if (nh->numFds < 1 || nh->numInts < 1
401 || nh->numFds > MAX_FENCE_FDS || nh->numInts > MAX_FENCE_INTS) {
402 ALOGE("Invalid handle for a sync fence (%d fds, %d ints)", nh->numFds, nh->numInts);
403 return nullptr;
404 }
405 std::vector<sp<Fence>> fences;
406 for (int i = 0; i < nh->numFds; i++) {
407 int fd = nh->data[i];
408 if (!takeOwnership && fd >= 0) {
409 fd = dup(fd);
410 }
411 if (fd >= 0) {
412 sp<Fence> fence = sp<Fence>::make(fd);
413 if (fence) {
414 fences.push_back(fence);
415 } else {
416 ALOGW("Failed to create fence from fd %d", fd);
417 }
418 }
419 }
420
421 std::shared_ptr<SyncFenceImpl> p;
422 if (fences.size() == 0) {
423 ALOGE("No valid fences found in handle for a sync fence");
424 return nullptr;
425 } else if (fences.size() == 1) {
426 p = std::make_shared<SyncFenceImpl>(fences[0]);
427 } else {
428 int32_t magic = nh->data[nh->numFds + nh->numInts - 1];
429 if (magic != SYNC_FENCE_MAGIC) {
430 // The last fence is the merged fence. Separate it.
431 sp<Fence> finalFence = fences.back();
432 fences.pop_back();
433
434 // Special case: if we end up with only a single element list
435 // with another merged fence, that merged fence must be the
436 // same fence. This happened in an early version of multi fd
437 // support for single-fd sync fences.
438 if (fences.size() == 1) {
439 // For single-fd fence the sp-s must be equal
440 finalFence = fences.back();
441 }
442 p = std::make_shared<SyncFenceImpl>(fences, finalFence);
443 } else {
444 // Use the last fence as the standalone fence.
445 p = std::make_shared<SyncFenceImpl>(fences, fences.back());
446 }
447 }
448
449 ALOGE_IF(!p, "Failed to allocate sync fence impl");
450 return p;
451 }
452
453 private:
454 /**
455 * The list of fences in case of a multi-fence sync fence. Otherwise, this
456 * list is empty.
457 */
458 std::vector<sp<Fence>> mListFences;
459
460 /**
461 * The singular fence for this sync fence. For multi-fence sync fences,
462 * this could be a merged fence, or simply the final fence.
463 */
464 sp<Fence> mFence;
465 };
466
ExtractFdsFromCodec2SyncFence(const C2Fence & fence)467 std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence) {
468 std::vector<int> retFds;
469 if ((fence.mImpl) && (fence.mImpl->type() == C2Fence::Impl::SYNC_FENCE)) {
470 retFds = static_cast<_C2FenceFactory::SyncFenceImpl *>(fence.mImpl.get())->fds();
471 }
472 return retFds;
473 }
474
CreateSyncFence(int fenceFd,bool validate)475 C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd, bool validate) {
476 std::shared_ptr<C2Fence::Impl> p;
477 if (fenceFd >= 0) {
478 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFd);
479 if (!p) {
480 ALOGE("Failed to allocate sync fence impl");
481 close(fenceFd);
482 } else if (validate && (!p->valid() || p->ready())) {
483 // don't create a fence object if the sync fd already signaled or is invalid
484 p.reset();
485 }
486 } else {
487 ALOGV("Won't create sync fence from invalid fd");
488 }
489 return C2Fence(p);
490 }
491
CreateUnorderedMultiSyncFence(const std::vector<int> & fenceFds,c2_status_t * status)492 C2Fence _C2FenceFactory::CreateUnorderedMultiSyncFence(
493 const std::vector<int>& fenceFds, c2_status_t *status) {
494 if (status) {
495 *status = C2_OK;
496 }
497
498 sp<Fence> finalFence;
499 std::vector<sp<Fence>> fences;
500
501 bool mergeFailed = false;
502 for (int fenceFd : fenceFds) {
503 if (fenceFd < 0) {
504 // ignore invalid fences
505 continue;
506 }
507 sp<Fence> fence = sp<Fence>::make(fenceFd);
508
509 // If we could not create an sp, further sp-s will also fail.
510 if (fence == nullptr) {
511 if (status) {
512 *status = C2_NO_MEMORY;
513 }
514 break;
515 }
516 fences.push_back(fence);
517
518 if (finalFence == nullptr) {
519 finalFence = fence;
520 } else {
521 sp<Fence> mergedFence = Fence::merge("syncFence", finalFence, fence);
522 if (mergedFence == nullptr || mergedFence == Fence::NO_FENCE) {
523 ALOGE_IF(!mergeFailed, "Could not merge fences for sync fence.");
524 mergeFailed = true;
525 if (status) {
526 *status = (mergedFence == nullptr) ? C2_NO_MEMORY : C2_CORRUPTED;
527 }
528
529 if (mergedFence == nullptr) {
530 break;
531 }
532 // If we cannot merge one of the fences, the best course of action
533 // is to keep going, as the alternative would be to clear all fences
534 // (making this a null fence) but that will always be ready.
535 } else {
536 finalFence = mergedFence;
537 }
538 }
539 }
540
541 // we may have ended up with a single or no fence due to merging failures or
542 // invalid fds.
543 if (fences.size() == 0) {
544 // we have no fds, we have a null fence.
545 return C2Fence();
546 }
547
548 std::shared_ptr<C2Fence::Impl> p;
549
550 if (fences.size() == 1) {
551 // We have a single sync fd. We don't need the merged fence, which is
552 // already simply that sole fence.
553 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(finalFence);
554 } else {
555 // if we couldn't merge any fences just use the last one
556 if (finalFence == fences[0]) {
557 finalFence = fences.back();
558 }
559
560 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fences, finalFence);
561 }
562
563 if (!p) {
564 ALOGE("Failed to allocate sync fence impl closing FDs");
565 // all fds were moved into Fence objects which will close them.
566 if (status) {
567 *status = C2_NO_MEMORY;
568 }
569 return C2Fence();
570 }
571
572 return C2Fence(p);
573 }
574
CreateMultiSyncFence(const std::vector<int> & fenceFds,c2_status_t * status)575 C2Fence _C2FenceFactory::CreateMultiSyncFence(
576 const std::vector<int>& fenceFds, c2_status_t *status) {
577 if (status) {
578 *status = C2_OK;
579 }
580
581 std::vector<sp<Fence>> fences;
582
583 for (int fenceFd : fenceFds) {
584 if (fenceFd < 0) {
585 // ignore invalid fences
586 continue;
587 }
588 sp<Fence> fence = sp<Fence>::make(fenceFd);
589
590 // If we could not create an sp, keep going with the existing fences.
591 if (fence == nullptr) {
592 if (status) {
593 *status = C2_NO_MEMORY;
594 }
595 break;
596 }
597 fences.push_back(fence);
598 }
599
600 // we may have ended up with a single or no fence due to invalid fds.
601 if (fences.size() == 0) {
602 // we have no fds, we have a null fence.
603 return C2Fence();
604 }
605
606 std::shared_ptr<C2Fence::Impl> p;
607
608 if (fences.size() == 1) {
609 // We have a single sync fd, this is a simple sync fence.
610 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fences[0]);
611 } else {
612 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fences, fences.back());
613 }
614
615 if (!p) {
616 ALOGE("Failed to allocate sync fence impl closing FDs");
617 // all fds were moved into Fence objects which will close them.
618 if (status) {
619 *status = C2_NO_MEMORY;
620 }
621 return C2Fence();
622 }
623
624 return C2Fence(p);
625 }
626
627 /**
628 * Fence implementation for notifying # of events available based on
629 * file descriptors created by pipe()/pipe2(). The writing end of the
630 * file descriptors is used to create the implementation.
631 * The implementation supports all C2Fence interface.
632 */
633 class _C2FenceFactory::PipeFenceImpl: public C2Fence::Impl {
634 private:
635 // Wait for an event using ::ppoll() and handle any interruptions by signals
636 // (EINTR) by retrying and accounting for time already waited.
637 // Note: while ppoll in theory supports blocking signals, Linux NPTL library does
638 // not allow blocking 2 realtime signals (see man nptl), so we do need to handle
639 // signal interruptions.
waitEvent(c2_nsecs_t timeoutNs,bool * hangUp) const640 bool waitEvent(c2_nsecs_t timeoutNs, bool *hangUp) const {
641 if (!mValid) {
642 *hangUp = true;
643 return false;
644 }
645
646 int64_t waitTimeNs = kPipeFenceWaitLimitSecs * 1000000000LL;
647 if (timeoutNs >= 0) {
648 waitTimeNs = timeoutNs;
649 } else {
650 ALOGD("polling for indefinite duration requested, but changed to wait for %d sec",
651 kPipeFenceWaitLimitSecs);
652 }
653
654 int64_t startTsNs = android::elapsedRealtimeNano();
655 int64_t elapsedTsNs = 0;
656 int tryNum = 0;
657 int noEvent = 0;
658 do {
659 struct pollfd pfd;
660 pfd.fd = mPipeFd.get();
661 pfd.events = POLLIN;
662 pfd.revents = 0;
663 struct timespec ts;
664
665 ts.tv_sec = int((waitTimeNs - elapsedTsNs) / 1000000000);
666 ts.tv_nsec = (waitTimeNs - elapsedTsNs) % 1000000000;
667 ++tryNum;
668 int ret = ::ppoll(&pfd, 1, &ts, nullptr);
669 if (ret >= 0) {
670 if (pfd.revents) {
671 if (pfd.revents & ~POLLIN) {
672 // Mostly this means the writing end fd was closed.
673 *hangUp = true;
674 mValid = false;
675 ALOGD("PipeFenceImpl: pipe fd hangup or err event returned");
676 return false;
677 }
678 return true;
679 }
680 ++noEvent;
681 // retry if the deadline does not meet yet.
682 } else if (errno != EINTR) {
683 ALOGE("PipeFenceImpl: poll() error %d", errno);
684 *hangUp = true;
685 mValid = false;
686 return false;
687 }
688 elapsedTsNs = android::elapsedRealtimeNano() - startTsNs;
689 } while (elapsedTsNs < waitTimeNs);
690 // EINTR till the end.
691 // treat this as event not ready yet.
692 ALOGV("PipeFenceImpl: tried %d times NoEvent %d times, spent %lld nanosecs",
693 tryNum, noEvent, (long long)elapsedTsNs);
694 return false;
695 }
696
697 public:
wait(c2_nsecs_t timeoutNs)698 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
699 if (!mValid) {
700 return C2_BAD_STATE;
701 }
702 bool hangUp = false;
703 bool event = waitEvent(timeoutNs, &hangUp);
704 if (hangUp) {
705 return C2_BAD_STATE;
706 }
707 if (event) {
708 return C2_OK;
709 }
710 return C2_TIMED_OUT;
711 }
712
valid() const713 virtual bool valid() const {
714 if (!mValid) {
715 return false;
716 }
717 bool hangUp = false;
718 (void)waitEvent(0, &hangUp);
719 return !hangUp;
720 }
721
ready() const722 virtual bool ready() const {
723 if (!mValid) {
724 return false;
725 }
726 bool hangUp = false;
727 bool event = waitEvent(0, &hangUp);
728 return event;
729 }
730
fd() const731 virtual int fd() const {
732 if (!mValid) {
733 return -1;
734 }
735 return ::dup(mPipeFd.get());
736 }
737
isHW() const738 virtual bool isHW() const {
739 return false;
740 }
741
type() const742 virtual type_t type() const {
743 return PIPE_FENCE;
744 }
745
createNativeHandle() const746 virtual native_handle_t *createNativeHandle() const {
747 // This is not supported.
748 return nullptr;
749 }
750
751 virtual ~PipeFenceImpl() = default;
752
PipeFenceImpl(int fd)753 PipeFenceImpl(int fd) : mPipeFd(fd) {
754 mValid = (mPipeFd.get() >= 0);
755 }
756
PipeFenceImpl(::android::base::unique_fd && ufd)757 PipeFenceImpl(::android::base::unique_fd &&ufd) : mPipeFd{std::move(ufd)} {
758 mValid = (mPipeFd.get() >= 0);
759 }
760
761 private:
762 friend struct _C2FenceFactory;
763 static constexpr int kPipeFenceWaitLimitSecs = 5;
764
765 mutable std::atomic<bool> mValid;
766 const ::android::base::unique_fd mPipeFd;
767 };
768
CreatePipeFence(int fd)769 C2Fence _C2FenceFactory::CreatePipeFence(int fd) {
770 ::android::base::unique_fd ufd{fd};
771 return CreatePipeFence(std::move(ufd));
772 }
773
CreatePipeFence(::android::base::unique_fd && ufd)774 C2Fence _C2FenceFactory::CreatePipeFence(::android::base::unique_fd &&ufd) {
775 std::shared_ptr<_C2FenceFactory::PipeFenceImpl> impl =
776 std::make_shared<_C2FenceFactory::PipeFenceImpl>(std::move(ufd));
777 std::shared_ptr<C2Fence::Impl> p = std::static_pointer_cast<C2Fence::Impl>(impl);
778 if (!p) {
779 ALOGE("PipeFence creation failure");
780 } else if (!impl->mValid) {
781 p.reset();
782 }
783 return C2Fence(p);
784 }
785
CreateNativeHandle(const C2Fence & fence)786 native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
787 return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
788 }
789
CreateFromNativeHandle(const native_handle_t * handle,bool takeOwnership)790 C2Fence _C2FenceFactory::CreateFromNativeHandle(
791 const native_handle_t* handle, bool takeOwnership) {
792 if (!handle) {
793 return C2Fence();
794 }
795 C2Fence::Impl::type_t type = C2Fence::Impl::GetTypeFromNativeHandle(handle);
796 std::shared_ptr<C2Fence::Impl> p;
797 switch (type) {
798 case C2Fence::Impl::SYNC_FENCE:
799 p = SyncFenceImpl::CreateFromNativeHandle(handle, takeOwnership);
800 break;
801 default:
802 ALOGV("Unsupported fence type %d", type);
803 // Still close the handle here if taking ownership.
804 if (takeOwnership) {
805 (void) native_handle_close(handle);
806 }
807 // return a null-fence in this case
808 break;
809 }
810 if (p && !p->valid()) {
811 p.reset();
812 }
813 return C2Fence(p);
814 }
815
816