1/*
2 * Copyright 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_TAG "Gralloc2"
18
19#include <hwbinder/IPCThreadState.h>
20#include <ui/Gralloc2.h>
21
22#include <log/log.h>
23#pragma clang diagnostic push
24#pragma clang diagnostic ignored "-Wzero-length-array"
25#include <sync/sync.h>
26#pragma clang diagnostic pop
27
28namespace android {
29
30namespace Gralloc2 {
31
32static constexpr Error kTransactionError = Error::NO_RESOURCES;
33
34Mapper::Mapper()
35{
36    mMapper = IMapper::getService();
37    if (mMapper == nullptr || mMapper->isRemote()) {
38        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
39    }
40}
41
42Error Mapper::createDescriptor(
43        const IMapper::BufferDescriptorInfo& descriptorInfo,
44        BufferDescriptor* outDescriptor) const
45{
46    Error error;
47    auto ret = mMapper->createDescriptor(descriptorInfo,
48            [&](const auto& tmpError, const auto& tmpDescriptor)
49            {
50                error = tmpError;
51                if (error != Error::NONE) {
52                    return;
53                }
54
55                *outDescriptor = tmpDescriptor;
56            });
57
58    return (ret.isOk()) ? error : kTransactionError;
59}
60
61Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
62        buffer_handle_t* outBufferHandle) const
63{
64    Error error;
65    auto ret = mMapper->importBuffer(rawHandle,
66            [&](const auto& tmpError, const auto& tmpBuffer)
67            {
68                error = tmpError;
69                if (error != Error::NONE) {
70                    return;
71                }
72
73                *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
74            });
75
76    return (ret.isOk()) ? error : kTransactionError;
77}
78
79void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
80{
81    auto buffer = const_cast<native_handle_t*>(bufferHandle);
82    auto ret = mMapper->freeBuffer(buffer);
83
84    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
85    ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
86            buffer, error);
87}
88
89Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
90        const IMapper::Rect& accessRegion,
91        int acquireFence, void** outData) const
92{
93    auto buffer = const_cast<native_handle_t*>(bufferHandle);
94
95    // put acquireFence in a hidl_handle
96    hardware::hidl_handle acquireFenceHandle;
97    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
98    if (acquireFence >= 0) {
99        auto h = native_handle_init(acquireFenceStorage, 1, 0);
100        h->data[0] = acquireFence;
101        acquireFenceHandle = h;
102    }
103
104    Error error;
105    auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
106            [&](const auto& tmpError, const auto& tmpData)
107            {
108                error = tmpError;
109                if (error != Error::NONE) {
110                    return;
111                }
112
113                *outData = tmpData;
114            });
115
116    // we own acquireFence even on errors
117    if (acquireFence >= 0) {
118        close(acquireFence);
119    }
120
121    return (ret.isOk()) ? error : kTransactionError;
122}
123
124Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
125        const IMapper::Rect& accessRegion,
126        int acquireFence, YCbCrLayout* outLayout) const
127{
128    auto buffer = const_cast<native_handle_t*>(bufferHandle);
129
130    // put acquireFence in a hidl_handle
131    hardware::hidl_handle acquireFenceHandle;
132    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
133    if (acquireFence >= 0) {
134        auto h = native_handle_init(acquireFenceStorage, 1, 0);
135        h->data[0] = acquireFence;
136        acquireFenceHandle = h;
137    }
138
139    Error error;
140    auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
141            acquireFenceHandle,
142            [&](const auto& tmpError, const auto& tmpLayout)
143            {
144                error = tmpError;
145                if (error != Error::NONE) {
146                    return;
147                }
148
149                *outLayout = tmpLayout;
150            });
151
152    // we own acquireFence even on errors
153    if (acquireFence >= 0) {
154        close(acquireFence);
155    }
156
157    return (ret.isOk()) ? error : kTransactionError;
158}
159
160int Mapper::unlock(buffer_handle_t bufferHandle) const
161{
162    auto buffer = const_cast<native_handle_t*>(bufferHandle);
163
164    int releaseFence = -1;
165    Error error;
166    auto ret = mMapper->unlock(buffer,
167            [&](const auto& tmpError, const auto& tmpReleaseFence)
168            {
169                error = tmpError;
170                if (error != Error::NONE) {
171                    return;
172                }
173
174                auto fenceHandle = tmpReleaseFence.getNativeHandle();
175                if (fenceHandle && fenceHandle->numFds == 1) {
176                    int fd = dup(fenceHandle->data[0]);
177                    if (fd >= 0) {
178                        releaseFence = fd;
179                    } else {
180                        ALOGD("failed to dup unlock release fence");
181                        sync_wait(fenceHandle->data[0], -1);
182                    }
183                }
184            });
185
186    if (!ret.isOk()) {
187        error = kTransactionError;
188    }
189
190    if (error != Error::NONE) {
191        ALOGE("unlock(%p) failed with %d", buffer, error);
192    }
193
194    return releaseFence;
195}
196
197Allocator::Allocator(const Mapper& mapper)
198    : mMapper(mapper)
199{
200    mAllocator = IAllocator::getService();
201    if (mAllocator == nullptr) {
202        LOG_ALWAYS_FATAL("gralloc-alloc is missing");
203    }
204}
205
206std::string Allocator::dumpDebugInfo() const
207{
208    std::string debugInfo;
209
210    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
211        debugInfo = tmpDebugInfo.c_str();
212    });
213
214    return debugInfo;
215}
216
217Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
218        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
219{
220    Error error;
221    auto ret = mAllocator->allocate(descriptor, count,
222            [&](const auto& tmpError, const auto& tmpStride,
223                const auto& tmpBuffers) {
224                error = tmpError;
225                if (tmpError != Error::NONE) {
226                    return;
227                }
228
229                // import buffers
230                for (uint32_t i = 0; i < count; i++) {
231                    error = mMapper.importBuffer(tmpBuffers[i],
232                            &outBufferHandles[i]);
233                    if (error != Error::NONE) {
234                        for (uint32_t j = 0; j < i; j++) {
235                            mMapper.freeBuffer(outBufferHandles[j]);
236                            outBufferHandles[j] = nullptr;
237                        }
238                        return;
239                    }
240                }
241
242                *outStride = tmpStride;
243            });
244
245    // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
246    hardware::IPCThreadState::self()->flushCommands();
247
248    return (ret.isOk()) ? error : kTransactionError;
249}
250
251} // namespace Gralloc2
252
253} // namespace android
254