1 /*
2  * Copyright (C) 2017 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 #define LOG_TAG "directchannel"
17 #include "directchannel.h"
18 
19 #include <cutils/ashmem.h>
20 #include <hardware/sensors.h>
21 #include <utils/Log.h>
22 
23 #include <sys/mman.h>
24 
25 namespace android {
26 
isValid()27 bool DirectChannelBase::isValid() {
28     return mBuffer != nullptr;
29 }
30 
getError()31 int DirectChannelBase::getError() {
32     return mError;
33 }
34 
write(const sensors_event_t * ev)35 void DirectChannelBase::write(const sensors_event_t * ev) {
36     if (isValid()) {
37         mBuffer->write(ev, 1);
38     }
39 }
40 
AshmemDirectChannel(const struct sensors_direct_mem_t * mem)41 AshmemDirectChannel::AshmemDirectChannel(const struct sensors_direct_mem_t *mem) : mAshmemFd(0) {
42     mAshmemFd = mem->handle->data[0];
43 
44     if (!::ashmem_valid(mAshmemFd)) {
45         mError = BAD_VALUE;
46         return;
47     }
48 
49     if ((size_t)::ashmem_get_size_region(mAshmemFd) != mem->size) {
50         mError = BAD_VALUE;
51         return;
52     }
53 
54     mSize = mem->size;
55 
56     mBase = ::mmap(NULL, mem->size, PROT_WRITE, MAP_SHARED, mAshmemFd, 0);
57     if (mBase == nullptr) {
58         mError = NO_MEMORY;
59         return;
60     }
61 
62     mBuffer = std::unique_ptr<LockfreeBuffer>(new LockfreeBuffer(mBase, mSize));
63     if (!mBuffer) {
64         mError = NO_MEMORY;
65     }
66 }
67 
~AshmemDirectChannel()68 AshmemDirectChannel::~AshmemDirectChannel() {
69     if (mBase) {
70         mBuffer = nullptr;
71         ::munmap(mBase, mSize);
72         mBase = nullptr;
73     }
74     ::close(mAshmemFd);
75 }
76 
77 ANDROID_SINGLETON_STATIC_INSTANCE(GrallocHalWrapper);
78 
GrallocHalWrapper()79 GrallocHalWrapper::GrallocHalWrapper()
80         : mError(NO_INIT), mVersion(-1),
81           mGrallocModule(nullptr), mAllocDevice(nullptr), mGralloc1Device(nullptr),
82           mPfnRetain(nullptr), mPfnRelease(nullptr), mPfnLock(nullptr), mPfnUnlock(nullptr) {
83     const hw_module_t *module;
84     status_t err = ::hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
85     ALOGE_IF(err, "couldn't load %s module (%s)", GRALLOC_HARDWARE_MODULE_ID, strerror(-err));
86 
87     if (module == nullptr) {
88         mError = (err < 0) ? err : NO_INIT;
89     }
90 
91     switch ((module->module_api_version >> 8) & 0xFF) {
92         case 0:
93             err = ::gralloc_open(module, &mAllocDevice);
94             if (err != NO_ERROR) {
95                 ALOGE("cannot open alloc device (%s)", strerror(-err));
96                 break;
97             }
98 
99             if (mAllocDevice == nullptr) {
100                 ALOGE("gralloc_open returns no error, but result is nullptr");
101                 err = INVALID_OPERATION;
102                 break;
103             }
104 
105             // successfully initialized gralloc
106             mGrallocModule = (gralloc_module_t *)module;
107             mVersion = 0;
108             break;
109         case 1:
110             err = ::gralloc1_open(module, &mGralloc1Device);
111             if (err != NO_ERROR) {
112                 ALOGE("cannot open gralloc1 device (%s)", strerror(-err));
113                 break;
114             }
115 
116             if (mGralloc1Device == nullptr || mGralloc1Device->getFunction == nullptr) {
117                 ALOGE("gralloc1_open returns no error, but result is nullptr");
118                 err = INVALID_OPERATION;
119                 break;
120             }
121 
122             mPfnRetain = (GRALLOC1_PFN_RETAIN)(mGralloc1Device->getFunction(mGralloc1Device,
123                                                       GRALLOC1_FUNCTION_RETAIN));
124             mPfnRelease = (GRALLOC1_PFN_RELEASE)(mGralloc1Device->getFunction(mGralloc1Device,
125                                                        GRALLOC1_FUNCTION_RELEASE));
126             mPfnLock = (GRALLOC1_PFN_LOCK)(mGralloc1Device->getFunction(mGralloc1Device,
127                                                     GRALLOC1_FUNCTION_LOCK));
128             mPfnUnlock = (GRALLOC1_PFN_UNLOCK)(mGralloc1Device->getFunction(mGralloc1Device,
129                                                       GRALLOC1_FUNCTION_UNLOCK));
130             if (mPfnRetain == nullptr || mPfnRelease == nullptr
131                     || mPfnLock == nullptr || mPfnUnlock == nullptr) {
132                 ALOGE("Function pointer for retain, release, lock and unlock are %p, %p, %p, %p",
133                       mPfnRetain, mPfnRelease, mPfnLock, mPfnUnlock);
134                 err = BAD_VALUE;
135                 break;
136             }
137 
138             // successfully initialized gralloc1
139             mGrallocModule = (gralloc_module_t *)module;
140             mVersion = 1;
141             break;
142         default:
143             ALOGE("Unknown version, not supported");
144             break;
145     }
146     mError = err;
147 }
148 
~GrallocHalWrapper()149 GrallocHalWrapper::~GrallocHalWrapper() {
150     if (mAllocDevice != nullptr) {
151         ::gralloc_close(mAllocDevice);
152     }
153 }
154 
registerBuffer(const native_handle_t * handle)155 int GrallocHalWrapper::registerBuffer(const native_handle_t *handle) {
156     switch (mVersion) {
157         case 0:
158             return mGrallocModule->registerBuffer(mGrallocModule, handle);
159         case 1:
160             return mapGralloc1Error(mPfnRetain(mGralloc1Device, handle));
161         default:
162             return NO_INIT;
163     }
164 }
165 
unregisterBuffer(const native_handle_t * handle)166 int GrallocHalWrapper::unregisterBuffer(const native_handle_t *handle) {
167     switch (mVersion) {
168         case 0:
169             return mGrallocModule->unregisterBuffer(mGrallocModule, handle);
170         case 1:
171             return mapGralloc1Error(mPfnRelease(mGralloc1Device, handle));
172         default:
173             return NO_INIT;
174     }
175 }
176 
lock(const native_handle_t * handle,int usage,int l,int t,int w,int h,void ** vaddr)177 int GrallocHalWrapper::lock(const native_handle_t *handle,
178                            int usage, int l, int t, int w, int h, void **vaddr) {
179     switch (mVersion) {
180         case 0:
181             return mGrallocModule->lock(mGrallocModule, handle, usage, l, t, w, h, vaddr);
182         case 1: {
183             const gralloc1_rect_t rect = {
184                 .left = l,
185                 .top = t,
186                 .width = w,
187                 .height = h
188             };
189             return mapGralloc1Error(mPfnLock(mGralloc1Device, handle,
190                                              GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
191                                              GRALLOC1_CONSUMER_USAGE_NONE,
192                                              &rect, vaddr, -1));
193         }
194         default:
195             return NO_INIT;
196     }
197 }
198 
unlock(const native_handle_t * handle)199 int GrallocHalWrapper::unlock(const native_handle_t *handle) {
200     switch (mVersion) {
201         case 0:
202             return mGrallocModule->unlock(mGrallocModule, handle);
203         case 1: {
204             int32_t dummy;
205             return mapGralloc1Error(mPfnUnlock(mGralloc1Device, handle, &dummy));
206         }
207         default:
208             return NO_INIT;
209     }
210 }
211 
mapGralloc1Error(int grallocError)212 int GrallocHalWrapper::mapGralloc1Error(int grallocError) {
213     switch (grallocError) {
214         case GRALLOC1_ERROR_NONE:
215             return NO_ERROR;
216         case GRALLOC1_ERROR_BAD_DESCRIPTOR:
217         case GRALLOC1_ERROR_BAD_HANDLE:
218         case GRALLOC1_ERROR_BAD_VALUE:
219             return BAD_VALUE;
220         case GRALLOC1_ERROR_NOT_SHARED:
221         case GRALLOC1_ERROR_NO_RESOURCES:
222             return NO_MEMORY;
223         case GRALLOC1_ERROR_UNDEFINED:
224         case GRALLOC1_ERROR_UNSUPPORTED:
225             return INVALID_OPERATION;
226         default:
227             return UNKNOWN_ERROR;
228     }
229 }
230 
GrallocDirectChannel(const struct sensors_direct_mem_t * mem)231 GrallocDirectChannel::GrallocDirectChannel(const struct sensors_direct_mem_t *mem)
232         : mNativeHandle(nullptr) {
233     if (mem->handle == nullptr) {
234         ALOGE("mem->handle == nullptr");
235         mError = BAD_VALUE;
236         return;
237     }
238 
239     mNativeHandle = ::native_handle_clone(mem->handle);
240     if (mNativeHandle == nullptr) {
241         ALOGE("clone mem->handle failed...");
242         mError = NO_MEMORY;
243         return;
244     }
245 
246     mError = GrallocHalWrapper::getInstance().registerBuffer(mNativeHandle);
247     if (mError != NO_ERROR) {
248         ALOGE("registerBuffer failed");
249         return;
250     }
251 
252     mError = GrallocHalWrapper::getInstance().lock(mNativeHandle,
253             GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, mem->size, 1, &mBase);
254     if (mError != NO_ERROR) {
255         ALOGE("lock buffer failed");
256         return;
257     }
258 
259     if (mBase == nullptr) {
260         ALOGE("lock buffer => nullptr");
261         mError = NO_MEMORY;
262         return;
263     }
264 
265     mSize = mem->size;
266     mBuffer = std::make_unique<LockfreeBuffer>(mBase, mSize);
267     if (!mBuffer) {
268         mError = NO_MEMORY;
269         return;
270     }
271 
272     mError = NO_ERROR;
273 }
274 
~GrallocDirectChannel()275 GrallocDirectChannel::~GrallocDirectChannel() {
276     if (mNativeHandle != nullptr) {
277         if (mBase) {
278             mBuffer = nullptr;
279             GrallocHalWrapper::getInstance().unlock(mNativeHandle);
280             mBase = nullptr;
281         }
282         GrallocHalWrapper::getInstance().unregisterBuffer(mNativeHandle);
283         ::native_handle_close(mNativeHandle);
284         ::native_handle_delete(mNativeHandle);
285         mNativeHandle = nullptr;
286     }
287 }
288 
289 } // namespace android
290