1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
19 
20 #include <errno.h>
21 #include <limits.h>
22 #include <pthread.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <sys/mman.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 
31 #include <cutils/atomic.h>
32 #include <log/log.h>
33 #include <utils/Trace.h>
34 
35 #include <hardware/hardware.h>
36 #include <hardware/gralloc.h>
37 
38 #include <gralloc1-adapter.h>
39 
40 #include "gralloc_priv.h"
41 #include "gr.h"
42 #include "alloc_controller.h"
43 #include "memalloc.h"
44 #include <qdMetaData.h>
45 
46 using namespace gralloc;
47 /*****************************************************************************/
48 
49 // Return the type of allocator -
50 // these are used for mapping/unmapping
getAllocator(int flags)51 static IMemAlloc* getAllocator(int flags)
52 {
53     IMemAlloc* memalloc;
54     IAllocController* alloc_ctrl = IAllocController::getInstance();
55     memalloc = alloc_ctrl->getAllocator(flags);
56     return memalloc;
57 }
58 
gralloc_map_metadata(buffer_handle_t handle)59 static int gralloc_map_metadata(buffer_handle_t handle) {
60     private_handle_t* hnd = (private_handle_t*)handle;
61     hnd->base_metadata = 0;
62     IMemAlloc* memalloc = getAllocator(hnd->flags) ;
63     void *mappedAddress = MAP_FAILED;
64     unsigned int size = 0;
65     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
66         mappedAddress = MAP_FAILED;
67         size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
68         int ret = memalloc->map_buffer(&mappedAddress, size,
69                                        hnd->offset_metadata, hnd->fd_metadata);
70         if(ret || mappedAddress == MAP_FAILED) {
71             ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
72                   hnd, hnd->fd_metadata, strerror(errno));
73             return -errno;
74         }
75         hnd->base_metadata = uint64_t(mappedAddress);
76     }
77     return 0;
78 }
79 
gralloc_map(gralloc_module_t const * module,buffer_handle_t handle)80 static int gralloc_map(gralloc_module_t const* module,
81                        buffer_handle_t handle)
82 {
83     ATRACE_CALL();
84     if(!module)
85         return -EINVAL;
86 
87     private_handle_t* hnd = (private_handle_t*)handle;
88     unsigned int size = 0;
89     int err = 0;
90     IMemAlloc* memalloc = getAllocator(hnd->flags) ;
91     void *mappedAddress = MAP_FAILED;
92     hnd->base = 0;
93 
94     // Dont map framebuffer and secure buffers
95     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
96         !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
97         size = hnd->size;
98         err = memalloc->map_buffer(&mappedAddress, size,
99                                        hnd->offset, hnd->fd);
100         if(err || mappedAddress == MAP_FAILED) {
101             ALOGE("Could not mmap handle %p, fd=%d (%s)",
102                   handle, hnd->fd, strerror(errno));
103             return -errno;
104         }
105 
106         hnd->base = uint64_t(mappedAddress);
107     } else {
108         // Cannot map secure buffers or framebuffers, but still need to map
109         // metadata for secure buffers.
110         // If mapping a secure buffers fails, the framework needs to get
111         // an error code.
112         err = -EACCES;
113     }
114 
115     //Allow mapping of metadata for all buffers including secure ones, but not
116     //of framebuffer
117     int metadata_err = gralloc_map_metadata(handle);
118     if (!err) {
119         err = metadata_err;
120     }
121     return err;
122 }
123 
gralloc_unmap(gralloc_module_t const * module,buffer_handle_t handle)124 static int gralloc_unmap(gralloc_module_t const* module,
125                          buffer_handle_t handle)
126 {
127     ATRACE_CALL();
128     int err = -EINVAL;
129     if(!module)
130         return err;
131 
132     private_handle_t* hnd = (private_handle_t*)handle;
133     IMemAlloc* memalloc = getAllocator(hnd->flags) ;
134     if(!memalloc)
135         return err;
136 
137     if(hnd->base) {
138         err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
139         if (err) {
140             ALOGE("Could not unmap memory at address %p, %s", (void*) hnd->base,
141                     strerror(errno));
142             return -errno;
143         }
144         hnd->base = 0;
145     }
146 
147     if(hnd->base_metadata) {
148         unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
149         err = memalloc->unmap_buffer((void*)hnd->base_metadata,
150                 size, hnd->offset_metadata);
151         if (err) {
152             ALOGE("Could not unmap memory at address %p, %s",
153                     (void*) hnd->base_metadata, strerror(errno));
154             return -errno;
155         }
156         hnd->base_metadata = 0;
157     }
158 
159     return 0;
160 }
161 
162 /*****************************************************************************/
163 
164 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
165 
166 /*****************************************************************************/
167 
gralloc_register_buffer(gralloc_module_t const * module,buffer_handle_t handle)168 int gralloc_register_buffer(gralloc_module_t const* module,
169                             buffer_handle_t handle)
170 {
171     ATRACE_CALL();
172     if (!module || private_handle_t::validate(handle) < 0)
173         return -EINVAL;
174 
175     int err =  gralloc_map(module, handle);
176     /* Do not fail register_buffer for secure buffers*/
177     if (err == -EACCES)
178         err = 0;
179     return err;
180 }
181 
gralloc_unregister_buffer(gralloc_module_t const * module,buffer_handle_t handle)182 int gralloc_unregister_buffer(gralloc_module_t const* module,
183                               buffer_handle_t handle)
184 {
185     ATRACE_CALL();
186     if (!module || private_handle_t::validate(handle) < 0)
187         return -EINVAL;
188 
189     /*
190      * If the buffer has been mapped during a lock operation, it's time
191      * to un-map it. It's an error to be here with a locked buffer.
192      * NOTE: the framebuffer is handled differently and is never unmapped.
193      * Also base and base_metadata are reset.
194      */
195     return gralloc_unmap(module, handle);
196 }
197 
terminateBuffer(gralloc_module_t const * module,private_handle_t * hnd)198 int terminateBuffer(gralloc_module_t const* module,
199                     private_handle_t* hnd)
200 {
201     ATRACE_CALL();
202     if(!module)
203         return -EINVAL;
204 
205     /*
206      * If the buffer has been mapped during a lock operation, it's time
207      * to un-map it. It's an error to be here with a locked buffer.
208      * NOTE: the framebuffer is handled differently and is never unmapped.
209      * Also base and base_metadata are reset.
210      */
211     return gralloc_unmap(module, hnd);
212 }
213 
gralloc_map_and_invalidate(gralloc_module_t const * module,buffer_handle_t handle,int usage)214 static int gralloc_map_and_invalidate (gralloc_module_t const* module,
215                                        buffer_handle_t handle, int usage)
216 {
217     ATRACE_CALL();
218     if (!module || private_handle_t::validate(handle) < 0)
219         return -EINVAL;
220 
221     int err = 0;
222     private_handle_t* hnd = (private_handle_t*)handle;
223     if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
224         if (hnd->base == 0) {
225             // we need to map for real
226             pthread_mutex_t* const lock = &sMapLock;
227             pthread_mutex_lock(lock);
228             err = gralloc_map(module, handle);
229             pthread_mutex_unlock(lock);
230         }
231         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
232                 hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
233             //Invalidate if CPU reads in software and there are non-CPU
234             //writers. No need to do this for the metadata buffer as it is
235             //only read/written in software.
236             if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
237                     (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
238             {
239                 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
240                 err = memalloc->clean_buffer((void*)hnd->base,
241                         hnd->size, hnd->offset, hnd->fd,
242                         CACHE_INVALIDATE);
243             }
244             //Mark the buffer to be flushed after CPU write.
245             if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
246                 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
247             }
248         }
249     }
250 
251     return err;
252 }
253 
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int,int,int,int,void ** vaddr)254 int gralloc_lock(gralloc_module_t const* module,
255                  buffer_handle_t handle, int usage,
256                  int /*l*/, int /*t*/, int /*w*/, int /*h*/,
257                  void** vaddr)
258 {
259     ATRACE_CALL();
260     private_handle_t* hnd = (private_handle_t*)handle;
261     int err = gralloc_map_and_invalidate(module, handle, usage);
262     if(!err)
263         *vaddr = (void*)hnd->base;
264     return err;
265 }
266 
gralloc_lock_ycbcr(gralloc_module_t const * module,buffer_handle_t handle,int usage,int,int,int,int,struct android_ycbcr * ycbcr)267 int gralloc_lock_ycbcr(gralloc_module_t const* module,
268                  buffer_handle_t handle, int usage,
269                  int /*l*/, int /*t*/, int /*w*/, int /*h*/,
270                  struct android_ycbcr *ycbcr)
271 {
272     ATRACE_CALL();
273     private_handle_t* hnd = (private_handle_t*)handle;
274     int err = gralloc_map_and_invalidate(module, handle, usage);
275     if(!err)
276         err = getYUVPlaneInfo(hnd, ycbcr);
277     return err;
278 }
279 
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)280 int gralloc_unlock(gralloc_module_t const* module,
281                    buffer_handle_t handle)
282 {
283     ATRACE_CALL();
284     if (!module || private_handle_t::validate(handle) < 0)
285         return -EINVAL;
286 
287     int err = 0;
288     private_handle_t* hnd = (private_handle_t*)handle;
289 
290     IMemAlloc* memalloc = getAllocator(hnd->flags);
291     if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
292         err = memalloc->clean_buffer((void*)hnd->base,
293                 hnd->size, hnd->offset, hnd->fd,
294                 CACHE_CLEAN);
295         hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
296     }
297 
298     return err;
299 }
300 
301 /*****************************************************************************/
302 
isYUV(private_handle_t * hnd)303 static bool isYUV(private_handle_t* hnd)
304 {
305     bool is_yuv;
306 
307     switch (hnd->format) {
308         //Semiplanar
309         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
310         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
311         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
312         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
313         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
314         case HAL_PIXEL_FORMAT_YCrCb_422_SP:
315         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
316         case HAL_PIXEL_FORMAT_NV21_ZSL:
317         case HAL_PIXEL_FORMAT_RAW10:
318         case HAL_PIXEL_FORMAT_RAW16:
319         //Planar
320         case HAL_PIXEL_FORMAT_YV12:
321             is_yuv = true;
322         break;
323         //Unsupported formats
324         case HAL_PIXEL_FORMAT_YCbCr_422_I:
325         case HAL_PIXEL_FORMAT_YCrCb_422_I:
326         case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
327         default:
328             is_yuv = false;
329             break;
330     }
331 
332     return is_yuv;
333 }
334 
ycbcr_to_flexible_layout(const struct android_ycbcr * ycbcr,struct android_flex_layout * layout)335 static void ycbcr_to_flexible_layout(const struct android_ycbcr* ycbcr,
336         struct android_flex_layout* layout)
337 {
338     layout->format = FLEX_FORMAT_YCbCr;
339     layout->num_planes = 3;
340 
341     for (uint32_t i = 0; i < layout->num_planes; i++) {
342         layout->planes[i].bits_per_component = 8;
343         layout->planes[i].bits_used = 8;
344         layout->planes[i].h_increment = 1;
345         layout->planes[i].v_increment = 1;
346         layout->planes[i].h_subsampling = 2;
347         layout->planes[i].v_subsampling = 2;
348     }
349 
350     layout->planes[0].top_left = (uint8_t*)ycbcr->y;
351     layout->planes[0].component = FLEX_COMPONENT_Y;
352     layout->planes[0].v_increment = (int32_t)ycbcr->ystride;
353 
354     layout->planes[1].top_left = (uint8_t*)ycbcr->cb;
355     layout->planes[1].component = FLEX_COMPONENT_Cb;
356     layout->planes[1].h_increment = (int32_t)ycbcr->chroma_step;
357     layout->planes[1].v_increment = (int32_t)ycbcr->cstride;
358 
359     layout->planes[2].top_left = (uint8_t*)ycbcr->cr;
360     layout->planes[2].component = FLEX_COMPONENT_Cr;
361     layout->planes[2].h_increment = (int32_t)ycbcr->chroma_step;
362     layout->planes[2].v_increment = (int32_t)ycbcr->cstride;
363 }
364 
gralloc_perform(struct gralloc_module_t const * module,int operation,...)365 int gralloc_perform(struct gralloc_module_t const* module,
366                     int operation, ... )
367 {
368     int res = -EINVAL;
369     va_list args;
370     if(!module)
371         return res;
372 
373     va_start(args, operation);
374     switch (operation) {
375         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
376             {
377                 int fd = va_arg(args, int);
378                 unsigned int size = va_arg(args, unsigned int);
379                 unsigned int offset = va_arg(args, unsigned int);
380                 void* base = va_arg(args, void*);
381                 int width = va_arg(args, int);
382                 int height = va_arg(args, int);
383                 int format = va_arg(args, int);
384 
385                 native_handle_t** handle = va_arg(args, native_handle_t**);
386                 private_handle_t* hnd = (private_handle_t*)native_handle_create(
387                     private_handle_t::sNumFds, private_handle_t::sNumInts());
388                 if (hnd) {
389                   hnd->magic = private_handle_t::sMagic;
390                   hnd->fd = fd;
391                   hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
392                   hnd->size = size;
393                   hnd->offset = offset;
394                   hnd->base = uint64_t(base) + offset;
395                   hnd->gpuaddr = 0;
396                   hnd->width = width;
397                   hnd->height = height;
398                   hnd->format = format;
399                   *handle = (native_handle_t *)hnd;
400                   res = 0;
401                 }
402                 break;
403 
404             }
405         case GRALLOC_MODULE_PERFORM_GET_STRIDE:
406             {
407                 int width   = va_arg(args, int);
408                 int format  = va_arg(args, int);
409                 int *stride = va_arg(args, int *);
410                 int alignedw = 0, alignedh = 0;
411                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
412                         0, format, 0, alignedw, alignedh);
413                 *stride = alignedw;
414                 res = 0;
415             } break;
416 
417         case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
418             {
419                 const private_handle_t* hnd =  va_arg(args, private_handle_t*);
420                 int *stride = va_arg(args, int *);
421                 if (private_handle_t::validate(hnd)) {
422                     return res;
423                 }
424 
425                 int alignedw = 0, alignedh = 0;
426                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
427                 *stride = alignedw;
428 
429                 res = 0;
430             } break;
431 
432         case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
433             {
434                 const private_handle_t* hnd =  va_arg(args, private_handle_t*);
435                 int *stride = va_arg(args, int *);
436                 int *height = va_arg(args, int *);
437                 if (private_handle_t::validate(hnd)) {
438                     return res;
439                 }
440 
441                 int alignedw = 0, alignedh = 0;
442                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(hnd, alignedw, alignedh);
443                 *stride = alignedw;
444                 *height = alignedh;
445 
446                 res = 0;
447             } break;
448 
449         case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
450             {
451                 int width   = va_arg(args, int);
452                 int height  = va_arg(args, int);
453                 int format  = va_arg(args, int);
454                 int usage   = va_arg(args, int);
455                 int *alignedWidth = va_arg(args, int *);
456                 int *alignedHeight = va_arg(args, int *);
457                 int *tileEnabled = va_arg(args,int *);
458                 *tileEnabled = isUBwcEnabled(format, usage) ||
459                                isMacroTileEnabled(format, usage);
460                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
461                         height, format, usage, *alignedWidth, *alignedHeight);
462                 res = 0;
463             } break;
464 
465         case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
466             {
467                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
468                 int *color_space = va_arg(args, int *);
469                 if (private_handle_t::validate(hnd)) {
470                     return res;
471                 }
472                 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
473                 if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
474                     *color_space = metadata->colorSpace;
475                     res = 0;
476                 }
477             } break;
478 
479         case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
480             {
481                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
482                 android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
483                 if (!private_handle_t::validate(hnd)) {
484                     res = getYUVPlaneInfo(hnd, ycbcr);
485                 }
486             } break;
487 
488         case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
489             {
490                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
491                 int *map_secure_buffer = va_arg(args, int *);
492                 if (private_handle_t::validate(hnd)) {
493                     return res;
494                 }
495                 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
496                 if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
497                     *map_secure_buffer = metadata->mapSecureBuffer;
498                     res = 0;
499                 } else {
500                     *map_secure_buffer = 0;
501                 }
502             } break;
503 
504         case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG:
505             {
506                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
507                 int *flag = va_arg(args, int *);
508                 if (private_handle_t::validate(hnd)) {
509                     return res;
510                 }
511                 *flag = hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
512                 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
513                 if (metadata && (metadata->operation & LINEAR_FORMAT)) {
514                     *flag = 0;
515                 }
516                 res = 0;
517             } break;
518 
519         case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
520             {
521                 private_handle_t* hnd = va_arg(args, private_handle_t*);
522                 void** rgb_data = va_arg(args, void**);
523                 if (!private_handle_t::validate(hnd)) {
524                     res = getRgbDataAddress(hnd, rgb_data);
525                 }
526             } break;
527 
528         case GRALLOC_MODULE_PERFORM_GET_IGC:
529             {
530                 private_handle_t* hnd = va_arg(args, private_handle_t*);
531                 uint32_t *igc = va_arg(args, uint32_t *);
532                 if (!private_handle_t::validate(hnd) && igc) {
533                     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
534                     if (metadata && (metadata->operation & SET_IGC)) {
535                         *igc = metadata->igc;
536                         res = 0;
537                     }
538                 }
539             } break;
540 
541         case GRALLOC_MODULE_PERFORM_SET_IGC:
542             res = 0;
543             break;
544 
545         case GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE:
546             {
547                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
548                 uint32_t *enable = va_arg(args, uint32_t*);
549                 if (!private_handle_t::validate(hnd)) {
550                     setMetaData(hnd, SET_SINGLE_BUFFER_MODE, enable);
551                     res = 0;
552                 }
553             } break;
554 
555         case GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR:
556             {
557                 auto outMinorVersion = va_arg(args, int*);
558                 *outMinorVersion = 1; // GRALLOC_MODULE_API_VERSION_0_1
559             } break;
560 
561         case GRALLOC1_ADAPTER_PERFORM_SET_USAGES:
562             {
563                 auto hnd =  va_arg(args, private_handle_t*);
564                 auto producerUsage = va_arg(args, int);
565                 auto consumerUsage = va_arg(args, int);
566                 hnd->producer_usage = producerUsage;
567                 hnd->consumer_usage = consumerUsage;
568             } break;
569 
570         case GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS:
571             {
572                 auto hnd =  va_arg(args, private_handle_t*);
573                 auto outWidth = va_arg(args, int*);
574                 auto outHeight = va_arg(args, int*);
575                 *outWidth = hnd->original_width;
576                 *outHeight = hnd->height;
577             } break;
578 
579         case GRALLOC1_ADAPTER_PERFORM_GET_FORMAT:
580             {
581                 auto hnd =  va_arg(args, private_handle_t*);
582                 auto outFormat = va_arg(args, int*);
583                 *outFormat = hnd->original_format;
584             } break;
585 
586         case GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE:
587             {
588                 auto hnd =  va_arg(args, private_handle_t*);
589                 auto outUsage = va_arg(args, int*);
590                 *outUsage = hnd->producer_usage;
591             } break;
592 
593         case GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE:
594             {
595                 auto hnd =  va_arg(args, private_handle_t*);
596                 auto outUsage = va_arg(args, int*);
597                 *outUsage = hnd->consumer_usage;
598             } break;
599 
600         case GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE:
601             {
602                 auto hnd =  va_arg(args, private_handle_t*);
603                 auto outBackingStore = va_arg(args, uint64_t*);
604                 *outBackingStore = hnd->backing_store;
605             } break;
606 
607         case GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES:
608             {
609                 auto hnd =  va_arg(args, private_handle_t*);
610                 auto outNumFlexPlanes = va_arg(args, int*);
611 
612                 (void) hnd;
613                 // for simpilicity
614                 *outNumFlexPlanes = 4;
615             } break;
616 
617         case GRALLOC1_ADAPTER_PERFORM_GET_STRIDE:
618             {
619                 auto hnd =  va_arg(args, private_handle_t*);
620                 auto outStride = va_arg(args, int*);
621                 *outStride = hnd->width;
622             } break;
623 
624         case GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX:
625             {
626                 auto hnd =  va_arg(args, private_handle_t*);
627                 auto producerUsage = va_arg(args, int);
628                 auto consumerUsage = va_arg(args, int);
629                 auto left = va_arg(args, int);
630                 auto top = va_arg(args, int);
631                 auto width = va_arg(args, int);
632                 auto height = va_arg(args, int);
633                 auto outLayout = va_arg(args, android_flex_layout*);
634                 // always -1
635                 auto acquireFence = va_arg(args, int);
636                 (void) acquireFence;
637 
638                 // TODO lock RGB as a flexible format
639                 if (!isYUV(hnd)) {
640                     return -EINVAL;
641                 }
642 
643                 struct android_ycbcr ycbcr;
644                 res = gralloc_lock_ycbcr(module, hnd,
645                         producerUsage | consumerUsage,
646                         left, top, width, height, &ycbcr);
647                 if (res != 0) {
648                     return res;
649                 }
650 
651                 ycbcr_to_flexible_layout(&ycbcr, outLayout);
652             } break;
653 
654         default:
655             break;
656     }
657     va_end(args);
658     return res;
659 }
660