1 /*
2  * Copyright 2016 The Android Open Source Project
3  * * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define LOG_TAG "GrallocMapperPassthrough"
17 
18 #include "GrallocMapper.h"
19 
20 #include "Gralloc0Mapper.h"
21 #include "Gralloc1Mapper.h"
22 #include "GrallocBufferDescriptor.h"
23 
24 #include <inttypes.h>
25 
26 #include <log/log.h>
27 #include <sync/sync.h>
28 
29 namespace android {
30 namespace hardware {
31 namespace graphics {
32 namespace mapper {
33 namespace V2_0 {
34 namespace implementation {
35 
36 using android::hardware::graphics::common::V1_0::BufferUsage;
37 using android::hardware::graphics::common::V1_0::PixelFormat;
38 
39 namespace {
40 
41 class RegisteredHandlePool {
42    public:
add(buffer_handle_t bufferHandle)43     bool add(buffer_handle_t bufferHandle) {
44         std::lock_guard<std::mutex> lock(mMutex);
45         return mHandles.insert(bufferHandle).second;
46     }
47 
pop(void * buffer)48     native_handle_t* pop(void* buffer) {
49         auto bufferHandle = static_cast<native_handle_t*>(buffer);
50 
51         std::lock_guard<std::mutex> lock(mMutex);
52         return mHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
53     }
54 
get(const void * buffer)55     buffer_handle_t get(const void* buffer) {
56         auto bufferHandle = static_cast<buffer_handle_t>(buffer);
57 
58         std::lock_guard<std::mutex> lock(mMutex);
59         return mHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
60     }
61 
62    private:
63     std::mutex mMutex;
64     std::unordered_set<buffer_handle_t> mHandles;
65 };
66 
67 // GraphicBufferMapper is expected to be valid (and leaked) during process
68 // termination.  We need to make sure IMapper, and in turn, gRegisteredHandles
69 // are valid as well.  Create the registered handle pool on the heap, and let
70 // it leak for simplicity.
71 //
72 // However, there is no way to make sure gralloc0/gralloc1 are valid.  Any use
73 // of static/global object in gralloc0/gralloc1 that may have been destructed
74 // is potentially broken.
75 RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
76 
77 }  // anonymous namespace
78 
validateDescriptorInfo(const BufferDescriptorInfo & descriptorInfo) const79 bool GrallocMapper::validateDescriptorInfo(
80     const BufferDescriptorInfo& descriptorInfo) const {
81     const uint64_t validUsageBits =
82         BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
83         BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
84         BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
85         BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
86         BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
87         BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
88         BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
89         BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
90         (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
91                                      : static_cast<BufferUsage>(0));
92 
93     if (!descriptorInfo.width || !descriptorInfo.height ||
94         !descriptorInfo.layerCount) {
95         return false;
96     }
97 
98     if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
99         return false;
100     }
101 
102     if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
103         return false;
104     }
105 
106     if (descriptorInfo.usage & ~validUsageBits) {
107         // could not fail as gralloc may use the reserved bits...
108         ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
109               descriptorInfo.usage & ~validUsageBits);
110     }
111 
112     return true;
113 }
114 
createDescriptor(const BufferDescriptorInfo & descriptorInfo,createDescriptor_cb hidl_cb)115 Return<void> GrallocMapper::createDescriptor(
116     const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
117     if (validateDescriptorInfo(descriptorInfo)) {
118         hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
119     } else {
120         hidl_cb(Error::BAD_VALUE, BufferDescriptor());
121     }
122 
123     return Void();
124 }
125 
importBuffer(const hidl_handle & rawHandle,importBuffer_cb hidl_cb)126 Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
127                                          importBuffer_cb hidl_cb) {
128     // because of passthrough HALs, we must not generate an error when
129     // rawHandle has been imported
130 
131     if (!rawHandle.getNativeHandle()) {
132         hidl_cb(Error::BAD_BUFFER, nullptr);
133         return Void();
134     }
135 
136     native_handle_t* bufferHandle =
137         native_handle_clone(rawHandle.getNativeHandle());
138     if (!bufferHandle) {
139         hidl_cb(Error::NO_RESOURCES, nullptr);
140         return Void();
141     }
142 
143     Error error = registerBuffer(bufferHandle);
144     if (error != Error::NONE) {
145         native_handle_close(bufferHandle);
146         native_handle_delete(bufferHandle);
147 
148         hidl_cb(error, nullptr);
149         return Void();
150     }
151 
152     // The newly cloned handle is already registered?  This can only happen
153     // when a handle previously registered was native_handle_delete'd instead
154     // of freeBuffer'd.
155     if (!gRegisteredHandles->add(bufferHandle)) {
156         ALOGE("handle %p has already been imported; potential fd leaking",
157               bufferHandle);
158         unregisterBuffer(bufferHandle);
159         if (!mCapabilities.unregisterImplyDelete) {
160             native_handle_close(bufferHandle);
161             native_handle_delete(bufferHandle);
162         }
163 
164         hidl_cb(Error::NO_RESOURCES, nullptr);
165         return Void();
166     }
167 
168     hidl_cb(Error::NONE, bufferHandle);
169     return Void();
170 }
171 
freeBuffer(void * buffer)172 Return<Error> GrallocMapper::freeBuffer(void* buffer) {
173     native_handle_t* bufferHandle = gRegisteredHandles->pop(buffer);
174     if (!bufferHandle) {
175         return Error::BAD_BUFFER;
176     }
177 
178     unregisterBuffer(bufferHandle);
179     if (!mCapabilities.unregisterImplyDelete) {
180         native_handle_close(bufferHandle);
181         native_handle_delete(bufferHandle);
182     }
183 
184     return Error::NONE;
185 }
186 
waitFenceFd(int fenceFd,const char * logname)187 void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
188     if (fenceFd < 0) {
189         return;
190     }
191 
192     const int warningTimeout = 3500;
193     const int error = sync_wait(fenceFd, warningTimeout);
194     if (error < 0 && errno == ETIME) {
195         ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
196               warningTimeout);
197         sync_wait(fenceFd, -1);
198     }
199 }
200 
getFenceFd(const hidl_handle & fenceHandle,int * outFenceFd)201 bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
202                                int* outFenceFd) {
203     auto handle = fenceHandle.getNativeHandle();
204     if (handle && handle->numFds > 1) {
205         ALOGE("invalid fence handle with %d fds", handle->numFds);
206         return false;
207     }
208 
209     *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
210     return true;
211 }
212 
getFenceHandle(int fenceFd,char * handleStorage)213 hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
214     native_handle_t* handle = nullptr;
215     if (fenceFd >= 0) {
216         handle = native_handle_init(handleStorage, 1, 0);
217         handle->data[0] = fenceFd;
218     }
219 
220     return hidl_handle(handle);
221 }
222 
lock(void * buffer,uint64_t cpuUsage,const IMapper::Rect & accessRegion,const hidl_handle & acquireFence,lock_cb hidl_cb)223 Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
224                                  const IMapper::Rect& accessRegion,
225                                  const hidl_handle& acquireFence,
226                                  lock_cb hidl_cb) {
227     buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
228     if (!bufferHandle) {
229         hidl_cb(Error::BAD_BUFFER, nullptr);
230         return Void();
231     }
232 
233     int fenceFd;
234     if (!getFenceFd(acquireFence, &fenceFd)) {
235         hidl_cb(Error::BAD_VALUE, nullptr);
236         return Void();
237     }
238 
239     void* data = nullptr;
240     Error error =
241         lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
242 
243     hidl_cb(error, data);
244     return Void();
245 }
246 
lockYCbCr(void * buffer,uint64_t cpuUsage,const IMapper::Rect & accessRegion,const hidl_handle & acquireFence,lockYCbCr_cb hidl_cb)247 Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
248                                       const IMapper::Rect& accessRegion,
249                                       const hidl_handle& acquireFence,
250                                       lockYCbCr_cb hidl_cb) {
251     YCbCrLayout layout = {};
252 
253     buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
254     if (!bufferHandle) {
255         hidl_cb(Error::BAD_BUFFER, layout);
256         return Void();
257     }
258 
259     int fenceFd;
260     if (!getFenceFd(acquireFence, &fenceFd)) {
261         hidl_cb(Error::BAD_VALUE, layout);
262         return Void();
263     }
264 
265     Error error =
266         lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
267 
268     hidl_cb(error, layout);
269     return Void();
270 }
271 
unlock(void * buffer,unlock_cb hidl_cb)272 Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
273     buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
274     if (!bufferHandle) {
275         hidl_cb(Error::BAD_BUFFER, nullptr);
276         return Void();
277     }
278 
279     int fenceFd;
280     Error error = unlockBuffer(bufferHandle, &fenceFd);
281     if (error == Error::NONE) {
282         NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
283 
284         hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
285 
286         if (fenceFd >= 0) {
287             close(fenceFd);
288         }
289     } else {
290         hidl_cb(error, nullptr);
291     }
292 
293     return Void();
294 }
295 
HIDL_FETCH_IMapper(const char *)296 IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
297     const hw_module_t* module = nullptr;
298     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
299     if (err) {
300         ALOGE("failed to get gralloc module");
301         return nullptr;
302     }
303 
304     uint8_t major = (module->module_api_version >> 8) & 0xff;
305     switch (major) {
306         case 1:
307             return new Gralloc1Mapper(module);
308         case 0:
309             return new Gralloc0Mapper(module);
310         default:
311             ALOGE("unknown gralloc module major version %d", major);
312             return nullptr;
313     }
314 }
315 
316 } // namespace implementation
317 } // namespace V2_0
318 } // namespace mapper
319 } // namespace graphics
320 } // namespace hardware
321 } // namespace android
322