1 /*
2  * Copyright (C) 2022 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 #ifndef ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H
18 #define ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H
19 
20 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
21 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
22 #include <ui/GraphicBuffer.h>
23 #include <ui/GraphicBufferAllocator.h>
24 #include <ui/GraphicBufferMapper.h>
25 
26 #include <aidlcommonsupport/NativeHandle.h>
27 #include <android-base/macros.h>
28 #include <log/log.h>
29 
30 #include <sys/mman.h>
31 #include <cinttypes>
32 
33 #include <cutils/ashmem.h>
34 
35 using ::aidl::android::hardware::graphics::common::BufferUsage;
36 using ::aidl::android::hardware::graphics::common::PixelFormat;
37 using ::aidl::android::hardware::sensors::BnSensors;
38 using ::aidl::android::hardware::sensors::Event;
39 using ::aidl::android::hardware::sensors::ISensors;
40 using ::aidl::android::hardware::sensors::SensorType;
41 
42 template <class SensorType, class Event>
43 class SensorsAidlTestSharedMemory {
44   public:
create(ISensors::SharedMemInfo::SharedMemType type,size_t size)45     static SensorsAidlTestSharedMemory* create(ISensors::SharedMemInfo::SharedMemType type,
46                                                size_t size) {
47         constexpr size_t kMaxSize =
48                 128 * 1024 * 1024;  // sensor test should not need more than 128M
49         if (size == 0 || size >= kMaxSize) {
50             return nullptr;
51         }
52 
53         auto m = new SensorsAidlTestSharedMemory<SensorType, Event>(type, size);
54         if (m->mSize != size || m->mBuffer == nullptr) {
55             delete m;
56             m = nullptr;
57         }
58         return m;
59     }
60 
getSharedMemInfo()61     ISensors::SharedMemInfo getSharedMemInfo() const {
62         if (mType == ISensors::SharedMemInfo::SharedMemType::GRALLOC) {
63             ISensors::SharedMemInfo mem = {
64                     .type = mType,
65                     .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT,
66                     .size = static_cast<int32_t>(mSize),
67                     .memoryHandle = android::dupToAidl(mBufferHandle)};
68             return mem;
69 
70         } else {
71             ISensors::SharedMemInfo mem = {
72                     .type = mType,
73                     .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT,
74                     .size = static_cast<int32_t>(mSize),
75                     .memoryHandle = android::dupToAidl(mNativeHandle)};
76             return mem;
77         }
78     }
getBuffer()79     char* getBuffer() const { return mBuffer; }
getSize()80     size_t getSize() const { return mSize; }
81     std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const {
82         constexpr size_t kEventSize =
83                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH);
84         constexpr size_t kOffsetSize =
85                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD);
86         constexpr size_t kOffsetToken =
87                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN);
88         constexpr size_t kOffsetType =
89                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE);
90         constexpr size_t kOffsetAtomicCounter = static_cast<size_t>(
91                 BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER);
92         constexpr size_t kOffsetTimestamp =
93                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP);
94         constexpr size_t kOffsetData =
95                 static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA);
96 
97         std::vector<Event> events;
98         std::vector<float> data(16);
99 
100         while (offset + kEventSize <= mSize) {
101             int64_t atomicCounter =
102                     *reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
103             if (atomicCounter <= lastCounter) {
104                 ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
105                       lastCounter);
106                 break;
107             }
108 
109             int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
110             if (size != kEventSize) {
111                 // unknown error, events parsed may be wrong, remove all
112                 events.clear();
113                 break;
114             }
115 
116             int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
117             int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
118             int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
119 
120             ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
121                   ", timestamp %" PRId64,
122                   offset, atomicCounter, token, type, timestamp);
123 
124             Event event = {
125                     .timestamp = timestamp,
126                     .sensorHandle = token,
127                     .sensorType = type,
128             };
129 
130             event.set<Event::Data>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
131             // event.u.data = android::hardware::hidl_array<float,
132             // 16>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
133 
134             events.push_back(event);
135 
136             lastCounter = atomicCounter;
137             offset += kEventSize;
138         }
139 
140         return events;
141     }
142 
~SensorsAidlTestSharedMemory()143     virtual ~SensorsAidlTestSharedMemory() {
144         switch (mType) {
145             case ISensors::SharedMemInfo::SharedMemType::ASHMEM: {
146                 if (mSize != 0) {
147                     ::munmap(mBuffer, mSize);
148                     mBuffer = nullptr;
149 
150                     ::native_handle_close(mNativeHandle);
151                     ::native_handle_delete(mNativeHandle);
152 
153                     mNativeHandle = nullptr;
154                     mSize = 0;
155                 }
156                 break;
157             }
158             case ISensors::SharedMemInfo::SharedMemType::GRALLOC: {
159                 if (mSize != 0) {
160                     android::status_t status =
161                             android::GraphicBufferAllocator::get().free(mBufferHandle);
162                     if (status != android::OK) {
163                         ALOGE("SensorsAidlTestSharedMemory Gralloc failed to free buffer. Status: "
164                               "%s",
165                               android::statusToString(status).c_str());
166                     }
167                     mBufferHandle = nullptr;
168                     mBuffer = nullptr;
169                     mSize = 0;
170                 }
171                 break;
172             }
173             default: {
174                 if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr ||
175                     mBufferHandle != nullptr) {
176                     ALOGE("SensorsAidlTestSharedMemory %p not properly destructed: "
177                           "type %d, native handle %p, size %zu, buffer %p, buffer handle %p",
178                           this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer,
179                           mBufferHandle);
180                 }
181                 break;
182             }
183         }
184     }
185 
186   private:
SensorsAidlTestSharedMemory(ISensors::SharedMemInfo::SharedMemType type,size_t size)187     SensorsAidlTestSharedMemory(ISensors::SharedMemInfo::SharedMemType type, size_t size)
188         : mType(type), mSize(0), mBuffer(nullptr) {
189         native_handle_t* handle = nullptr;
190         char* buffer = nullptr;
191         switch (type) {
192             case ISensors::SharedMemInfo::SharedMemType::ASHMEM: {
193                 int fd;
194                 handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
195                 if (handle != nullptr) {
196                     handle->data[0] = fd =
197                             ::ashmem_create_region("SensorsAidlTestSharedMemory", size);
198                     if (handle->data[0] > 0) {
199                         // memory is pinned by default
200                         buffer = static_cast<char*>(
201                                 ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
202                         if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
203                             break;
204                         }
205                         ::native_handle_close(handle);
206                     }
207                     ::native_handle_delete(handle);
208                     handle = nullptr;
209                 }
210                 break;
211             }
212             case ISensors::SharedMemInfo::SharedMemType::GRALLOC: {
213                 static constexpr uint64_t kBufferUsage =
214                         static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA) |
215                         static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
216                         static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY);
217 
218                 uint32_t stride = 0;
219                 buffer_handle_t bufferHandle;
220                 android::status_t status = android::GraphicBufferAllocator::get().allocate(
221                         size, 1, static_cast<int>(PixelFormat::BLOB), 1, kBufferUsage,
222                         &bufferHandle, &stride, "SensorVts");
223                 if (status != android::OK) {
224                     ALOGE("SensorsAidlTestSharedMemory failed to allocate memory. Status: %s",
225                           android::statusToString(status).c_str());
226                     break;
227                 }
228                 // Per the HAL, all-zeros Rect means the entire buffer
229                 android::Rect rect = {0, 0, 0, 0};
230                 void* ret;
231                 status = android::GraphicBufferMapper::get().lock(bufferHandle, kBufferUsage, rect,
232                                                                   &ret);
233                 if (status != android::OK) {
234                     ALOGE("SensorsAidlTestSharedMemory failed to import buffer: Status: %s",
235                           android::statusToString(status).c_str());
236                 } else {
237                     buffer = static_cast<char*>(ret);
238                     mBufferHandle = bufferHandle;
239                 }
240                 break;
241             }
242             default:
243                 break;
244         }
245 
246         if (buffer != nullptr) {
247             mNativeHandle = handle;
248             mSize = size;
249             mBuffer = buffer;
250         }
251     }
252 
253     ISensors::SharedMemInfo::SharedMemType mType;
254     native_handle_t* mNativeHandle;
255     buffer_handle_t mBufferHandle;
256     size_t mSize;
257     char* mBuffer;
258 
259     DISALLOW_COPY_AND_ASSIGN(SensorsAidlTestSharedMemory);
260 };
261 
262 #endif  // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
263