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