1 /*
2 * Copyright (C) 2024 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 #include <cstring>
18 #include <string_view>
19 
20 #include <sched.h>
21 
22 #include <android-base/unique_fd.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25 
26 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
27 #include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
28 #include <aidl/android/hardware/graphics/allocator/BnAllocator.h>
29 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
30 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
31 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
32 
33 #include <aidlcommonsupport/NativeHandle.h>
34 
35 #include <debug.h>
36 #include <drm_fourcc.h>
37 #include <glUtils.h>
38 #include <goldfish_address_space.h>
39 #include <gralloc_cb_bp.h>
40 #include <qemu_pipe_bp.h>
41 
42 #include "CbExternalMetadata.h"
43 #include "DebugLevel.h"
44 #include "HostConnectionSession.h"
45 
46 using ::aidl::android::hardware::graphics::allocator::AllocationError;
47 using ::aidl::android::hardware::graphics::allocator::AllocationResult;
48 using ::aidl::android::hardware::graphics::allocator::BnAllocator;
49 using ::aidl::android::hardware::graphics::allocator::BufferDescriptorInfo;
50 using ::aidl::android::hardware::graphics::common::BufferUsage;
51 using ::aidl::android::hardware::graphics::common::PixelFormat;
52 using ::aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
53 
54 #ifndef GL_RGBA16F
55 #define GL_RGBA16F                        0x881A
56 #endif // GL_RGBA16F
57 
58 #ifndef GL_HALF_FLOAT
59 #define GL_HALF_FLOAT                     0x140B
60 #endif // GL_HALF_FLOAT
61 
62 #ifndef GL_RGB10_A2
63 #define GL_RGB10_A2                       0x8059
64 #endif // GL_RGB10_A2
65 
66 #ifndef GL_UNSIGNED_INT_2_10_10_10_REV
67 #define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
68 #endif // GL_UNSIGNED_INT_2_10_10_10_REV
69 
70 namespace {
71 enum class EmulatorFrameworkFormat : uint8_t {
72     GL_COMPATIBLE = 0,
73     YV12 = 1,
74     YUV_420_888 = 2, // (Y+)(U+)(V+)
75 };
76 
align(const size_t value,const size_t alignmentP2)77 size_t align(const size_t value, const size_t alignmentP2) {
78     return (value + alignmentP2 - 1) & ~(alignmentP2 - 1);
79 }
80 
strnlen(const char * str,const size_t maxSize)81 size_t strnlen(const char* str, const size_t maxSize) {
82     const char* const begin = str;
83     const char* const end = begin + maxSize;
84     for (; *str && (str != end); ++str) {}
85     return str - begin;
86 }
87 
toBinderStatus(const AllocationError error)88 ndk::ScopedAStatus toBinderStatus(const AllocationError error) {
89     return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
90 }
91 
toUsage64(const BufferUsage usage)92 uint64_t toUsage64(const BufferUsage usage) {
93     return static_cast<uint64_t>(usage);
94 }
95 
needGpuBuffer(const uint64_t usage)96 bool needGpuBuffer(const uint64_t usage) {
97     return usage & (toUsage64(BufferUsage::GPU_TEXTURE)
98                     | toUsage64(BufferUsage::GPU_RENDER_TARGET)
99                     | toUsage64(BufferUsage::COMPOSER_OVERLAY)
100                     | toUsage64(BufferUsage::COMPOSER_CLIENT_TARGET)
101                     | toUsage64(BufferUsage::GPU_DATA_BUFFER));
102 }
103 
needCpuBuffer(const uint64_t usage)104 bool needCpuBuffer(const uint64_t usage) {
105     return usage & (toUsage64(BufferUsage::CPU_READ_MASK)
106                     | toUsage64(BufferUsage::CPU_WRITE_MASK));
107 }
108 
makePlaneLayoutComponent(const PlaneLayoutComponentType type,const unsigned offsetInBits,const unsigned sizeInBits)109 PlaneLayoutComponent makePlaneLayoutComponent(const PlaneLayoutComponentType type,
110                                               const unsigned offsetInBits,
111                                               const unsigned sizeInBits) {
112     return {
113         .type = static_cast<uint32_t>(type),
114         .offsetInBits = static_cast<uint16_t>(offsetInBits),
115         .sizeInBits = static_cast<uint16_t>(sizeInBits),
116     };
117 }
118 
initPlaneLayout(PlaneLayout & plane,const uint32_t width,const uint32_t height,const size_t offsetInBytes,const uint32_t alignment,const unsigned sampleSizeInBytes,const unsigned subsamplingShift,const unsigned componentsBase,const unsigned componentsSize)119 size_t initPlaneLayout(PlaneLayout& plane,
120                        const uint32_t width,
121                        const uint32_t height,
122                        const size_t offsetInBytes,
123                        const uint32_t alignment,
124                        const unsigned sampleSizeInBytes,
125                        const unsigned subsamplingShift,
126                        const unsigned componentsBase,
127                        const unsigned componentsSize) {
128     const uint32_t strideInBytes = align(width * sampleSizeInBytes, alignment);
129 
130     plane.offsetInBytes = offsetInBytes;
131     plane.strideInBytes = strideInBytes;
132     plane.totalSizeInBytes = strideInBytes * height;
133     plane.sampleIncrementInBytes = sampleSizeInBytes;
134     plane.horizontalSubsamplingShift = subsamplingShift;
135     plane.verticalSubsamplingShift = subsamplingShift;
136     plane.componentsBase = componentsBase;
137     plane.componentsSize = componentsSize;
138 
139     return offsetInBytes + plane.totalSizeInBytes;
140 }
141 
142 struct GoldfishAllocator : public BnAllocator {
GoldfishAllocator__anon4bbb6fa40111::GoldfishAllocator143     GoldfishAllocator()
144         : mHostConn(HostConnection::createUnique(kCapsetNone))
145         , mDebugLevel(getDebugLevel()) {}
146 
allocate2__anon4bbb6fa40111::GoldfishAllocator147     ndk::ScopedAStatus allocate2(const BufferDescriptorInfo& desc,
148                                  const int32_t count,
149                                  AllocationResult* const outResult) override {
150         if (count <= 0) {
151             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
152                                             "%s: count=%d", "BAD_DESCRIPTOR",
153                                             count));
154         }
155         if (desc.width <= 0) {
156             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
157                                             "%s: width=%d", "BAD_DESCRIPTOR",
158                                             desc.width));
159         }
160         if (desc.height <= 0) {
161             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
162                                             "%s: height=%d", "BAD_DESCRIPTOR",
163                                             desc.height));
164         }
165         if (!validateUsage(desc.usage)) {
166             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
167                                             "%s: usage=0x%" PRIX64, "BAD_DESCRIPTOR",
168                                             toUsage64(desc.usage)));
169         }
170         if (desc.layerCount != 1) {
171             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
172                                             "%s: layerCount=%d", "BAD_DESCRIPTOR",
173                                             desc.layerCount));
174         }
175         if (desc.reservedSize < 0) {
176             return toBinderStatus(FAILURE_V(AllocationError::BAD_DESCRIPTOR,
177                                             "%s: reservedSize=%" PRId64, "BAD_DESCRIPTOR",
178                                             desc.reservedSize));
179         }
180         if (!desc.additionalOptions.empty()) {
181             return toBinderStatus(FAILURE_V(
182                 AllocationError::BAD_DESCRIPTOR, "%s: %s", "BAD_DESCRIPTOR",
183                 "'BufferDescriptorInfo::additionalOptions' are not supported"));
184         }
185 
186         const uint64_t usage = toUsage64(desc.usage);
187         const uint32_t width = desc.width;
188         const uint32_t height = desc.height;
189         size_t offsetInBytes = 0;
190 
191         AllocationRequest req;
192         switch (desc.format) {
193         case PixelFormat::RGBA_8888:
194             req.glFormat = GL_RGBA;
195             req.glType = GL_UNSIGNED_BYTE;
196 
197             req.drmFormat = DRM_FORMAT_ABGR8888;
198 
199             req.planeSize = 1;
200             offsetInBytes = initPlaneLayout(
201                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
202                 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
203                 /*componentsBase=*/ 0, /*componentsSize*/ 4);
204             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
205             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
206             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
207             req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 24, 8);
208             break;
209 
210         case PixelFormat::RGBX_8888:
211             req.glFormat = GL_RGBA;
212             req.glType = GL_UNSIGNED_BYTE;
213 
214             req.drmFormat = DRM_FORMAT_XBGR8888;
215 
216             req.planeSize = 1;
217             offsetInBytes = initPlaneLayout(
218                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
219                 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
220                 /*componentsBase=*/ 0, /*componentsSize*/ 3);
221             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
222             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
223             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
224             break;
225 
226         case PixelFormat::BGRA_8888:
227             req.glFormat = GL_RGBA;
228             req.glType = GL_UNSIGNED_BYTE;
229 
230             req.drmFormat = DRM_FORMAT_ARGB8888;
231 
232             req.planeSize = 1;
233             offsetInBytes = initPlaneLayout(
234                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
235                 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
236                 /*componentsBase=*/ 0, /*componentsSize*/ 4);
237             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 0, 8);
238             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
239             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 16, 8);
240             req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 24, 8);
241             break;
242 
243         case PixelFormat::RGB_888:
244             if (needGpuBuffer(usage)) {
245                 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
246             }
247 
248             req.drmFormat = DRM_FORMAT_BGR888;
249 
250             req.planeSize = 1;
251             offsetInBytes = initPlaneLayout(
252                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
253                 /*sampleSizeInBytes=*/ 3, /*subsamplingShift=*/ 0,
254                 /*componentsBase=*/ 0, /*componentsSize*/ 3);
255             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 8);
256             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 8, 8);
257             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 16, 8);
258             break;
259 
260         case PixelFormat::RGB_565:
261             req.glFormat = GL_RGB565;
262             req.glType = GL_UNSIGNED_SHORT_5_6_5;
263 
264             req.drmFormat = DRM_FORMAT_BGR565;
265 
266             req.planeSize = 1;
267             offsetInBytes = initPlaneLayout(
268                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
269                 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
270                 /*componentsBase=*/ 0, /*componentsSize*/ 3);
271             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 5);
272             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 5, 6);
273             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 11, 5);
274             break;
275 
276         case PixelFormat::RGBA_FP16:
277             req.glFormat = GL_RGBA16F;
278             req.glType = GL_HALF_FLOAT;
279 
280             req.drmFormat = DRM_FORMAT_ABGR16161616F;
281 
282             req.planeSize = 1;
283             offsetInBytes = initPlaneLayout(
284                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
285                 /*sampleSizeInBytes=*/ 8, /*subsamplingShift=*/ 0,
286                 /*componentsBase=*/ 0, /*componentsSize*/ 4);
287             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 16);
288             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 16, 16);
289             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 32, 16);
290             req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 48, 16);
291             break;
292 
293         case PixelFormat::RGBA_1010102:
294             req.glFormat = GL_RGB10_A2;
295             req.glType = GL_UNSIGNED_INT_2_10_10_10_REV;
296 
297             req.drmFormat = DRM_FORMAT_ABGR2101010;
298 
299             req.planeSize = 1;
300             offsetInBytes = initPlaneLayout(
301                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
302                 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 0,
303                 /*componentsBase=*/ 0, /*componentsSize*/ 4);
304             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::R, 0, 10);
305             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::G, 10, 10);
306             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::B, 20, 10);
307             req.planeComponent[3] = makePlaneLayoutComponent(PlaneLayoutComponentType::A, 30, 2);
308             break;
309 
310         case PixelFormat::RAW16:
311             if (needGpuBuffer(usage)) {
312                 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
313             }
314 
315             req.drmFormat = DRM_FORMAT_R16;
316 
317             req.planeSize = 1;
318             offsetInBytes = initPlaneLayout(
319                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
320                 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
321                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
322             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::RAW, 0, 16);
323             break;
324 
325         case PixelFormat::Y16:
326             if (needGpuBuffer(usage)) {
327                 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
328             }
329 
330             req.drmFormat = DRM_FORMAT_R16;
331 
332             req.planeSize = 1;
333             offsetInBytes = initPlaneLayout(
334                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
335                 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
336                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
337             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 16);
338             break;
339 
340         case PixelFormat::BLOB:
341             if (needGpuBuffer(usage)) {
342                 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
343             }
344 
345             req.planeSize = 1;
346             offsetInBytes = initPlaneLayout(
347                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
348                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
349                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
350             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::RAW, 0, 8);
351             break;
352 
353         case PixelFormat::YCRCB_420_SP:  // Y + CrCb interleaved
354             if (needGpuBuffer(usage)) {
355                 return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
356             }
357 
358             req.drmFormat = DRM_FORMAT_YVU420;
359 
360             req.planeSize = 2;
361             offsetInBytes = initPlaneLayout(
362                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
363                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
364                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
365             offsetInBytes = initPlaneLayout(
366                 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
367                 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 1,
368                 /*componentsBase=*/ 1, /*componentsSize*/ 2);
369             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
370             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
371             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 8, 8);
372             break;
373 
374         case PixelFormat::YV12:  // 3 planes (Y, Cr, Cb), 16bytes aligned
375             req.glFormat = GL_RGBA;
376             req.glType = GL_UNSIGNED_BYTE;
377             req.emuFwkFormat = EmulatorFrameworkFormat::YV12;
378 
379             req.drmFormat = DRM_FORMAT_YVU420;
380 
381             req.planeSize = 3;
382             offsetInBytes = initPlaneLayout(
383                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 16,
384                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
385                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
386             offsetInBytes = initPlaneLayout(
387                 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 16,
388                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
389                 /*componentsBase=*/ 1, /*componentsSize*/ 1);
390             offsetInBytes = initPlaneLayout(
391                 req.plane[2], width / 2, height / 2, offsetInBytes, /*alignment=*/ 16,
392                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
393                 /*componentsBase=*/ 2, /*componentsSize*/ 1);
394 
395             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
396             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
397             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 0, 8);
398             break;
399 
400         case PixelFormat::YCBCR_420_888:  // 3 planes (Y, Cb, Cr)
401             req.glFormat = GL_RGBA;
402             req.glType = GL_UNSIGNED_BYTE;
403             req.emuFwkFormat = EmulatorFrameworkFormat::YUV_420_888;
404 
405             req.drmFormat = DRM_FORMAT_YUV420;
406 
407             req.planeSize = 3;
408             offsetInBytes = initPlaneLayout(
409                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
410                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 0,
411                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
412             offsetInBytes = initPlaneLayout(
413                 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
414                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
415                 /*componentsBase=*/ 1, /*componentsSize*/ 1);
416             offsetInBytes = initPlaneLayout(
417                 req.plane[2], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
418                 /*sampleSizeInBytes=*/ 1, /*subsamplingShift=*/ 1,
419                 /*componentsBase=*/ 2, /*componentsSize*/ 1);
420 
421             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 0, 8);
422             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 0, 8);
423             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 0, 8);
424             break;
425 
426         case PixelFormat::YCBCR_P010:  // Y + CbCr interleaved, 2bytes per component
427             req.glFormat = GL_RGBA;
428             req.glType = GL_UNSIGNED_BYTE;
429 
430             req.drmFormat = DRM_FORMAT_YUV420_10BIT;
431 
432             req.planeSize = 2;
433             offsetInBytes = initPlaneLayout(
434                 req.plane[0], width, height, offsetInBytes, /*alignment=*/ 1,
435                 /*sampleSizeInBytes=*/ 2, /*subsamplingShift=*/ 0,
436                 /*componentsBase=*/ 0, /*componentsSize*/ 1);
437             offsetInBytes = initPlaneLayout(
438                 req.plane[1], width / 2, height / 2, offsetInBytes, /*alignment=*/ 1,
439                 /*sampleSizeInBytes=*/ 4, /*subsamplingShift=*/ 1,
440                 /*componentsBase=*/ 1, /*componentsSize*/ 2);
441 
442             req.planeComponent[0] = makePlaneLayoutComponent(PlaneLayoutComponentType::Y, 6, 10);
443             req.planeComponent[1] = makePlaneLayoutComponent(PlaneLayoutComponentType::CB, 6, 10);
444             req.planeComponent[2] = makePlaneLayoutComponent(PlaneLayoutComponentType::CR, 6 + 10 + 6, 10);
445             break;
446 
447         default:
448             return toBinderStatus(FAILURE_V(AllocationError::UNSUPPORTED,
449                                             "Unsupported format: format=0x%X, usage=%" PRIX64,
450                                             static_cast<uint32_t>(desc.format), desc.usage));
451         }
452 
453         req.name = std::string_view(reinterpret_cast<const char*>(desc.name.data()),
454                                     strnlen(reinterpret_cast<const char*>(desc.name.data()),
455                                     desc.name.size()));
456         req.usage = usage;
457         req.width = width;
458         req.height = height;
459         req.format = desc.format;
460         req.reservedRegionSize = desc.reservedSize;
461 
462         if (needCpuBuffer(usage)) {
463             req.imageSizeInBytes = offsetInBytes;
464             req.stride0 = (req.planeSize == 1) ?
465                               (req.plane[0].strideInBytes /
466                                req.plane[0].sampleIncrementInBytes) : 0;
467         } else {
468             req.imageSizeInBytes = 0;   // the image is not allocated
469             /*
470              * b/359874912: the spec does not say how to handle PLANE_LAYOUTS
471              * if the CPU buffer is not allocated. Let's not populate them
472              * without the CPU buffer (sizes and offsets don't make sense anyway).
473              */
474             req.planeSize = 0;
475             req.stride0 = 0;
476         }
477 
478         if (needGpuBuffer(usage)) {
479             req.rcAllocFormat = (req.format == PixelFormat::RGBX_8888) ? GL_RGB : req.glFormat;
480         } else {
481             req.glFormat = -1;  // no GPU buffer - no GPU formats
482             req.glType = -1;
483             req.rcAllocFormat = -1;
484         }
485 
486         std::vector<std::unique_ptr<cb_handle_t>> cbs(count);
487 
488         {
489             HostConnectionSession connSession(mHostConn.get());
490             ExtendedRCEncoderContext* const rcEnc = connSession.getRcEncoder();
491             LOG_ALWAYS_FATAL_IF(!rcEnc);
492             const bool hasSharedSlots =
493                 rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator;
494 
495             for (int i = 0; i < count; ++i) {
496                 std::unique_ptr<cb_handle_t> cb = allocateImpl(
497                     req, *rcEnc, ++mBufferIdGenerator, hasSharedSlots);
498                 if (cb) {
499                     cbs[i] = std::move(cb);
500                 } else {
501                     for (--i; i > 0; --i) {
502                         unallocate(std::move(cbs[i]));
503                     }
504                     return toBinderStatus(FAILURE(AllocationError::NO_RESOURCES));
505                 }
506             }
507         }
508 
509         outResult->stride = req.stride0;
510         outResult->buffers.reserve(count);
511         for (auto& cb : cbs) {
512             outResult->buffers.push_back(android::dupToAidl(cb.get()));
513             unallocate(std::move(cb));
514         }
515 
516         return ndk::ScopedAStatus::ok();
517     }
518 
isSupported__anon4bbb6fa40111::GoldfishAllocator519     ndk::ScopedAStatus isSupported(const BufferDescriptorInfo& descriptor,
520                                    bool* outResult) override {
521         *outResult = isSupportedImpl(descriptor);
522         return ndk::ScopedAStatus::ok();
523     }
524 
getIMapperLibrarySuffix__anon4bbb6fa40111::GoldfishAllocator525     ndk::ScopedAStatus getIMapperLibrarySuffix(std::string* outResult) override {
526         *outResult = "ranchu";
527         return ndk::ScopedAStatus::ok();
528     }
529 
allocate__anon4bbb6fa40111::GoldfishAllocator530     ndk::ScopedAStatus allocate(const std::vector<uint8_t>& encodedDescriptor,
531                                 const int32_t count,
532                                 AllocationResult* const outResult) override {
533         (void)encodedDescriptor;
534         (void)count;
535         (void)outResult;
536         return toBinderStatus(FAILURE(AllocationError::UNSUPPORTED));
537     }
538 
539 private:
540     struct AllocationRequest {
541         std::string_view name;
542         PlaneLayout plane[3];
543         PlaneLayoutComponent planeComponent[4];
544         size_t imageSizeInBytes = 0;
545         size_t reservedRegionSize = 0;
546         uint64_t usage = 0;
547         uint32_t width = 0;
548         uint32_t height = 0;
549         uint32_t stride0 = 0;
550         uint32_t drmFormat = DRM_FORMAT_INVALID;
551         PixelFormat format = PixelFormat::UNSPECIFIED;
552         int glFormat = -1;
553         int glType = -1;
554         int rcAllocFormat = -1;
555         EmulatorFrameworkFormat emuFwkFormat = EmulatorFrameworkFormat::GL_COMPATIBLE;
556         uint8_t planeSize = 0;
557     };
558 
559     std::unique_ptr<cb_handle_t>
allocateImpl__anon4bbb6fa40111::GoldfishAllocator560     allocateImpl(const AllocationRequest& req,
561                  ExtendedRCEncoderContext& rcEnc,
562                  const uint64_t bufferID,
563                  const bool hasSharedSlots) const {
564         android::base::unique_fd cpuAlocatorFd;
565         GoldfishAddressSpaceBlock bufferBits;
566         const size_t imageSizeInBytesAligned = align(req.imageSizeInBytes, 16);
567         const size_t totalAllocationSize =
568             imageSizeInBytesAligned + sizeof(CbExternalMetadata) + req.reservedRegionSize;
569 
570         {
571             GoldfishAddressSpaceHostMemoryAllocator hostMemoryAllocator(hasSharedSlots);
572             LOG_ALWAYS_FATAL_IF(!hostMemoryAllocator.is_opened());
573 
574             if (hostMemoryAllocator.hostMalloc(&bufferBits, totalAllocationSize)) {
575                 return FAILURE(nullptr);
576             }
577 
578             cpuAlocatorFd.reset(hostMemoryAllocator.release());
579 
580             CbExternalMetadata& metadata =
581                 *reinterpret_cast<CbExternalMetadata*>(
582                     static_cast<char*>(bufferBits.guestPtr()) + imageSizeInBytesAligned);
583 
584             memset(&metadata, 0, sizeof(metadata));
585             metadata.magic = CbExternalMetadata::kMagicValue;
586             metadata.bufferID = bufferID;
587             metadata.nameSize = std::min(req.name.size(), sizeof(CbExternalMetadata::name));
588             memcpy(metadata.name, req.name.data(), metadata.nameSize);
589 
590             metadata.planeLayoutSize = req.planeSize;
591             if (req.planeSize) {
592                 static_assert(sizeof(metadata.planeLayout) == sizeof(req.plane));
593                 memcpy(metadata.planeLayout, req.plane, sizeof(req.plane));
594 
595                 static_assert(sizeof(metadata.planeLayoutComponent) ==
596                               sizeof(req.planeComponent));
597                 memcpy(metadata.planeLayoutComponent, req.planeComponent,
598                        sizeof(req.planeComponent));
599             }
600 
601             metadata.reservedRegionSize = req.reservedRegionSize;
602             metadata.width = req.width;
603             metadata.height = req.height;
604             metadata.glFormat = req.glFormat;
605             metadata.glType = req.glType;
606         }
607 
608         uint32_t hostHandle = 0;
609         android::base::unique_fd hostHandleRefCountFd;
610         if (needGpuBuffer(req.usage)) {
611             hostHandleRefCountFd.reset(qemu_pipe_open("refcount"));
612             if (!hostHandleRefCountFd.ok()) {
613                 return FAILURE(nullptr);
614             }
615 
616             hostHandle = rcEnc.rcCreateColorBufferDMA(
617                 &rcEnc, req.width, req.height,
618                 req.rcAllocFormat, static_cast<int>(req.emuFwkFormat));
619             if (!hostHandle) {
620                 return FAILURE(nullptr);
621             }
622 
623             if (qemu_pipe_write(hostHandleRefCountFd.get(),
624                                 &hostHandle,
625                                 sizeof(hostHandle)) != sizeof(hostHandle)) {
626                 rcEnc.rcCloseColorBuffer(&rcEnc, hostHandle);
627                 return FAILURE(nullptr);
628             }
629         }
630 
631         if (mDebugLevel >= DebugLevel::ALLOC) {
632             char hostHandleValueStr[128];
633             if (hostHandle) {
634                 snprintf(hostHandleValueStr, sizeof(hostHandleValueStr),
635                          "0x%X glFormat=0x%X glType=0x%X "
636                          "rcAllocFormat=0x%X emuFwkFormat=%d",
637                          hostHandle, req.glFormat, req.glType, req.rcAllocFormat,
638                          static_cast<int>(req.emuFwkFormat));
639             } else {
640                 strcpy(hostHandleValueStr, "null");
641             }
642 
643             char bufferValueStr[96];
644             if (req.imageSizeInBytes) {
645                 snprintf(bufferValueStr, sizeof(bufferValueStr),
646                          "{ ptr=%p mappedSize=%zu offset=0x%" PRIX64 " } imageSizeInBytes=%zu",
647                          bufferBits.guestPtr(), size_t(bufferBits.size()),
648                          bufferBits.offset(), size_t(req.imageSizeInBytes));
649             } else {
650                 strcpy(bufferValueStr, "null");
651             }
652 
653             ALOGD("%s:%d name='%.*s' id=%" PRIu64 " width=%u height=%u format=0x%X "
654                   "usage=0x%" PRIX64 " hostHandle=%s buffer=%s reservedSize=%zu",
655                   __func__, __LINE__, int(req.name.size()), req.name.data(), bufferID,
656                   req.width, req.height, static_cast<uint32_t>(req.format),
657                   req.usage, hostHandleValueStr, bufferValueStr,
658                   req.reservedRegionSize);
659         }
660 
661         auto cb = std::make_unique<cb_handle_t>(
662             cpuAlocatorFd.release(), hostHandleRefCountFd.release(), hostHandle,
663             req.usage, static_cast<uint32_t>(req.format), req.drmFormat,
664             req.stride0, req.imageSizeInBytes, bufferBits.guestPtr(),
665             bufferBits.size(), bufferBits.offset(),
666             imageSizeInBytesAligned);
667 
668         bufferBits.release();  // now cb owns it
669         return cb;
670     }
671 
unallocate__anon4bbb6fa40111::GoldfishAllocator672     static void unallocate(const std::unique_ptr<cb_handle_t> cb) {
673         if (cb->hostHandleRefcountFd >= 0) {
674             ::close(cb->hostHandleRefcountFd);
675         }
676 
677         if (cb->bufferFd >= 0) {
678             if (cb->mmapedSize > 0) {
679                 GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
680             }
681 
682             GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
683         }
684     }
685 
validateUsage__anon4bbb6fa40111::GoldfishAllocator686     static bool validateUsage(const BufferUsage usage) {
687         static constexpr uint64_t kReservedUsage =
688             (1U << 10) | (1U << 13) | (1U << 19) | (1U << 21);
689 
690         return 0 == (toUsage64(usage) & kReservedUsage);
691     }
692 
isSupportedImpl__anon4bbb6fa40111::GoldfishAllocator693     static bool isSupportedImpl(const BufferDescriptorInfo& desc) {
694         if (desc.width <= 0) { return false; }
695         if (desc.height <= 0) { return false; }
696         if (desc.layerCount != 1) { return false; }
697         if (desc.reservedSize < 0) { return false; }
698         if (!desc.additionalOptions.empty()) { return false; }
699 
700         switch (desc.format) {
701         case PixelFormat::RGBA_8888:
702         case PixelFormat::RGBX_8888:
703         case PixelFormat::BGRA_8888:
704         case PixelFormat::RGB_565:
705         case PixelFormat::RGBA_FP16:
706         case PixelFormat::RGBA_1010102:
707         case PixelFormat::YV12:
708         case PixelFormat::YCBCR_420_888:
709         case PixelFormat::YCBCR_P010:
710             return validateUsage(desc.usage);
711 
712         case PixelFormat::RGB_888:
713         case PixelFormat::YCRCB_420_SP:
714         case PixelFormat::RAW16:
715         case PixelFormat::Y16:
716         case PixelFormat::BLOB:
717             return validateUsage(desc.usage) &&
718                    !needGpuBuffer(toUsage64(desc.usage));
719 
720         case PixelFormat::IMPLEMENTATION_DEFINED:  // we don't support it
721         default:
722             return false;
723         }
724     }
725 
726     const std::unique_ptr<HostConnection> mHostConn;
727     uint64_t mBufferIdGenerator = 0;
728     const DebugLevel mDebugLevel;
729 };
730 }  // namespace
731 
main(int,char **)732 int main(int /*argc*/, char** /*argv*/) {
733     struct sched_param param = {0};
734     param.sched_priority = 2;
735     if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
736         ALOGW("Failed to set priority: %s", strerror(errno));
737     }
738 
739     auto allocator = ndk::SharedRefBase::make<GoldfishAllocator>();
740 
741     {
742         const std::string instance = std::string(GoldfishAllocator::descriptor) + "/default";
743         if (AServiceManager_addService(allocator->asBinder().get(),
744                                        instance.c_str()) != STATUS_OK) {
745             ALOGE("Failed to register: '%s'", instance.c_str());
746             return EXIT_FAILURE;
747         }
748     }
749 
750     ABinderProcess_setThreadPoolMaxThreadCount(4);
751     ABinderProcess_startThreadPool();
752     ABinderProcess_joinThreadPool();
753     return EXIT_FAILURE;    // joinThreadPool is not expected to return
754 }
755