• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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