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