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