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