1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2AllocatorGralloc"
19 #include <utils/Log.h>
20
21 #include <mutex>
22
23 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
24 #include <android/hardware/graphics/common/1.2/types.h>
25 #include <cutils/native_handle.h>
26 #include <gralloctypes/Gralloc4.h>
27 #include <hardware/gralloc.h>
28 #include <ui/GraphicBufferAllocator.h>
29 #include <ui/GraphicBufferMapper.h>
30 #include <ui/Rect.h>
31
32 #include <C2AllocatorGralloc.h>
33 #include <C2Buffer.h>
34 #include <C2Debug.h>
35 #include <C2PlatformSupport.h>
36
37 using ::android::hardware::hidl_handle;
38 using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
39
40 namespace android {
41
42 namespace /* unnamed */ {
43 enum : uint64_t {
44 /**
45 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
46 */
47 PASSTHROUGH_USAGE_MASK =
48 ~static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_MASK |
49 GRALLOC_USAGE_SW_WRITE_MASK |
50 GRALLOC_USAGE_PROTECTED)
51 };
52
53 // verify that passthrough mask is within the platform mask
54 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
55 } // unnamed
56
isAtLeastT()57 static bool isAtLeastT() {
58 return android_get_device_api_level() >= __ANDROID_API_T__;
59 }
60
FromGrallocUsage(uint64_t usage)61 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
62 // gralloc does not support WRITE_PROTECTED
63 return C2MemoryUsage(
64 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
65 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
66 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
67 (usage & PASSTHROUGH_USAGE_MASK));
68 }
69
asGrallocUsage() const70 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
71 // gralloc does not support WRITE_PROTECTED
72 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
73 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
74 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
75 (expected & PASSTHROUGH_USAGE_MASK));
76 }
77
78 namespace /* unnamed */ {
79
80 /* ===================================== GRALLOC ALLOCATION ==================================== */
native_handle_is_invalid(const native_handle_t * const handle)81 bool native_handle_is_invalid(const native_handle_t *const handle) {
82 // perform basic validation of a native handle
83 if (handle == nullptr) {
84 // null handle is considered valid
85 return false;
86 }
87 return ((size_t)handle->version != sizeof(native_handle_t) ||
88 handle->numFds < 0 ||
89 handle->numInts < 0 ||
90 // for sanity assume handles must occupy less memory than INT_MAX bytes
91 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
92 }
93
94 class C2HandleGralloc : public C2Handle {
95 private:
96 struct ExtraData {
97 uint32_t width;
98 uint32_t height;
99 uint32_t format;
100 uint32_t usage_lo;
101 uint32_t usage_hi;
102 uint32_t stride;
103 uint32_t generation;
104 uint32_t igbp_id_lo;
105 uint32_t igbp_id_hi;
106 uint32_t igbp_slot;
107 uint32_t magic;
108 };
109
110 enum {
111 NUM_INTS = sizeof(ExtraData) / sizeof(int),
112 };
113 const static uint32_t MAGIC = '\xc2gr\x00';
114
115 static
GetExtraData(const C2Handle * const handle)116 const ExtraData* GetExtraData(const C2Handle *const handle) {
117 if (handle == nullptr
118 || native_handle_is_invalid(handle)
119 || handle->numInts < NUM_INTS) {
120 return nullptr;
121 }
122 return reinterpret_cast<const ExtraData*>(
123 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
124 }
125
126 static
GetExtraData(C2Handle * const handle)127 ExtraData *GetExtraData(C2Handle *const handle) {
128 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
129 }
130
131 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const132 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
133 const ExtraData *ed = GetExtraData(this);
134 *generation = ed->generation;
135 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
136 *igbp_slot = ed->igbp_slot;
137 }
138
IsValid(const C2Handle * const o)139 static bool IsValid(const C2Handle *const o) {
140 if (o == nullptr) { // null handle is always valid
141 return true;
142 }
143 const ExtraData *xd = GetExtraData(o);
144 // we cannot validate width/height/format/usage without accessing gralloc driver
145 return xd != nullptr && xd->magic == MAGIC;
146 }
147
WrapAndMoveNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)148 static C2HandleGralloc* WrapAndMoveNativeHandle(
149 const native_handle_t *const handle,
150 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
151 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
152 //CHECK(handle != nullptr);
153 if (native_handle_is_invalid(handle) ||
154 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
155 return nullptr;
156 }
157 ExtraData xd = {
158 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
159 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
160 igbp_slot, MAGIC
161 };
162 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
163 if (res != nullptr) {
164 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
165 *GetExtraData(res) = xd;
166 }
167 return reinterpret_cast<C2HandleGralloc *>(res);
168 }
169
WrapNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)170 static C2HandleGralloc* WrapNativeHandle(
171 const native_handle_t *const handle,
172 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
173 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
174 if (handle == nullptr) {
175 return nullptr;
176 }
177 native_handle_t *clone = native_handle_clone(handle);
178 if (clone == nullptr) {
179 return nullptr;
180 }
181 C2HandleGralloc *res = WrapAndMoveNativeHandle(
182 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
183 if (res == nullptr) {
184 native_handle_close(clone);
185 }
186 native_handle_delete(clone);
187 return res;
188 }
189
getPixelFormat(const C2Handle * const handle)190 static uint32_t getPixelFormat(const C2Handle *const handle) {
191 if (handle == nullptr) {
192 return 0;
193 }
194 const ExtraData *xd = GetExtraData(handle);
195 return xd->format;
196 }
197
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)198 static bool MigrateNativeHandle(
199 native_handle_t *handle,
200 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
201 if (handle == nullptr || !IsValid(handle)) {
202 return false;
203 }
204 ExtraData *ed = GetExtraData(handle);
205 if (!ed) return false;
206 ed->generation = generation;
207 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
208 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
209 ed->igbp_slot = igbp_slot;
210 return true;
211 }
212
213
UnwrapNativeHandle(const C2Handle * const handle)214 static native_handle_t* UnwrapNativeHandle(
215 const C2Handle *const handle) {
216 const ExtraData *xd = GetExtraData(handle);
217 if (xd == nullptr || xd->magic != MAGIC) {
218 return nullptr;
219 }
220 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
221 if (res != nullptr) {
222 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
223 }
224 return res;
225 }
226
Import(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)227 static const C2HandleGralloc* Import(
228 const C2Handle *const handle,
229 uint32_t *width, uint32_t *height, uint32_t *format,
230 uint64_t *usage, uint32_t *stride,
231 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
232 const ExtraData *xd = GetExtraData(handle);
233 if (xd == nullptr) {
234 return nullptr;
235 }
236 *width = xd->width;
237 *height = xd->height;
238 *format = xd->format;
239 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
240 *stride = xd->stride;
241 *generation = xd->generation;
242 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
243 *igbp_slot = xd->igbp_slot;
244 return reinterpret_cast<const C2HandleGralloc *>(handle);
245 }
246 };
247
248 static
Gralloc4Mapper_lock(native_handle_t * handle,uint64_t usage,const Rect & bounds,C2PlanarLayout * layout,uint8_t ** addr)249 c2_status_t Gralloc4Mapper_lock(native_handle_t *handle, uint64_t usage, const Rect& bounds,
250 C2PlanarLayout *layout, uint8_t **addr) {
251 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
252
253 std::vector<ui::PlaneLayout> planes;
254 // this method is only supported on Gralloc 4 or later
255 status_t err = mapper.getPlaneLayouts(handle, &planes);
256 if (err != NO_ERROR || planes.empty()) {
257 return C2_CANNOT_DO;
258 }
259
260 uint8_t *pointer = nullptr;
261 err = mapper.lock(handle, usage, bounds, (void **)&pointer, nullptr, nullptr);
262 if (err != NO_ERROR || pointer == nullptr) {
263 return C2_CORRUPTED;
264 }
265
266 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
267 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
268
269 layout->type = C2PlanarLayout::TYPE_YUV;
270 layout->numPlanes = 0;
271 layout->rootPlanes = 0;
272
273 for (const ui::PlaneLayout &plane : planes) {
274 layout->rootPlanes++;
275 uint32_t lastOffsetInBits = 0;
276 uint32_t rootIx = layout->numPlanes;
277
278 for (const PlaneLayoutComponent &component : plane.components) {
279 if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
280 mapper.unlock(handle);
281 return C2_CANNOT_DO;
282 }
283
284 uint32_t rightShiftBits = component.offsetInBits - lastOffsetInBits;
285 uint32_t allocatedDepthInBits = component.sizeInBits + rightShiftBits;
286 C2PlanarLayout::plane_index_t planeId;
287 C2PlaneInfo::channel_t channel;
288
289 switch (static_cast<PlaneLayoutComponentType>(component.type.value)) {
290 case PlaneLayoutComponentType::Y:
291 planeId = C2PlanarLayout::PLANE_Y;
292 channel = C2PlaneInfo::CHANNEL_Y;
293 break;
294 case PlaneLayoutComponentType::CB:
295 planeId = C2PlanarLayout::PLANE_U;
296 channel = C2PlaneInfo::CHANNEL_CB;
297 break;
298 case PlaneLayoutComponentType::CR:
299 planeId = C2PlanarLayout::PLANE_V;
300 channel = C2PlaneInfo::CHANNEL_CR;
301 break;
302 default:
303 mapper.unlock(handle);
304 return C2_CORRUPTED;
305 }
306
307 addr[planeId] = pointer + plane.offsetInBytes + (component.offsetInBits / 8);
308 layout->planes[planeId] = {
309 channel, // channel
310 static_cast<int32_t>(plane.sampleIncrementInBits / 8), // colInc
311 static_cast<int32_t>(plane.strideInBytes), // rowInc
312 static_cast<uint32_t>(plane.horizontalSubsampling), // mColSampling
313 static_cast<uint32_t>(plane.verticalSubsampling), // mRowSampling
314 allocatedDepthInBits, // allocatedDepth (bits)
315 static_cast<uint32_t>(component.sizeInBits), // bitDepth (bits)
316 rightShiftBits, // rightShift (bits)
317 C2PlaneInfo::NATIVE, // endianness
318 rootIx, // rootIx
319 static_cast<uint32_t>(component.offsetInBits / 8), // offset (bytes)
320 };
321
322 layout->numPlanes++;
323 lastOffsetInBits = component.offsetInBits + component.sizeInBits;
324 }
325 }
326 return C2_OK;
327 }
328
329 } // unnamed namespace
330
331
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)332 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
333 return C2HandleGralloc::UnwrapNativeHandle(handle);
334 }
335
WrapNativeCodec2GrallocHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)336 C2Handle *WrapNativeCodec2GrallocHandle(
337 const native_handle_t *const handle,
338 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
339 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
340 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
341 generation, igbp_id, igbp_slot);
342 }
343
ExtractFormatFromCodec2GrallocHandle(const C2Handle * const handle)344 uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle) {
345 return C2HandleGralloc::getPixelFormat(handle);
346 }
347
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)348 bool MigrateNativeCodec2GrallocHandle(
349 native_handle_t *handle,
350 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
351 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
352 }
353
354
355 class C2AllocationGralloc : public C2GraphicAllocation {
356 public:
357 virtual ~C2AllocationGralloc() override;
358
359 virtual c2_status_t map(
360 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
361 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
362 virtual c2_status_t unmap(
363 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const364 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const365 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
366 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
367
368 // internal methods
369 // |handle| will be moved.
370
371 C2AllocationGralloc(
372 uint32_t width, uint32_t height,
373 uint32_t format, uint32_t layerCount,
374 uint64_t grallocUsage, uint32_t stride,
375 hidl_handle &hidlHandle,
376 const C2HandleGralloc *const handle,
377 C2Allocator::id_t allocatorId);
378 int dup() const;
379 c2_status_t status() const;
380
381 private:
382 const uint32_t mWidth;
383 const uint32_t mHeight;
384 const uint32_t mFormat;
385 const uint32_t mLayerCount;
386 const uint64_t mGrallocUsage;
387 const uint32_t mStride;
388 const hidl_handle mHidlHandle;
389 const C2HandleGralloc *mHandle;
390 buffer_handle_t mBuffer;
391 const C2HandleGralloc *mLockedHandle;
392 bool mLocked;
393 C2Allocator::id_t mAllocatorId;
394 std::mutex mMappedLock;
395 };
396
C2AllocationGralloc(uint32_t width,uint32_t height,uint32_t format,uint32_t layerCount,uint64_t grallocUsage,uint32_t stride,hidl_handle & hidlHandle,const C2HandleGralloc * const handle,C2Allocator::id_t allocatorId)397 C2AllocationGralloc::C2AllocationGralloc(
398 uint32_t width, uint32_t height,
399 uint32_t format, uint32_t layerCount,
400 uint64_t grallocUsage, uint32_t stride,
401 hidl_handle &hidlHandle,
402 const C2HandleGralloc *const handle,
403 C2Allocator::id_t allocatorId)
404 : C2GraphicAllocation(width, height),
405 mWidth(width),
406 mHeight(height),
407 mFormat(format),
408 mLayerCount(layerCount),
409 mGrallocUsage(grallocUsage),
410 mStride(stride),
411 mHidlHandle(std::move(hidlHandle)),
412 mHandle(handle),
413 mBuffer(nullptr),
414 mLockedHandle(nullptr),
415 mLocked(false),
416 mAllocatorId(allocatorId) {
417 }
418
~C2AllocationGralloc()419 C2AllocationGralloc::~C2AllocationGralloc() {
420 if (mBuffer && mLocked) {
421 // implementation ignores addresss and rect
422 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
423 unmap(addr, C2Rect(), nullptr);
424 }
425 if (mBuffer) {
426 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
427 if (err) {
428 ALOGE("failed transaction: freeBuffer");
429 }
430 }
431 if (mHandle) {
432 native_handle_delete(
433 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
434 }
435 if (mLockedHandle) {
436 native_handle_delete(
437 const_cast<native_handle_t *>(
438 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
439 }
440 }
441
map(C2Rect c2Rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)442 c2_status_t C2AllocationGralloc::map(
443 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
444 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
445 const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
446 (int32_t)(c2Rect.left + c2Rect.width) /* right */,
447 (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
448
449 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
450 ALOGV("mapping buffer with usage %#llx => %#llx",
451 (long long)usage.expected, (long long)grallocUsage);
452
453 // TODO
454 (void)fence;
455
456 std::lock_guard<std::mutex> lock(mMappedLock);
457 if (mBuffer && mLocked) {
458 ALOGD("already mapped");
459 return C2_DUPLICATE;
460 }
461 if (!layout || !addr) {
462 ALOGD("wrong param");
463 return C2_BAD_VALUE;
464 }
465
466 if (!mBuffer) {
467 status_t err = GraphicBufferMapper::get().importBuffer(
468 mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
469 mFormat, mGrallocUsage, mStride, &mBuffer);
470 if (err) {
471 ALOGE("failed transaction: importBuffer");
472 return C2_CORRUPTED;
473 }
474 if (mBuffer == nullptr) {
475 ALOGD("importBuffer returned null buffer");
476 return C2_CORRUPTED;
477 }
478 uint32_t generation = 0;
479 uint64_t igbp_id = 0;
480 uint32_t igbp_slot = 0;
481 if (mHandle) {
482 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
483 }
484
485 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
486 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
487 mStride, generation, igbp_id, igbp_slot);
488 }
489
490 // 'NATIVE' on Android means LITTLE_ENDIAN
491 constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
492
493 switch (mFormat) {
494 case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
495 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
496 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
497 // default to YUV for now.
498 void *pointer = nullptr;
499 // TODO: fence
500 status_t err = GraphicBufferMapper::get().lock(
501 const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
502 if (err) {
503 ALOGE("failed transaction: lock(RGBA_1010102)");
504 return C2_CORRUPTED;
505 }
506 // treat as 32-bit values
507 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
508 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
509 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
510 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
511 layout->type = C2PlanarLayout::TYPE_YUVA;
512 layout->numPlanes = 4;
513 layout->rootPlanes = 1;
514 layout->planes[C2PlanarLayout::PLANE_Y] = {
515 C2PlaneInfo::CHANNEL_Y, // channel
516 4, // colInc
517 static_cast<int32_t>(4 * mStride), // rowInc
518 1, // mColSampling
519 1, // mRowSampling
520 32, // allocatedDepth
521 10, // bitDepth
522 10, // rightShift
523 C2PlaneInfo::LITTLE_END, // endianness
524 C2PlanarLayout::PLANE_Y, // rootIx
525 0, // offset
526 };
527 layout->planes[C2PlanarLayout::PLANE_U] = {
528 C2PlaneInfo::CHANNEL_CB, // channel
529 4, // colInc
530 static_cast<int32_t>(4 * mStride), // rowInc
531 1, // mColSampling
532 1, // mRowSampling
533 32, // allocatedDepth
534 10, // bitDepth
535 0, // rightShift
536 C2PlaneInfo::LITTLE_END, // endianness
537 C2PlanarLayout::PLANE_Y, // rootIx
538 0, // offset
539 };
540 layout->planes[C2PlanarLayout::PLANE_V] = {
541 C2PlaneInfo::CHANNEL_CR, // channel
542 4, // colInc
543 static_cast<int32_t>(4 * mStride), // rowInc
544 1, // mColSampling
545 1, // mRowSampling
546 32, // allocatedDepth
547 10, // bitDepth
548 20, // rightShift
549 C2PlaneInfo::LITTLE_END, // endianness
550 C2PlanarLayout::PLANE_Y, // rootIx
551 0, // offset
552 };
553 layout->planes[C2PlanarLayout::PLANE_A] = {
554 C2PlaneInfo::CHANNEL_A, // channel
555 4, // colInc
556 static_cast<int32_t>(4 * mStride), // rowInc
557 1, // mColSampling
558 1, // mRowSampling
559 32, // allocatedDepth
560 2, // bitDepth
561 30, // rightShift
562 C2PlaneInfo::LITTLE_END, // endianness
563 C2PlanarLayout::PLANE_Y, // rootIx
564 0, // offset
565 };
566 break;
567 }
568
569 case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
570 // TODO: alpha channel
571 // fall-through
572 case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
573 void *pointer = nullptr;
574 // TODO: fence
575 status_t err = GraphicBufferMapper::get().lock(
576 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
577 if (err) {
578 ALOGE("failed transaction: lock(RGBA_8888)");
579 return C2_CORRUPTED;
580 }
581 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
582 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
583 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
584 layout->type = C2PlanarLayout::TYPE_RGB;
585 layout->numPlanes = 3;
586 layout->rootPlanes = 1;
587 layout->planes[C2PlanarLayout::PLANE_R] = {
588 C2PlaneInfo::CHANNEL_R, // channel
589 4, // colInc
590 static_cast<int32_t>(4 * mStride), // rowInc
591 1, // mColSampling
592 1, // mRowSampling
593 8, // allocatedDepth
594 8, // bitDepth
595 0, // rightShift
596 C2PlaneInfo::NATIVE, // endianness
597 C2PlanarLayout::PLANE_R, // rootIx
598 0, // offset
599 };
600 layout->planes[C2PlanarLayout::PLANE_G] = {
601 C2PlaneInfo::CHANNEL_G, // channel
602 4, // colInc
603 static_cast<int32_t>(4 * mStride), // rowInc
604 1, // mColSampling
605 1, // mRowSampling
606 8, // allocatedDepth
607 8, // bitDepth
608 0, // rightShift
609 C2PlaneInfo::NATIVE, // endianness
610 C2PlanarLayout::PLANE_R, // rootIx
611 1, // offset
612 };
613 layout->planes[C2PlanarLayout::PLANE_B] = {
614 C2PlaneInfo::CHANNEL_B, // channel
615 4, // colInc
616 static_cast<int32_t>(4 * mStride), // rowInc
617 1, // mColSampling
618 1, // mRowSampling
619 8, // allocatedDepth
620 8, // bitDepth
621 0, // rightShift
622 C2PlaneInfo::NATIVE, // endianness
623 C2PlanarLayout::PLANE_R, // rootIx
624 2, // offset
625 };
626 break;
627 }
628
629 case static_cast<uint32_t>(PixelFormat4::BLOB): {
630 void *pointer = nullptr;
631 // TODO: fence
632 status_t err = GraphicBufferMapper::get().lock(
633 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
634 if (err) {
635 ALOGE("failed transaction: lock(BLOB)");
636 return C2_CORRUPTED;
637 }
638 *addr = (uint8_t *)pointer;
639 break;
640 }
641
642 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
643 // fall-through
644 case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
645 // fall-through
646 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
647 // fall-through
648 case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
649 // fall-through
650 case static_cast<uint32_t>(PixelFormat4::YV12): {
651 android_ycbcr ycbcrLayout;
652
653 status_t err = GraphicBufferMapper::get().lockYCbCr(
654 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
655 if (err) {
656 ALOGE("failed transaction: lockYCbCr (err=%d)", err);
657 return C2_CORRUPTED;
658 }
659 if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
660 || ycbcrLayout.ystride == 0
661 || ycbcrLayout.cstride == 0
662 || ycbcrLayout.chroma_step == 0) {
663 ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
664 "ystride=%zu cstride=%zu chroma_step=%zu)",
665 ycbcrLayout.y ? "(non-null)" : "(null)",
666 ycbcrLayout.cb ? "(non-null)" : "(null)",
667 ycbcrLayout.cr ? "(non-null)" : "(null)",
668 ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
669 return C2_CORRUPTED;
670 }
671
672 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
673 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
674 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
675 layout->type = C2PlanarLayout::TYPE_YUV;
676 layout->numPlanes = 3;
677 layout->rootPlanes = 3;
678 layout->planes[C2PlanarLayout::PLANE_Y] = {
679 C2PlaneInfo::CHANNEL_Y, // channel
680 1, // colInc
681 (int32_t)ycbcrLayout.ystride, // rowInc
682 1, // mColSampling
683 1, // mRowSampling
684 8, // allocatedDepth
685 8, // bitDepth
686 0, // rightShift
687 C2PlaneInfo::NATIVE, // endianness
688 C2PlanarLayout::PLANE_Y, // rootIx
689 0, // offset
690 };
691 layout->planes[C2PlanarLayout::PLANE_U] = {
692 C2PlaneInfo::CHANNEL_CB, // channel
693 (int32_t)ycbcrLayout.chroma_step, // colInc
694 (int32_t)ycbcrLayout.cstride, // rowInc
695 2, // mColSampling
696 2, // mRowSampling
697 8, // allocatedDepth
698 8, // bitDepth
699 0, // rightShift
700 C2PlaneInfo::NATIVE, // endianness
701 C2PlanarLayout::PLANE_U, // rootIx
702 0, // offset
703 };
704 layout->planes[C2PlanarLayout::PLANE_V] = {
705 C2PlaneInfo::CHANNEL_CR, // channel
706 (int32_t)ycbcrLayout.chroma_step, // colInc
707 (int32_t)ycbcrLayout.cstride, // rowInc
708 2, // mColSampling
709 2, // mRowSampling
710 8, // allocatedDepth
711 8, // bitDepth
712 0, // rightShift
713 C2PlaneInfo::NATIVE, // endianness
714 C2PlanarLayout::PLANE_V, // rootIx
715 0, // offset
716 };
717 break;
718 }
719
720 case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
721 // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
722 // try locking with the gralloc4 mapper first.
723 c2_status_t status = Gralloc4Mapper_lock(
724 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
725 if (status == C2_OK) {
726 break;
727 }
728
729 void *pointer = nullptr;
730 status_t err = GraphicBufferMapper::get().lock(
731 const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
732 if (err) {
733 ALOGE("failed transaction: lock(YCBCR_P010)");
734 return C2_CORRUPTED;
735 }
736 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
737 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + mStride * 2 * rect.height();
738 addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
739 layout->type = C2PlanarLayout::TYPE_YUV;
740 layout->numPlanes = 3;
741 layout->rootPlanes = 2;
742 layout->planes[C2PlanarLayout::PLANE_Y] = {
743 C2PlaneInfo::CHANNEL_Y, // channel
744 2, // colInc
745 static_cast<int32_t>(2 * mStride), // rowInc
746 1, // mColSampling
747 1, // mRowSampling
748 16, // allocatedDepth
749 10, // bitDepth
750 6, // rightShift
751 kEndianness, // endianness
752 C2PlanarLayout::PLANE_Y, // rootIx
753 0, // offset
754 };
755 layout->planes[C2PlanarLayout::PLANE_U] = {
756 C2PlaneInfo::CHANNEL_CB, // channel
757 4, // colInc
758 static_cast<int32_t>(2 * mStride), // rowInc
759 2, // mColSampling
760 2, // mRowSampling
761 16, // allocatedDepth
762 10, // bitDepth
763 6, // rightShift
764 kEndianness, // endianness
765 C2PlanarLayout::PLANE_U, // rootIx
766 0, // offset
767 };
768 layout->planes[C2PlanarLayout::PLANE_V] = {
769 C2PlaneInfo::CHANNEL_CR, // channel
770 4, // colInc
771 static_cast<int32_t>(2 * mStride), // rowInc
772 2, // mColSampling
773 2, // mRowSampling
774 16, // allocatedDepth
775 10, // bitDepth
776 6, // rightShift
777 kEndianness, // endianness
778 C2PlanarLayout::PLANE_U, // rootIx
779 2, // offset
780 };
781 break;
782 }
783
784 default: {
785 // We don't know what it is, let's try to lock it with gralloc4
786 android_ycbcr ycbcrLayout;
787 if (isAtLeastT()) {
788 c2_status_t status = Gralloc4Mapper_lock(
789 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
790 if (status == C2_OK) {
791 break;
792 }
793 }
794
795 // fallback to lockYCbCr
796 status_t err = GraphicBufferMapper::get().lockYCbCr(
797 const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
798 if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
799 && ycbcrLayout.ystride > 0
800 && ycbcrLayout.cstride > 0
801 && ycbcrLayout.chroma_step > 0) {
802 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
803 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
804 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
805 layout->type = C2PlanarLayout::TYPE_YUV;
806 layout->numPlanes = 3;
807 layout->rootPlanes = 3;
808 layout->planes[C2PlanarLayout::PLANE_Y] = {
809 C2PlaneInfo::CHANNEL_Y, // channel
810 1, // colInc
811 (int32_t)ycbcrLayout.ystride, // rowInc
812 1, // mColSampling
813 1, // mRowSampling
814 8, // allocatedDepth
815 8, // bitDepth
816 0, // rightShift
817 C2PlaneInfo::NATIVE, // endianness
818 C2PlanarLayout::PLANE_Y, // rootIx
819 0, // offset
820 };
821 layout->planes[C2PlanarLayout::PLANE_U] = {
822 C2PlaneInfo::CHANNEL_CB, // channel
823 (int32_t)ycbcrLayout.chroma_step, // colInc
824 (int32_t)ycbcrLayout.cstride, // rowInc
825 2, // mColSampling
826 2, // mRowSampling
827 8, // allocatedDepth
828 8, // bitDepth
829 0, // rightShift
830 C2PlaneInfo::NATIVE, // endianness
831 C2PlanarLayout::PLANE_U, // rootIx
832 0, // offset
833 };
834 layout->planes[C2PlanarLayout::PLANE_V] = {
835 C2PlaneInfo::CHANNEL_CR, // channel
836 (int32_t)ycbcrLayout.chroma_step, // colInc
837 (int32_t)ycbcrLayout.cstride, // rowInc
838 2, // mColSampling
839 2, // mRowSampling
840 8, // allocatedDepth
841 8, // bitDepth
842 0, // rightShift
843 C2PlaneInfo::NATIVE, // endianness
844 C2PlanarLayout::PLANE_V, // rootIx
845 0, // offset
846 };
847 break;
848 }
849
850 // We really don't know what this is; lock the buffer and pass it through ---
851 // the client may know how to interpret it.
852
853 // unlock previous allocation if it was successful
854 if (err == OK) {
855 err = GraphicBufferMapper::get().unlock(mBuffer);
856 if (err) {
857 ALOGE("failed transaction: unlock");
858 return C2_CORRUPTED;
859 }
860 }
861
862 void *pointer = nullptr;
863 err = GraphicBufferMapper::get().lock(
864 const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
865 if (err) {
866 ALOGE("failed transaction: lock(??? %x)", mFormat);
867 return C2_CORRUPTED;
868 }
869 addr[0] = (uint8_t *)pointer;
870 layout->type = C2PlanarLayout::TYPE_UNKNOWN;
871 layout->numPlanes = 1;
872 layout->rootPlanes = 1;
873 layout->planes[0] = {
874 // TODO: CHANNEL_UNKNOWN?
875 C2PlaneInfo::channel_t(0xFF), // channel
876 1, // colInc
877 int32_t(mStride), // rowInc
878 1, // mColSampling
879 1, // mRowSampling
880 8, // allocatedDepth
881 8, // bitDepth
882 0, // rightShift
883 C2PlaneInfo::NATIVE, // endianness
884 0, // rootIx
885 0, // offset
886 };
887 break;
888 }
889 }
890 mLocked = true;
891
892 // handle interleaved formats
893 if (layout->type == C2PlanarLayout::TYPE_YUV && layout->rootPlanes == 3) {
894 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
895 intptr_t uvColInc = layout->planes[C2PlanarLayout::PLANE_U].colInc;
896 if (uvOffset > 0 && uvOffset < uvColInc) {
897 layout->rootPlanes = 2;
898 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
899 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
900 } else if (uvOffset < 0 && uvOffset > -uvColInc) {
901 layout->rootPlanes = 2;
902 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
903 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
904 }
905 }
906
907 ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
908 layout->type, layout->numPlanes, layout->rootPlanes);
909 for (int i = 0; i < layout->numPlanes; ++i) {
910 const C2PlaneInfo &plane = layout->planes[i];
911 ALOGV("C2AllocationGralloc::map: plane[%d]: colInc=%d rowInc=%d rootIx=%u offset=%u",
912 i, plane.colInc, plane.rowInc, plane.rootIx, plane.offset);
913 }
914
915 return C2_OK;
916 }
917
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)918 c2_status_t C2AllocationGralloc::unmap(
919 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
920 // TODO: check addr and size, use fence
921 (void)addr;
922 (void)rect;
923 (void)fence;
924
925 std::lock_guard<std::mutex> lock(mMappedLock);
926 // TODO: fence
927 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
928 if (err) {
929 ALOGE("failed transaction: unlock");
930 return C2_CORRUPTED;
931 }
932
933 mLocked = false;
934 return C2_OK;
935 }
936
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const937 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
938 return other && other->handle() == handle();
939 }
940
941 /* ===================================== GRALLOC ALLOCATOR ==================================== */
942 class C2AllocatorGralloc::Impl {
943 public:
944 Impl(id_t id, bool bufferQueue);
945
getId() const946 id_t getId() const {
947 return mTraits->id;
948 }
949
getName() const950 C2String getName() const {
951 return mTraits->name;
952 }
953
getTraits() const954 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
955 return mTraits;
956 }
957
958 c2_status_t newGraphicAllocation(
959 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
960 std::shared_ptr<C2GraphicAllocation> *allocation);
961
962 c2_status_t priorGraphicAllocation(
963 const C2Handle *handle,
964 std::shared_ptr<C2GraphicAllocation> *allocation);
965
status() const966 c2_status_t status() const { return mInit; }
967
968 private:
969 std::shared_ptr<C2Allocator::Traits> mTraits;
970 c2_status_t mInit;
971 const bool mBufferQueue;
972 };
973
_UnwrapNativeCodec2GrallocMetadata(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)974 void _UnwrapNativeCodec2GrallocMetadata(
975 const C2Handle *const handle,
976 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
977 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
978 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
979 generation, igbp_id, igbp_slot);
980 }
981
Impl(id_t id,bool bufferQueue)982 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
983 : mInit(C2_OK), mBufferQueue(bufferQueue) {
984 // TODO: get this from allocator
985 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
986 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
987 mTraits = std::make_shared<C2Allocator::Traits>(traits);
988 }
989
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)990 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
991 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
992 std::shared_ptr<C2GraphicAllocation> *allocation) {
993 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
994 ALOGV("allocating buffer with usage %#llx => %#llx",
995 (long long)usage.expected, (long long)grallocUsage);
996
997 buffer_handle_t buffer;
998
999 uint32_t stride = 0;
1000
1001 status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
1002 1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
1003 if (err) {
1004 ALOGE("failed transaction: allocate");
1005 return C2_CORRUPTED;
1006 }
1007
1008 hidl_handle hidlHandle;
1009 hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
1010
1011 allocation->reset(new C2AllocationGralloc(
1012 width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
1013 C2HandleGralloc::WrapAndMoveNativeHandle(
1014 hidlHandle, width, height,
1015 format, grallocUsage, stride,
1016 0, 0, mBufferQueue ? ~0 : 0),
1017 mTraits->id));
1018 return C2_OK;
1019 }
1020
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1021 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
1022 const C2Handle *handle,
1023 std::shared_ptr<C2GraphicAllocation> *allocation) {
1024
1025 uint32_t generation;
1026 uint64_t igbp_id;
1027 uint32_t igbp_slot;
1028
1029 uint32_t width;
1030 uint32_t height;
1031 uint32_t format;
1032 uint32_t layerCount = 1;
1033 uint64_t grallocUsage;
1034 uint32_t stride;
1035
1036 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1037 handle, &width, &height, &format, &grallocUsage, &stride,
1038 &generation, &igbp_id, &igbp_slot);
1039 if (grallocHandle == nullptr) {
1040 return C2_BAD_VALUE;
1041 }
1042
1043 hidl_handle hidlHandle;
1044 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1045
1046 allocation->reset(new C2AllocationGralloc(
1047 width, height, format, layerCount,
1048 grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
1049 return C2_OK;
1050 }
1051
C2AllocatorGralloc(id_t id,bool bufferQueue)1052 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
1053 : mImpl(new Impl(id, bufferQueue)) {}
1054
~C2AllocatorGralloc()1055 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
1056
getId() const1057 C2Allocator::id_t C2AllocatorGralloc::getId() const {
1058 return mImpl->getId();
1059 }
1060
getName() const1061 C2String C2AllocatorGralloc::getName() const {
1062 return mImpl->getName();
1063 }
1064
getTraits() const1065 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
1066 return mImpl->getTraits();
1067 }
1068
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)1069 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
1070 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1071 std::shared_ptr<C2GraphicAllocation> *allocation) {
1072 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1073 }
1074
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1075 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
1076 const C2Handle *handle,
1077 std::shared_ptr<C2GraphicAllocation> *allocation) {
1078 return mImpl->priorGraphicAllocation(handle, allocation);
1079 }
1080
status() const1081 c2_status_t C2AllocatorGralloc::status() const {
1082 return mImpl->status();
1083 }
1084
1085 // static
CheckHandle(const C2Handle * const o)1086 bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
1087 return C2HandleGralloc::IsValid(o);
1088 }
1089
1090 } // namespace android
1091