1 /*
2  * Copyright (C) 2018 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_TEST_SHARED_MEMORY_H
18 #define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
19 
20 #include "GrallocWrapper.h"
21 
22 #include <android-base/macros.h>
23 #include <log/log.h>
24 
25 #include <sys/mman.h>
26 #include <cinttypes>
27 
28 #include <cutils/ashmem.h>
29 
30 using namespace ::android::hardware::sensors::V1_0;
31 
32 template <class SensorTypeVersion, class EventType>
33 class SensorsTestSharedMemory {
34   public:
create(SharedMemType type,size_t size)35     static SensorsTestSharedMemory* create(SharedMemType type, size_t size) {
36         constexpr size_t kMaxSize =
37                 128 * 1024 * 1024;  // sensor test should not need more than 128M
38         if (size == 0 || size >= kMaxSize) {
39             return nullptr;
40         }
41 
42         auto m = new SensorsTestSharedMemory<SensorTypeVersion, EventType>(type, size);
43         if (m->mSize != size || m->mBuffer == nullptr) {
44             delete m;
45             m = nullptr;
46         }
47         return m;
48     }
49 
getSharedMemInfo()50     SharedMemInfo getSharedMemInfo() const {
51         SharedMemInfo mem = {.type = mType,
52                              .format = SharedMemFormat::SENSORS_EVENT,
53                              .size = static_cast<uint32_t>(mSize),
54                              .memoryHandle = mNativeHandle};
55         return mem;
56     }
getBuffer()57     char* getBuffer() const { return mBuffer; }
getSize()58     size_t getSize() const { return mSize; }
59     std::vector<EventType> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const {
60         constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
61         constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
62         constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
63         constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
64         constexpr size_t kOffsetAtomicCounter =
65                 static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
66         constexpr size_t kOffsetTimestamp =
67                 static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
68         constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
69 
70         std::vector<EventType> events;
71         std::vector<float> data(16);
72 
73         while (offset + kEventSize <= mSize) {
74             int64_t atomicCounter =
75                     *reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
76             if (atomicCounter <= lastCounter) {
77                 ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
78                       lastCounter);
79                 break;
80             }
81 
82             int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
83             if (size != kEventSize) {
84                 // unknown error, events parsed may be wrong, remove all
85                 events.clear();
86                 break;
87             }
88 
89             int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
90             int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
91             int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
92 
93             ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
94                   ", timestamp %" PRId64,
95                   offset, atomicCounter, token, type, timestamp);
96 
97             EventType event = {
98                     .timestamp = timestamp,
99                     .sensorHandle = token,
100                     .sensorType = static_cast<SensorTypeVersion>(type),
101             };
102             event.u.data = android::hardware::hidl_array<float, 16>(
103                     reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
104 
105             events.push_back(event);
106 
107             lastCounter = atomicCounter;
108             offset += kEventSize;
109         }
110 
111         return events;
112     }
113 
~SensorsTestSharedMemory()114     virtual ~SensorsTestSharedMemory() {
115         switch (mType) {
116             case SharedMemType::ASHMEM: {
117                 if (mSize != 0) {
118                     ::munmap(mBuffer, mSize);
119                     mBuffer = nullptr;
120 
121                     ::native_handle_close(mNativeHandle);
122                     ::native_handle_delete(mNativeHandle);
123 
124                     mNativeHandle = nullptr;
125                     mSize = 0;
126                 }
127                 break;
128             }
129             case SharedMemType::GRALLOC: {
130                 if (mSize != 0) {
131                     mGrallocWrapper->freeBuffer(mNativeHandle);
132                     mNativeHandle = nullptr;
133                     mSize = 0;
134                 }
135                 break;
136             }
137             default: {
138                 if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
139                     ALOGE("SensorsTestSharedMemory %p not properly destructed: "
140                           "type %d, native handle %p, size %zu, buffer %p",
141                           this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
142                 }
143                 break;
144             }
145         }
146     }
147 
148   private:
SensorsTestSharedMemory(SharedMemType type,size_t size)149     SensorsTestSharedMemory(SharedMemType type, size_t size)
150         : mType(type), mSize(0), mBuffer(nullptr) {
151         native_handle_t* handle = nullptr;
152         char* buffer = nullptr;
153         switch (type) {
154             case SharedMemType::ASHMEM: {
155                 int fd;
156                 handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
157                 if (handle != nullptr) {
158                     handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
159                     if (handle->data[0] > 0) {
160                         // memory is pinned by default
161                         buffer = static_cast<char*>(
162                                 ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
163                         if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
164                             break;
165                         }
166                         ::native_handle_close(handle);
167                     }
168                     ::native_handle_delete(handle);
169                     handle = nullptr;
170                 }
171                 break;
172             }
173             case SharedMemType::GRALLOC: {
174                 mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
175                 if (!mGrallocWrapper->isInitialized()) {
176                     break;
177                 }
178 
179                 std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
180                 handle = buf.first;
181                 buffer = static_cast<char*>(buf.second);
182                 break;
183             }
184             default:
185                 break;
186         }
187 
188         if (buffer != nullptr) {
189             mNativeHandle = handle;
190             mSize = size;
191             mBuffer = buffer;
192         }
193     }
194 
195     SharedMemType mType;
196     native_handle_t* mNativeHandle;
197     size_t mSize;
198     char* mBuffer;
199     std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
200 
201     DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
202 };
203 
204 #endif  // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
205