• 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 <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