1 /*
2  * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above
10  *    copyright notice, this list of conditions and the following
11  *    disclaimer in the documentation and/or other materials provided
12  *    with the distribution.
13  *  * Neither the name of The Linux Foundation nor the names of its
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <gralloc_priv.h>
31 
32 #include <core/buffer_allocator.h>
33 #include <utils/constants.h>
34 #include <utils/debug.h>
35 
36 #include "gr_utils.h"
37 #include "hwc_buffer_allocator.h"
38 #include "hwc_debugger.h"
39 #include "hwc_layers.h"
40 
41 #define __CLASS__ "HWCBufferAllocator"
42 
43 using android::hardware::graphics::mapper::V2_0::Error;
44 using MapperV3Error = android::hardware::graphics::mapper::V3_0::Error;
45 using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
46 using MapperV3BufferDescriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
47 using android::hardware::hidl_handle;
48 using android::hardware::hidl_vec;
49 
50 namespace sdm {
51 
GetGrallocInstance()52 DisplayError HWCBufferAllocator::GetGrallocInstance() {
53   // Lazy initialization of gralloc HALs
54   if (mapper_V3_ != nullptr || mapper_V2_ != nullptr || allocator_V3_ != nullptr ||
55       allocator_V2_ != nullptr) {
56     return kErrorNone;
57   }
58 
59   allocator_V3_ = IAllocatorV3::getService();
60   if (allocator_V3_ == nullptr) {
61     allocator_V2_ = IAllocatorV2::getService();
62     if (allocator_V2_ == nullptr) {
63       DLOGE("Unable to get allocator");
64       return kErrorCriticalResource;
65     }
66   }
67 
68   mapper_V3_ = IMapperV3::getService();
69   if (mapper_V3_ == nullptr) {
70     mapper_V2_ = IMapperV2::getService();
71     if (mapper_V2_ == nullptr) {
72       DLOGE("Unable to get mapper");
73       return kErrorCriticalResource;
74     }
75   }
76 
77   return kErrorNone;
78 }
79 
AllocateBuffer(BufferInfo * buffer_info)80 DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
81   auto err = GetGrallocInstance();
82   if (err != kErrorNone) {
83     return err;
84   }
85   const BufferConfig &buffer_config = buffer_info->buffer_config;
86   AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
87   int format;
88   uint64_t alloc_flags = 0;
89   int error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
90   if (error != 0) {
91     return kErrorParameters;
92   }
93 
94   if (buffer_config.secure) {
95     alloc_flags |= BufferUsage::PROTECTED;
96   }
97 
98   if (buffer_config.secure_camera) {
99     alloc_flags |= BufferUsage::CAMERA_OUTPUT;
100   }
101 
102   if (!buffer_config.cache) {
103     // Allocate uncached buffers
104     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
105   }
106 
107   if (buffer_config.gfx_client) {
108     alloc_flags |= BufferUsage::GPU_TEXTURE;
109   }
110 
111   alloc_flags |= BufferUsage::COMPOSER_OVERLAY;
112 
113   const native_handle_t *buf = nullptr;
114 
115   if (mapper_V3_ != nullptr) {
116     IMapperV3::BufferDescriptorInfo descriptor_info;
117     descriptor_info.width = buffer_config.width;
118     descriptor_info.height = buffer_config.height;
119     descriptor_info.layerCount = 1;
120     descriptor_info.format =
121         static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
122     descriptor_info.usage = alloc_flags;
123 
124     auto hidl_err = MapperV3Error::NONE;
125 
126     auto descriptor = BufferDescriptor();
127     mapper_V3_->createDescriptor(descriptor_info, [&](const auto &_error, const auto &_descriptor) {
128       hidl_err = _error;
129       if (hidl_err != MapperV3Error::NONE) {
130         return;
131       }
132       descriptor = _descriptor;
133     });
134 
135     if (hidl_err != MapperV3Error::NONE) {
136       DLOGE("Failed to create descriptor");
137       return kErrorMemory;
138     }
139 
140     hidl_handle raw_handle = nullptr;
141 
142     allocator_V3_->allocate(descriptor, 1,
143                             [&](const auto &_error, const auto &_stride, const auto &_buffers) {
144                               hidl_err = _error;
145                               if (hidl_err != MapperV3Error::NONE) {
146                                 return;
147                               }
148                               raw_handle = _buffers[0];
149                             });
150 
151     if (hidl_err != MapperV3Error::NONE) {
152       DLOGE("Failed to allocate buffer");
153       return kErrorMemory;
154     }
155 
156     mapper_V3_->importBuffer(raw_handle, [&](const auto &_error, const auto &_buffer) {
157       hidl_err = _error;
158       if (hidl_err != MapperV3Error::NONE) {
159         return;
160       }
161       buf = static_cast<const native_handle_t *>(_buffer);
162     });
163 
164     if (hidl_err != MapperV3Error::NONE) {
165       DLOGE("Failed to import buffer into HWC");
166       return kErrorMemory;
167     }
168   } else {
169     IMapperV2::BufferDescriptorInfo descriptor_info;
170     descriptor_info.width = buffer_config.width;
171     descriptor_info.height = buffer_config.height;
172     descriptor_info.layerCount = 1;
173     descriptor_info.format =
174         static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format);
175     descriptor_info.usage = alloc_flags;
176 
177     auto hidl_err = Error::NONE;
178 
179     auto descriptor = BufferDescriptor();
180     mapper_V2_->createDescriptor(descriptor_info, [&](const auto &_error, const auto &_descriptor) {
181       hidl_err = _error;
182       if (hidl_err != Error::NONE) {
183         return;
184       }
185       descriptor = _descriptor;
186     });
187 
188     if (hidl_err != Error::NONE) {
189       DLOGE("Failed to create descriptor");
190       return kErrorMemory;
191     }
192 
193     hidl_handle raw_handle = nullptr;
194 
195     allocator_V2_->allocate(descriptor, 1,
196                             [&](const auto &_error, const auto &_stride, const auto &_buffers) {
197                               hidl_err = _error;
198                               if (hidl_err != Error::NONE) {
199                                 return;
200                               }
201                               raw_handle = _buffers[0];
202                             });
203 
204     if (hidl_err != Error::NONE) {
205       DLOGE("Failed to allocate buffer");
206       return kErrorMemory;
207     }
208 
209     mapper_V2_->importBuffer(raw_handle, [&](const auto &_error, const auto &_buffer) {
210       hidl_err = _error;
211       if (hidl_err != Error::NONE) {
212         return;
213       }
214       buf = static_cast<const native_handle_t *>(_buffer);
215     });
216 
217     if (hidl_err != Error::NONE) {
218       DLOGE("Failed to import buffer into HWC");
219       return kErrorMemory;
220     }
221   }
222 
223   private_handle_t *hnd = nullptr;
224   hnd = (private_handle_t *)buf;  // NOLINT
225   alloc_buffer_info->fd = hnd->fd;
226   alloc_buffer_info->stride = UINT32(hnd->width);
227   alloc_buffer_info->aligned_width = UINT32(hnd->width);
228   alloc_buffer_info->aligned_height = UINT32(hnd->height);
229   alloc_buffer_info->size = hnd->size;
230   alloc_buffer_info->id = hnd->id;
231   alloc_buffer_info->format = HWCLayer::GetSDMFormat(hnd->format, hnd->flags);
232 
233   buffer_info->private_data = reinterpret_cast<void *>(hnd);
234   return kErrorNone;
235 }
236 
FreeBuffer(BufferInfo * buffer_info)237 DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
238   DisplayError err = kErrorNone;
239   auto hnd = reinterpret_cast<void *>(buffer_info->private_data);
240   if (mapper_V3_ != nullptr) {
241     mapper_V3_->freeBuffer(hnd);
242   } else {
243     mapper_V2_->freeBuffer(hnd);
244   }
245   AllocatedBufferInfo &alloc_buffer_info = buffer_info->alloc_buffer_info;
246 
247   alloc_buffer_info.fd = -1;
248   alloc_buffer_info.stride = 0;
249   alloc_buffer_info.size = 0;
250   buffer_info->private_data = NULL;
251   return err;
252 }
253 
GetCustomWidthAndHeight(const private_handle_t * handle,int * width,int * height)254 void HWCBufferAllocator::GetCustomWidthAndHeight(const private_handle_t *handle, int *width,
255                                                  int *height) {
256   *width = handle->width;
257   *height = handle->height;
258   gralloc::GetCustomDimensions(const_cast<private_handle_t *>(handle), width, height);
259 }
260 
GetAlignedWidthAndHeight(int width,int height,int format,uint32_t alloc_type,int * aligned_width,int * aligned_height)261 void HWCBufferAllocator::GetAlignedWidthAndHeight(int width, int height, int format,
262                                                   uint32_t alloc_type, int *aligned_width,
263                                                   int *aligned_height) {
264   uint64_t usage = 0;
265   if (alloc_type & GRALLOC_USAGE_HW_FB) {
266     usage |= BufferUsage::COMPOSER_CLIENT_TARGET;
267   }
268   if (alloc_type & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
269     usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
270   }
271   uint32_t aligned_w = UINT(width);
272   uint32_t aligned_h = UINT(height);
273   gralloc::BufferInfo info(width, height, format, usage);
274   gralloc::GetAlignedWidthAndHeight(info, &aligned_w, &aligned_h);
275   *aligned_width = INT(aligned_w);
276   *aligned_height = INT(aligned_h);
277 }
278 
GetBufferSize(BufferInfo * buffer_info)279 uint32_t HWCBufferAllocator::GetBufferSize(BufferInfo *buffer_info) {
280   const BufferConfig &buffer_config = buffer_info->buffer_config;
281   uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
282 
283   int width = INT(buffer_config.width);
284   int height = INT(buffer_config.height);
285   int format;
286 
287   if (buffer_config.secure) {
288     alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
289   }
290 
291   if (!buffer_config.cache) {
292     // Allocate uncached buffers
293     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
294   }
295 
296   if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
297     return 0;
298   }
299 
300   uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
301   gralloc::BufferInfo info(width, height, format, alloc_flags);
302   int ret = GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
303   if (ret < 0) {
304     return 0;
305   }
306   return buffer_size;
307 }
308 
SetBufferInfo(LayerBufferFormat format,int * target,uint64_t * flags)309 int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags) {
310   switch (format) {
311     case kFormatRGBA8888:
312       *target = HAL_PIXEL_FORMAT_RGBA_8888;
313       break;
314     case kFormatRGBX8888:
315       *target = HAL_PIXEL_FORMAT_RGBX_8888;
316       break;
317     case kFormatRGB888:
318       *target = HAL_PIXEL_FORMAT_RGB_888;
319       break;
320     case kFormatRGB565:
321       *target = HAL_PIXEL_FORMAT_RGB_565;
322       break;
323     case kFormatBGR565:
324       *target = HAL_PIXEL_FORMAT_BGR_565;
325       break;
326     case kFormatBGR888:
327       *target = HAL_PIXEL_FORMAT_BGR_888;
328       break;
329     case kFormatBGRA8888:
330       *target = HAL_PIXEL_FORMAT_BGRA_8888;
331       break;
332     case kFormatYCrCb420PlanarStride16:
333       *target = HAL_PIXEL_FORMAT_YV12;
334       break;
335     case kFormatYCrCb420SemiPlanar:
336       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;
337       break;
338     case kFormatYCbCr420SemiPlanar:
339       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;
340       break;
341     case kFormatYCbCr422H2V1Packed:
342       *target = HAL_PIXEL_FORMAT_YCbCr_422_I;
343       break;
344     case kFormatCbYCrY422H2V1Packed:
345       *target = HAL_PIXEL_FORMAT_CbYCrY_422_I;
346       break;
347     case kFormatYCbCr422H2V1SemiPlanar:
348       *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;
349       break;
350     case kFormatYCbCr420SemiPlanarVenus:
351       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
352       break;
353     case kFormatYCrCb420SemiPlanarVenus:
354       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
355       break;
356     case kFormatYCbCr420SPVenusUbwc:
357     case kFormatYCbCr420SPVenusTile:
358       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
359       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
360       break;
361     case kFormatRGBA5551:
362       *target = HAL_PIXEL_FORMAT_RGBA_5551;
363       break;
364     case kFormatRGBA4444:
365       *target = HAL_PIXEL_FORMAT_RGBA_4444;
366       break;
367     case kFormatRGBA1010102:
368       *target = HAL_PIXEL_FORMAT_RGBA_1010102;
369       break;
370     case kFormatARGB2101010:
371       *target = HAL_PIXEL_FORMAT_ARGB_2101010;
372       break;
373     case kFormatRGBX1010102:
374       *target = HAL_PIXEL_FORMAT_RGBX_1010102;
375       break;
376     case kFormatXRGB2101010:
377       *target = HAL_PIXEL_FORMAT_XRGB_2101010;
378       break;
379     case kFormatBGRA1010102:
380       *target = HAL_PIXEL_FORMAT_BGRA_1010102;
381       break;
382     case kFormatABGR2101010:
383       *target = HAL_PIXEL_FORMAT_ABGR_2101010;
384       break;
385     case kFormatBGRX1010102:
386       *target = HAL_PIXEL_FORMAT_BGRX_1010102;
387       break;
388     case kFormatXBGR2101010:
389       *target = HAL_PIXEL_FORMAT_XBGR_2101010;
390       break;
391     case kFormatYCbCr420P010:
392       *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
393       break;
394     case kFormatYCbCr420TP10Ubwc:
395     case kFormatYCbCr420TP10Tile:
396       *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
397       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
398       break;
399     case kFormatYCbCr420P010Ubwc:
400     case kFormatYCbCr420P010Tile:
401       *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
402       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
403       break;
404     case kFormatYCbCr420P010Venus:
405       *target = HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS;
406       break;
407     case kFormatRGBA8888Ubwc:
408       *target = HAL_PIXEL_FORMAT_RGBA_8888;
409       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
410       break;
411     case kFormatRGBX8888Ubwc:
412       *target = HAL_PIXEL_FORMAT_RGBX_8888;
413       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
414       break;
415     case kFormatBGR565Ubwc:
416       *target = HAL_PIXEL_FORMAT_BGR_565;
417       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
418       break;
419     case kFormatRGBA1010102Ubwc:
420       *target = HAL_PIXEL_FORMAT_RGBA_1010102;
421       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
422       break;
423     case kFormatRGBX1010102Ubwc:
424       *target = HAL_PIXEL_FORMAT_RGBX_1010102;
425       *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
426       break;
427     default:
428       DLOGW("Unsupported format = 0x%x", format);
429       return -EINVAL;
430   }
431   return 0;
432 }
433 
GetAllocatedBufferInfo(const BufferConfig & buffer_config,AllocatedBufferInfo * allocated_buffer_info)434 DisplayError HWCBufferAllocator::GetAllocatedBufferInfo(
435     const BufferConfig &buffer_config, AllocatedBufferInfo *allocated_buffer_info) {
436   // TODO(user): This API should pass the buffer_info of the already allocated buffer
437   // The private_data can then be typecast to the private_handle and used directly.
438   uint64_t alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
439 
440   int width = INT(buffer_config.width);
441   int height = INT(buffer_config.height);
442   int format;
443 
444   if (buffer_config.secure) {
445     alloc_flags |= INT(GRALLOC_USAGE_PROTECTED);
446   }
447 
448   if (!buffer_config.cache) {
449     // Allocate uncached buffers
450     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
451   }
452 
453   if (SetBufferInfo(buffer_config.format, &format, &alloc_flags) < 0) {
454     return kErrorParameters;
455   }
456 
457   uint32_t aligned_width = 0, aligned_height = 0, buffer_size = 0;
458   gralloc::BufferInfo info(width, height, format, alloc_flags);
459   int ret = GetBufferSizeAndDimensions(info, &buffer_size, &aligned_width, &aligned_height);
460   if (ret < 0) {
461     return kErrorParameters;
462   }
463   allocated_buffer_info->stride = UINT32(aligned_width);
464   allocated_buffer_info->aligned_width = UINT32(aligned_width);
465   allocated_buffer_info->aligned_height = UINT32(aligned_height);
466   allocated_buffer_info->size = UINT32(buffer_size);
467 
468   return kErrorNone;
469 }
470 
GetBufferLayout(const AllocatedBufferInfo & buf_info,uint32_t stride[4],uint32_t offset[4],uint32_t * num_planes)471 DisplayError HWCBufferAllocator::GetBufferLayout(const AllocatedBufferInfo &buf_info,
472                                                  uint32_t stride[4], uint32_t offset[4],
473                                                  uint32_t *num_planes) {
474   // TODO(user): Transition APIs to not need a private handle
475   private_handle_t hnd(-1, 0, 0, 0, 0, 0, 0);
476   int format = HAL_PIXEL_FORMAT_RGBA_8888;
477   uint64_t flags = 0;
478 
479   SetBufferInfo(buf_info.format, &format, &flags);
480   // Setup only the required stuff, skip rest
481   hnd.format = format;
482   hnd.width = INT32(buf_info.aligned_width);
483   hnd.height = INT32(buf_info.aligned_height);
484   if (flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
485     hnd.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
486   }
487 
488   int ret = gralloc::GetBufferLayout(&hnd, stride, offset, num_planes);
489   if (ret < 0) {
490     DLOGE("GetBufferLayout failed");
491     return kErrorParameters;
492   }
493 
494   return kErrorNone;
495 }
496 
MapBuffer(const private_handle_t * handle,shared_ptr<Fence> acquire_fence)497 DisplayError HWCBufferAllocator::MapBuffer(const private_handle_t *handle,
498                                            shared_ptr<Fence> acquire_fence) {
499   auto err = GetGrallocInstance();
500   if (err != kErrorNone) {
501     return err;
502   }
503 
504   Fence::ScopedRef scoped_ref;
505   NATIVE_HANDLE_DECLARE_STORAGE(acquire_fence_storage, 1, 0);
506   hidl_handle acquire_fence_handle;
507   if (acquire_fence) {
508     auto h = native_handle_init(acquire_fence_storage, 1, 0);
509     h->data[0] = scoped_ref.Get(acquire_fence);
510     acquire_fence_handle = h;
511   }
512 
513   auto hnd = const_cast<private_handle_t *>(handle);
514   void *buffer_ptr = NULL;
515   if (mapper_V3_ != nullptr) {
516     const IMapperV3::Rect access_region = {.left = 0, .top = 0, .width = 0, .height = 0};
517     mapper_V3_->lock(
518         reinterpret_cast<void *>(hnd), (uint64_t)BufferUsage::CPU_READ_OFTEN, access_region,
519         acquire_fence_handle,
520         [&](const auto &_error, const auto &_buffer, const auto &_bpp, const auto &_stride) {
521           if (_error == MapperV3Error::NONE) {
522             buffer_ptr = _buffer;
523           }
524         });
525   } else {
526     const IMapperV2::Rect access_region = {.left = 0, .top = 0, .width = 0, .height = 0};
527     mapper_V2_->lock(reinterpret_cast<void *>(hnd), (uint64_t)BufferUsage::CPU_READ_OFTEN,
528                      access_region, acquire_fence_handle,
529                      [&](const auto &_error, const auto &_buffer) {
530                        if (_error == Error::NONE) {
531                          buffer_ptr = _buffer;
532                        }
533                      });
534   }
535   if (!buffer_ptr) {
536     return kErrorUndefined;
537   }
538   return kErrorNone;
539 }
540 
UnmapBuffer(const private_handle_t * handle,int * release_fence)541 DisplayError HWCBufferAllocator::UnmapBuffer(const private_handle_t *handle, int *release_fence) {
542   DisplayError err = kErrorNone;
543   *release_fence = -1;
544   auto hnd = const_cast<private_handle_t *>(handle);
545   if (mapper_V3_ != nullptr) {
546     mapper_V3_->unlock(reinterpret_cast<void *>(hnd),
547                        [&](const auto &_error, const auto &_release_fence) {
548                          if (_error != MapperV3Error::NONE) {
549                            err = kErrorUndefined;
550                          }
551                        });
552   } else {
553     mapper_V2_->unlock(reinterpret_cast<void *>(hnd),
554                        [&](const auto &_error, const auto &_release_fence) {
555                          if (_error != Error::NONE) {
556                            err = kErrorUndefined;
557                          }
558                        });
559   }
560   return err;
561 }
562 
563 }  // namespace sdm
564