1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "AndroidHardwareBuffer.h"
8 
9 #include <dlfcn.h>
10 
11 #include "mozilla/gfx/2D.h"
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/layers/ImageBridgeChild.h"
14 #include "mozilla/layers/TextureClientSharedSurface.h"
15 #include "mozilla/TimeStamp.h"
16 #include "mozilla/UniquePtrExtensions.h"
17 
18 namespace mozilla {
19 namespace layers {
20 
ToAHardwareBuffer_Format(gfx::SurfaceFormat aFormat)21 static uint32_t ToAHardwareBuffer_Format(gfx::SurfaceFormat aFormat) {
22   switch (aFormat) {
23     case gfx::SurfaceFormat::R8G8B8A8:
24     case gfx::SurfaceFormat::B8G8R8A8:
25       return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
26 
27     case gfx::SurfaceFormat::R8G8B8X8:
28     case gfx::SurfaceFormat::B8G8R8X8:
29       return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
30 
31     case gfx::SurfaceFormat::R5G6B5_UINT16:
32       return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
33 
34     default:
35       MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceFormat");
36       return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
37   }
38 }
39 
40 StaticAutoPtr<AndroidHardwareBufferApi> AndroidHardwareBufferApi::sInstance;
41 
42 /* static */
Init()43 void AndroidHardwareBufferApi::Init() {
44   sInstance = new AndroidHardwareBufferApi();
45   if (!sInstance->Load()) {
46     sInstance = nullptr;
47   }
48 }
49 
50 /* static */
Shutdown()51 void AndroidHardwareBufferApi::Shutdown() { sInstance = nullptr; }
52 
AndroidHardwareBufferApi()53 AndroidHardwareBufferApi::AndroidHardwareBufferApi() {}
54 
Load()55 bool AndroidHardwareBufferApi::Load() {
56   void* handle = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
57   MOZ_ASSERT(handle);
58   if (!handle) {
59     gfxCriticalNote << "Failed to load libandroid.so";
60     return false;
61   }
62 
63   mAHardwareBuffer_allocate =
64       (_AHardwareBuffer_allocate)dlsym(handle, "AHardwareBuffer_allocate");
65   mAHardwareBuffer_acquire =
66       (_AHardwareBuffer_acquire)dlsym(handle, "AHardwareBuffer_acquire");
67   mAHardwareBuffer_release =
68       (_AHardwareBuffer_release)dlsym(handle, "AHardwareBuffer_release");
69   mAHardwareBuffer_describe =
70       (_AHardwareBuffer_describe)dlsym(handle, "AHardwareBuffer_describe");
71   mAHardwareBuffer_lock =
72       (_AHardwareBuffer_lock)dlsym(handle, "AHardwareBuffer_lock");
73   mAHardwareBuffer_unlock =
74       (_AHardwareBuffer_unlock)dlsym(handle, "AHardwareBuffer_unlock");
75   mAHardwareBuffer_sendHandleToUnixSocket =
76       (_AHardwareBuffer_sendHandleToUnixSocket)dlsym(
77           handle, "AHardwareBuffer_sendHandleToUnixSocket");
78   mAHardwareBuffer_recvHandleFromUnixSocket =
79       (_AHardwareBuffer_recvHandleFromUnixSocket)dlsym(
80           handle, "AHardwareBuffer_recvHandleFromUnixSocket");
81 
82   if (!mAHardwareBuffer_allocate || !mAHardwareBuffer_acquire ||
83       !mAHardwareBuffer_release || !mAHardwareBuffer_describe ||
84       !mAHardwareBuffer_lock || !mAHardwareBuffer_unlock ||
85       !mAHardwareBuffer_sendHandleToUnixSocket ||
86       !mAHardwareBuffer_recvHandleFromUnixSocket) {
87     gfxCriticalNote << "Failed to load AHardwareBuffer";
88     return false;
89   }
90   return true;
91 }
92 
Allocate(const AHardwareBuffer_Desc * aDesc,AHardwareBuffer ** aOutBuffer)93 void AndroidHardwareBufferApi::Allocate(const AHardwareBuffer_Desc* aDesc,
94                                         AHardwareBuffer** aOutBuffer) {
95   mAHardwareBuffer_allocate(aDesc, aOutBuffer);
96 }
97 
Acquire(AHardwareBuffer * aBuffer)98 void AndroidHardwareBufferApi::Acquire(AHardwareBuffer* aBuffer) {
99   mAHardwareBuffer_acquire(aBuffer);
100 }
101 
Release(AHardwareBuffer * aBuffer)102 void AndroidHardwareBufferApi::Release(AHardwareBuffer* aBuffer) {
103   mAHardwareBuffer_release(aBuffer);
104 }
105 
Describe(const AHardwareBuffer * aBuffer,AHardwareBuffer_Desc * aOutDesc)106 void AndroidHardwareBufferApi::Describe(const AHardwareBuffer* aBuffer,
107                                         AHardwareBuffer_Desc* aOutDesc) {
108   mAHardwareBuffer_describe(aBuffer, aOutDesc);
109 }
110 
Lock(AHardwareBuffer * aBuffer,uint64_t aUsage,int32_t aFence,const ARect * aRect,void ** aOutVirtualAddress)111 int AndroidHardwareBufferApi::Lock(AHardwareBuffer* aBuffer, uint64_t aUsage,
112                                    int32_t aFence, const ARect* aRect,
113                                    void** aOutVirtualAddress) {
114   return mAHardwareBuffer_lock(aBuffer, aUsage, aFence, aRect,
115                                aOutVirtualAddress);
116 }
117 
Unlock(AHardwareBuffer * aBuffer,int32_t * aFence)118 int AndroidHardwareBufferApi::Unlock(AHardwareBuffer* aBuffer,
119                                      int32_t* aFence) {
120   return mAHardwareBuffer_unlock(aBuffer, aFence);
121 }
122 
SendHandleToUnixSocket(const AHardwareBuffer * aBuffer,int aSocketFd)123 int AndroidHardwareBufferApi::SendHandleToUnixSocket(
124     const AHardwareBuffer* aBuffer, int aSocketFd) {
125   return mAHardwareBuffer_sendHandleToUnixSocket(aBuffer, aSocketFd);
126 }
127 
RecvHandleFromUnixSocket(int aSocketFd,AHardwareBuffer ** aOutBuffer)128 int AndroidHardwareBufferApi::RecvHandleFromUnixSocket(
129     int aSocketFd, AHardwareBuffer** aOutBuffer) {
130   return mAHardwareBuffer_recvHandleFromUnixSocket(aSocketFd, aOutBuffer);
131 }
132 
133 /* static */
GetNextId()134 uint64_t AndroidHardwareBuffer::GetNextId() {
135   static std::atomic<uint64_t> sNextId = 0;
136   uint64_t id = ++sNextId;
137   return id;
138 }
139 
140 /* static */
Create(gfx::IntSize aSize,gfx::SurfaceFormat aFormat)141 already_AddRefed<AndroidHardwareBuffer> AndroidHardwareBuffer::Create(
142     gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
143   if (!AndroidHardwareBufferApi::Get()) {
144     return nullptr;
145   }
146 
147   if (aFormat != gfx::SurfaceFormat::R8G8B8A8 &&
148       aFormat != gfx::SurfaceFormat::R8G8B8X8 &&
149       aFormat != gfx::SurfaceFormat::B8G8R8A8 &&
150       aFormat != gfx::SurfaceFormat::B8G8R8X8 &&
151       aFormat != gfx::SurfaceFormat::R5G6B5_UINT16) {
152     return nullptr;
153   }
154 
155   AHardwareBuffer_Desc desc = {};
156   desc.width = aSize.width;
157   desc.height = aSize.height;
158   desc.layers = 1;  // number of images
159   desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
160                AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
161                AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
162                AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
163   desc.format = ToAHardwareBuffer_Format(aFormat);
164 
165   AHardwareBuffer* nativeBuffer = nullptr;
166   AndroidHardwareBufferApi::Get()->Allocate(&desc, &nativeBuffer);
167   if (!nativeBuffer) {
168     return nullptr;
169   }
170 
171   AHardwareBuffer_Desc bufferInfo = {};
172   AndroidHardwareBufferApi::Get()->Describe(nativeBuffer, &bufferInfo);
173 
174   RefPtr<AndroidHardwareBuffer> buffer = new AndroidHardwareBuffer(
175       nativeBuffer, aSize, bufferInfo.stride, aFormat, GetNextId());
176   AndroidHardwareBufferManager::Get()->Register(buffer);
177   return buffer.forget();
178 }
179 
180 /* static */
181 already_AddRefed<AndroidHardwareBuffer>
FromFileDescriptor(ipc::FileDescriptor & aFileDescriptor,uint64_t aBufferId,gfx::IntSize aSize,gfx::SurfaceFormat aFormat)182 AndroidHardwareBuffer::FromFileDescriptor(ipc::FileDescriptor& aFileDescriptor,
183                                           uint64_t aBufferId,
184                                           gfx::IntSize aSize,
185                                           gfx::SurfaceFormat aFormat) {
186   if (!aFileDescriptor.IsValid()) {
187     gfxCriticalNote << "AndroidHardwareBuffer invalid FileDescriptor";
188     return nullptr;
189   }
190 
191   ipc::FileDescriptor& fileDescriptor =
192       const_cast<ipc::FileDescriptor&>(aFileDescriptor);
193   auto rawFD = fileDescriptor.TakePlatformHandle();
194   AHardwareBuffer* nativeBuffer = nullptr;
195   int ret = AndroidHardwareBufferApi::Get()->RecvHandleFromUnixSocket(
196       rawFD.get(), &nativeBuffer);
197   if (ret < 0) {
198     gfxCriticalNote << "RecvHandleFromUnixSocket failed";
199     return nullptr;
200   }
201 
202   AHardwareBuffer_Desc bufferInfo = {};
203   AndroidHardwareBufferApi::Get()->Describe(nativeBuffer, &bufferInfo);
204 
205   RefPtr<AndroidHardwareBuffer> buffer = new AndroidHardwareBuffer(
206       nativeBuffer, aSize, bufferInfo.stride, aFormat, aBufferId);
207   return buffer.forget();
208 }
209 
AndroidHardwareBuffer(AHardwareBuffer * aNativeBuffer,gfx::IntSize aSize,uint32_t aStride,gfx::SurfaceFormat aFormat,uint64_t aId)210 AndroidHardwareBuffer::AndroidHardwareBuffer(AHardwareBuffer* aNativeBuffer,
211                                              gfx::IntSize aSize,
212                                              uint32_t aStride,
213                                              gfx::SurfaceFormat aFormat,
214                                              uint64_t aId)
215     : mSize(aSize),
216       mStride(aStride),
217       mFormat(aFormat),
218       mId(aId),
219       mNativeBuffer(aNativeBuffer),
220       mIsRegistered(false) {
221   MOZ_ASSERT(mNativeBuffer);
222 #ifdef DEBUG
223   AHardwareBuffer_Desc bufferInfo = {};
224   AndroidHardwareBufferApi::Get()->Describe(mNativeBuffer, &bufferInfo);
225   MOZ_ASSERT(mSize.width == (int32_t)bufferInfo.width);
226   MOZ_ASSERT(mSize.height == (int32_t)bufferInfo.height);
227   MOZ_ASSERT(mStride == bufferInfo.stride);
228   MOZ_ASSERT(ToAHardwareBuffer_Format(mFormat) == bufferInfo.format);
229 #endif
230 }
231 
~AndroidHardwareBuffer()232 AndroidHardwareBuffer::~AndroidHardwareBuffer() {
233   if (mIsRegistered) {
234     AndroidHardwareBufferManager::Get()->Unregister(this);
235   }
236   AndroidHardwareBufferApi::Get()->Release(mNativeBuffer);
237 }
238 
Lock(uint64_t aUsage,const ARect * aRect,void ** aOutVirtualAddress)239 int AndroidHardwareBuffer::Lock(uint64_t aUsage, const ARect* aRect,
240                                 void** aOutVirtualAddress) {
241   ipc::FileDescriptor fd = GetAndResetReleaseFence();
242   int32_t fenceFd = -1;
243   ipc::FileDescriptor::UniquePlatformHandle rawFd;
244   if (fd.IsValid()) {
245     rawFd = fd.TakePlatformHandle();
246     fenceFd = rawFd.get();
247   }
248   return AndroidHardwareBufferApi::Get()->Lock(mNativeBuffer, aUsage, fenceFd,
249                                                aRect, aOutVirtualAddress);
250 }
251 
Unlock()252 int AndroidHardwareBuffer::Unlock() {
253   int rawFd = -1;
254   // XXX All tested recent Android devices did not return valid fence.
255   int ret = AndroidHardwareBufferApi::Get()->Unlock(mNativeBuffer, &rawFd);
256   if (ret != 0) {
257     return ret;
258   }
259 
260   ipc::FileDescriptor acquireFenceFd;
261   // The value -1 indicates that unlocking has already completed before
262   // the function returned and no further operations are necessary.
263   if (rawFd >= 0) {
264     acquireFenceFd = ipc::FileDescriptor(UniqueFileHandle(rawFd));
265   }
266 
267   if (acquireFenceFd.IsValid()) {
268     SetAcquireFence(std::move(acquireFenceFd));
269   }
270   return 0;
271 }
272 
SendHandleToUnixSocket(int aSocketFd)273 int AndroidHardwareBuffer::SendHandleToUnixSocket(int aSocketFd) {
274   return AndroidHardwareBufferApi::Get()->SendHandleToUnixSocket(mNativeBuffer,
275                                                                  aSocketFd);
276 }
277 
SetLastFwdTransactionId(uint64_t aFwdTransactionId,bool aUsesImageBridge,const MonitorAutoLock & aAutoLock)278 void AndroidHardwareBuffer::SetLastFwdTransactionId(
279     uint64_t aFwdTransactionId, bool aUsesImageBridge,
280     const MonitorAutoLock& aAutoLock) {
281   if (mTransactionId.isNothing()) {
282     mTransactionId =
283         Some(FwdTransactionId(aFwdTransactionId, aUsesImageBridge));
284     return;
285   }
286   MOZ_RELEASE_ASSERT(mTransactionId.ref().mUsesImageBridge == aUsesImageBridge);
287   MOZ_RELEASE_ASSERT(mTransactionId.ref().mId <= aFwdTransactionId);
288 
289   mTransactionId.ref().mId = aFwdTransactionId;
290 }
291 
GetLastFwdTransactionId(const MonitorAutoLock & aAutoLock)292 uint64_t AndroidHardwareBuffer::GetLastFwdTransactionId(
293     const MonitorAutoLock& aAutoLock) {
294   if (mTransactionId.isNothing()) {
295     MOZ_ASSERT_UNREACHABLE("unexpected to be called");
296     return 0;
297   }
298   return mTransactionId.ref().mId;
299 }
300 
SetReleaseFence(ipc::FileDescriptor && aFenceFd)301 void AndroidHardwareBuffer::SetReleaseFence(ipc::FileDescriptor&& aFenceFd) {
302   MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor());
303   SetReleaseFence(std::move(aFenceFd), lock);
304 }
305 
SetReleaseFence(ipc::FileDescriptor && aFenceFd,const MonitorAutoLock & aAutoLock)306 void AndroidHardwareBuffer::SetReleaseFence(ipc::FileDescriptor&& aFenceFd,
307                                             const MonitorAutoLock& aAutoLock) {
308   mReleaseFenceFd = std::move(aFenceFd);
309 }
310 
SetAcquireFence(ipc::FileDescriptor && aFenceFd)311 void AndroidHardwareBuffer::SetAcquireFence(ipc::FileDescriptor&& aFenceFd) {
312   MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor());
313 
314   mAcquireFenceFd = std::move(aFenceFd);
315 }
316 
GetAndResetReleaseFence()317 ipc::FileDescriptor AndroidHardwareBuffer::GetAndResetReleaseFence() {
318   MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor());
319 
320   if (!mReleaseFenceFd.IsValid()) {
321     return ipc::FileDescriptor();
322   }
323 
324   return std::move(mReleaseFenceFd);
325 }
326 
GetAndResetAcquireFence()327 ipc::FileDescriptor AndroidHardwareBuffer::GetAndResetAcquireFence() {
328   MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor());
329 
330   if (!mAcquireFenceFd.IsValid()) {
331     return ipc::FileDescriptor();
332   }
333 
334   return std::move(mAcquireFenceFd);
335 }
336 
GetAcquireFence()337 ipc::FileDescriptor AndroidHardwareBuffer::GetAcquireFence() {
338   MonitorAutoLock lock(AndroidHardwareBufferManager::Get()->GetMonitor());
339 
340   if (!mAcquireFenceFd.IsValid()) {
341     return ipc::FileDescriptor();
342   }
343 
344   return mAcquireFenceFd;
345 }
346 
WaitForBufferOwnership()347 bool AndroidHardwareBuffer::WaitForBufferOwnership() {
348   return AndroidHardwareBufferManager::Get()->WaitForBufferOwnership(this);
349 }
350 
IsWaitingForBufferOwnership()351 bool AndroidHardwareBuffer::IsWaitingForBufferOwnership() {
352   return AndroidHardwareBufferManager::Get()->IsWaitingForBufferOwnership(this);
353 }
354 
355 RefPtr<TextureClient>
GetTextureClientOfSharedSurfaceTextureData(const layers::SurfaceDescriptor & aDesc,const gfx::SurfaceFormat aFormat,const gfx::IntSize & aSize,const TextureFlags aFlags,LayersIPCChannel * aAllocator)356 AndroidHardwareBuffer::GetTextureClientOfSharedSurfaceTextureData(
357     const layers::SurfaceDescriptor& aDesc, const gfx::SurfaceFormat aFormat,
358     const gfx::IntSize& aSize, const TextureFlags aFlags,
359     LayersIPCChannel* aAllocator) {
360   if (mTextureClientOfSharedSurfaceTextureData) {
361     return mTextureClientOfSharedSurfaceTextureData;
362   }
363   mTextureClientOfSharedSurfaceTextureData =
364       SharedSurfaceTextureData::CreateTextureClient(aDesc, aFormat, aSize,
365                                                     aFlags, aAllocator);
366   return mTextureClientOfSharedSurfaceTextureData;
367 }
368 
369 StaticAutoPtr<AndroidHardwareBufferManager>
370     AndroidHardwareBufferManager::sInstance;
371 
372 /* static */
Init()373 void AndroidHardwareBufferManager::Init() {
374   sInstance = new AndroidHardwareBufferManager();
375 }
376 
377 /* static */
Shutdown()378 void AndroidHardwareBufferManager::Shutdown() { sInstance = nullptr; }
379 
AndroidHardwareBufferManager()380 AndroidHardwareBufferManager::AndroidHardwareBufferManager()
381     : mMonitor("AndroidHardwareBufferManager.mMonitor") {}
382 
Register(RefPtr<AndroidHardwareBuffer> aBuffer)383 void AndroidHardwareBufferManager::Register(
384     RefPtr<AndroidHardwareBuffer> aBuffer) {
385   MonitorAutoLock lock(mMonitor);
386 
387   aBuffer->mIsRegistered = true;
388   ThreadSafeWeakPtr<AndroidHardwareBuffer> weak(aBuffer);
389 
390 #ifdef DEBUG
391   const auto it = mBuffers.find(aBuffer->mId);
392   MOZ_ASSERT(it == mBuffers.end());
393 #endif
394   mBuffers.emplace(aBuffer->mId, weak);
395 }
396 
Unregister(AndroidHardwareBuffer * aBuffer)397 void AndroidHardwareBufferManager::Unregister(AndroidHardwareBuffer* aBuffer) {
398   MonitorAutoLock lock(mMonitor);
399 
400   const auto it = mBuffers.find(aBuffer->mId);
401   MOZ_ASSERT(it != mBuffers.end());
402   if (it == mBuffers.end()) {
403     gfxCriticalNote << "AndroidHardwareBuffer id mismatch happened";
404     return;
405   }
406   mBuffers.erase(it);
407 }
408 
GetBuffer(uint64_t aBufferId)409 already_AddRefed<AndroidHardwareBuffer> AndroidHardwareBufferManager::GetBuffer(
410     uint64_t aBufferId) {
411   MonitorAutoLock lock(mMonitor);
412 
413   const auto it = mBuffers.find(aBufferId);
414   if (it == mBuffers.end()) {
415     return nullptr;
416   }
417   auto buffer = RefPtr<AndroidHardwareBuffer>(it->second);
418   return buffer.forget();
419 }
420 
WaitForBufferOwnership(AndroidHardwareBuffer * aBuffer)421 bool AndroidHardwareBufferManager::WaitForBufferOwnership(
422     AndroidHardwareBuffer* aBuffer) {
423   MonitorAutoLock lock(mMonitor);
424 
425   if (aBuffer->mTransactionId.isNothing()) {
426     return true;
427   }
428 
429   auto it = mWaitingNotifyNotUsed.find(aBuffer->mId);
430   if (it == mWaitingNotifyNotUsed.end()) {
431     return true;
432   }
433 
434   const double waitWarningTimeoutMs = 300;
435   const double maxTimeoutSec = 3;
436   auto begin = TimeStamp::Now();
437 
438   bool isWaiting = true;
439   while (isWaiting) {
440     TimeDuration timeout = TimeDuration::FromMilliseconds(waitWarningTimeoutMs);
441     CVStatus status = mMonitor.Wait(timeout);
442     if (status == CVStatus::Timeout) {
443       gfxCriticalNoteOnce << "AndroidHardwareBuffer wait is slow";
444     }
445     const auto it = mWaitingNotifyNotUsed.find(aBuffer->mId);
446     if (it == mWaitingNotifyNotUsed.end()) {
447       return true;
448     }
449     auto now = TimeStamp::Now();
450     if ((now - begin).ToSeconds() > maxTimeoutSec) {
451       isWaiting = false;
452       gfxCriticalNote << "AndroidHardwareBuffer wait timeout";
453     }
454   }
455 
456   return false;
457 }
458 
IsWaitingForBufferOwnership(AndroidHardwareBuffer * aBuffer)459 bool AndroidHardwareBufferManager::IsWaitingForBufferOwnership(
460     AndroidHardwareBuffer* aBuffer) {
461   MonitorAutoLock lock(mMonitor);
462 
463   if (aBuffer->mTransactionId.isNothing()) {
464     return false;
465   }
466 
467   auto it = mWaitingNotifyNotUsed.find(aBuffer->mId);
468   if (it == mWaitingNotifyNotUsed.end()) {
469     return false;
470   }
471   return true;
472 }
473 
HoldUntilNotifyNotUsed(uint64_t aBufferId,uint64_t aFwdTransactionId,bool aUsesImageBridge)474 void AndroidHardwareBufferManager::HoldUntilNotifyNotUsed(
475     uint64_t aBufferId, uint64_t aFwdTransactionId, bool aUsesImageBridge) {
476   MOZ_ASSERT(NS_IsMainThread() || InImageBridgeChildThread());
477 
478   const auto it = mBuffers.find(aBufferId);
479   if (it == mBuffers.end()) {
480     return;
481   }
482   auto buffer = RefPtr<AndroidHardwareBuffer>(it->second);
483 
484   MonitorAutoLock lock(mMonitor);
485   buffer->SetLastFwdTransactionId(aFwdTransactionId, aUsesImageBridge, lock);
486   mWaitingNotifyNotUsed.emplace(aBufferId, buffer);
487 }
488 
NotifyNotUsed(ipc::FileDescriptor && aFenceFd,uint64_t aBufferId,uint64_t aTransactionId,bool aUsesImageBridge)489 void AndroidHardwareBufferManager::NotifyNotUsed(ipc::FileDescriptor&& aFenceFd,
490                                                  uint64_t aBufferId,
491                                                  uint64_t aTransactionId,
492                                                  bool aUsesImageBridge) {
493   MOZ_ASSERT(InImageBridgeChildThread());
494 
495   MonitorAutoLock lock(mMonitor);
496 
497   auto it = mWaitingNotifyNotUsed.find(aBufferId);
498   if (it != mWaitingNotifyNotUsed.end()) {
499     if (aTransactionId < it->second->GetLastFwdTransactionId(lock)) {
500       // Released on host side, but client already requested newer use texture.
501       return;
502     }
503     it->second->SetReleaseFence(std::move(aFenceFd), lock);
504     mWaitingNotifyNotUsed.erase(it);
505     mMonitor.NotifyAll();
506   }
507 }
508 
509 }  // namespace layers
510 }  // namespace mozilla
511