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 // LOG_TAG defined via build flag.
18 #ifndef LOG_TAG
19 #define LOG_TAG "AidlSensorManager"
20 #endif
21
22 #include "DirectReportChannel.h"
23 #include "EventQueue.h"
24 #include "SensorManagerAidl.h"
25 #include "utils.h"
26
27 #include <aidl/android/hardware/sensors/ISensors.h>
28 #include <android-base/logging.h>
29 #include <android/binder_ibinder.h>
30 #include <sched.h>
31
32 namespace android {
33 namespace frameworks {
34 namespace sensorservice {
35 namespace implementation {
36
37 using ::aidl::android::frameworks::sensorservice::IDirectReportChannel;
38 using ::aidl::android::frameworks::sensorservice::IEventQueue;
39 using ::aidl::android::frameworks::sensorservice::IEventQueueCallback;
40 using ::aidl::android::frameworks::sensorservice::ISensorManager;
41 using ::aidl::android::hardware::common::Ashmem;
42 using ::aidl::android::hardware::sensors::ISensors;
43 using ::aidl::android::hardware::sensors::SensorInfo;
44 using ::aidl::android::hardware::sensors::SensorType;
45 using ::android::frameworks::sensorservice::implementation::SensorManagerAidl;
46
47 static const char* POLL_THREAD_NAME = "aidl_ssvc_poll";
48
SensorManagerAidl(JavaVM * vm)49 SensorManagerAidl::SensorManagerAidl(JavaVM* vm)
50 : mLooper(new Looper(false)), mStopThread(true), mJavaVm(vm) {}
~SensorManagerAidl()51 SensorManagerAidl::~SensorManagerAidl() {
52 // Stops pollAll inside the thread.
53 std::lock_guard<std::mutex> lock(mThreadMutex);
54
55 mStopThread = true;
56 if (mLooper != nullptr) {
57 mLooper->wake();
58 }
59 if (mPollThread.joinable()) {
60 mPollThread.join();
61 }
62
63 ::android::SensorManager::removeInstanceForPackage(
64 String16(ISensorManager::descriptor));
65 }
66
createDirectChannel(::android::SensorManager & manager,size_t size,int type,const native_handle_t * handle,std::shared_ptr<IDirectReportChannel> * chan)67 ndk::ScopedAStatus createDirectChannel(::android::SensorManager& manager, size_t size, int type,
68 const native_handle_t* handle,
69 std::shared_ptr<IDirectReportChannel>* chan) {
70 int channelId = manager.createDirectChannel(size, type, handle);
71 if (channelId < 0) {
72 return convertResult(channelId);
73 }
74 if (channelId == 0) {
75 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
76 }
77 *chan = ndk::SharedRefBase::make<DirectReportChannel>(manager, channelId);
78 return ndk::ScopedAStatus::ok();
79 }
80
createAshmemDirectChannel(const Ashmem & in_mem,int64_t in_size,std::shared_ptr<IDirectReportChannel> * _aidl_return)81 ndk::ScopedAStatus SensorManagerAidl::createAshmemDirectChannel(
82 const Ashmem& in_mem, int64_t in_size,
83 std::shared_ptr<IDirectReportChannel>* _aidl_return) {
84 if (in_size > in_mem.size || in_size < ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH) {
85 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_BAD_VALUE);
86 }
87 native_handle_t* handle = native_handle_create(1, 0);
88 handle->data[0] = dup(in_mem.fd.get());
89
90 auto status = createDirectChannel(getInternalManager(), in_size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
91 handle, _aidl_return);
92 int result = native_handle_close(handle);
93 CHECK(result == 0) << "Failed to close the native_handle_t: " << result;
94 result = native_handle_delete(handle);
95 CHECK(result == 0) << "Failed to delete the native_handle_t: " << result;
96
97 return status;
98 }
99
createGrallocDirectChannel(const ndk::ScopedFileDescriptor & in_mem,int64_t in_size,std::shared_ptr<IDirectReportChannel> * _aidl_return)100 ndk::ScopedAStatus SensorManagerAidl::createGrallocDirectChannel(
101 const ndk::ScopedFileDescriptor& in_mem, int64_t in_size,
102 std::shared_ptr<IDirectReportChannel>* _aidl_return) {
103 native_handle_t* handle = native_handle_create(1, 0);
104 handle->data[0] = dup(in_mem.get());
105
106 auto status = createDirectChannel(getInternalManager(), in_size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
107 handle, _aidl_return);
108 int result = native_handle_close(handle);
109 CHECK(result == 0) << "Failed to close the native_handle_t: " << result;
110 result = native_handle_delete(handle);
111 CHECK(result == 0) << "Failed to delete the native_handle_t: " << result;
112
113 return status;
114 }
115
createEventQueue(const std::shared_ptr<IEventQueueCallback> & in_callback,std::shared_ptr<IEventQueue> * _aidl_return)116 ndk::ScopedAStatus SensorManagerAidl::createEventQueue(
117 const std::shared_ptr<IEventQueueCallback>& in_callback,
118 std::shared_ptr<IEventQueue>* _aidl_return) {
119 if (in_callback == nullptr) {
120 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_BAD_VALUE);
121 }
122
123 sp<::android::Looper> looper = getLooper();
124 if (looper == nullptr) {
125 LOG(ERROR) << "::android::SensorManagerAidl::createEventQueue cannot initialize looper";
126 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
127 }
128
129 String8 package(String8::format("aidl_client_pid_%d", AIBinder_getCallingPid()));
130 sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue(package);
131 if (internalQueue == nullptr) {
132 LOG(ERROR) << "::android::SensorManagerAidl::createEventQueue returns nullptr.";
133 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
134 }
135
136 *_aidl_return = ndk::SharedRefBase::make<EventQueue>(in_callback, looper, internalQueue);
137
138 return ndk::ScopedAStatus::ok();
139 }
140
convertSensor(Sensor src)141 SensorInfo convertSensor(Sensor src) {
142 SensorInfo dst;
143 dst.sensorHandle = src.getHandle();
144 dst.name = src.getName();
145 dst.vendor = src.getVendor();
146 dst.version = src.getVersion();
147 dst.type = static_cast<SensorType>(src.getType());
148 dst.typeAsString = src.getStringType();
149 // maxRange uses maxValue because ::android::Sensor wraps the
150 // internal sensor_t in this way.
151 dst.maxRange = src.getMaxValue();
152 dst.resolution = src.getResolution();
153 dst.power = src.getPowerUsage();
154 dst.minDelayUs = src.getMinDelay();
155 dst.fifoReservedEventCount = src.getFifoReservedEventCount();
156 dst.fifoMaxEventCount = src.getFifoMaxEventCount();
157 dst.requiredPermission = src.getRequiredPermission();
158 dst.maxDelayUs = src.getMaxDelay();
159 dst.flags = src.getFlags();
160 return dst;
161 }
162
getDefaultSensor(SensorType in_type,SensorInfo * _aidl_return)163 ndk::ScopedAStatus SensorManagerAidl::getDefaultSensor(SensorType in_type,
164 SensorInfo* _aidl_return) {
165 ::android::Sensor const* sensor =
166 getInternalManager().getDefaultSensor(static_cast<int>(in_type));
167 if (!sensor) {
168 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_NOT_EXIST);
169 }
170 *_aidl_return = convertSensor(*sensor);
171 return ndk::ScopedAStatus::ok();
172 }
173
getSensorList(std::vector<SensorInfo> * _aidl_return)174 ndk::ScopedAStatus SensorManagerAidl::getSensorList(std::vector<SensorInfo>* _aidl_return) {
175 Sensor const* const* list;
176 _aidl_return->clear();
177 ssize_t count = getInternalManager().getSensorList(&list);
178 if (count < 0 || list == nullptr) {
179 LOG(ERROR) << "SensorMAanger::getSensorList failed with count: " << count;
180 return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
181 }
182 _aidl_return->reserve(static_cast<size_t>(count));
183 for (ssize_t i = 0; i < count; ++i) {
184 _aidl_return->push_back(convertSensor(*list[i]));
185 }
186
187 return ndk::ScopedAStatus::ok();
188 }
189
getInternalManager()190 ::android::SensorManager& SensorManagerAidl::getInternalManager() {
191 int32_t version;
192 ndk::ScopedAStatus status = getInterfaceVersion(&version);
193 if (!status.isOk()) {
194 LOG(ERROR) << "Failed to get interface version with error: "
195 << status.getDescription();
196 version = -1;
197 }
198 String16 packageName = String16(ISensorManager::descriptor);
199 packageName += String16("@") + String16(std::to_string(version).c_str());
200 return ::android::SensorManager::getInstanceForPackage(packageName);
201 }
202
203 /* One global looper for all event queues created from this SensorManager. */
getLooper()204 sp<Looper> SensorManagerAidl::getLooper() {
205 std::lock_guard<std::mutex> lock(mThreadMutex);
206
207 if (!mJavaVm) {
208 LOG(ERROR) << "No Java VM. This must be running in a test or fuzzer.";
209 return mLooper;
210 }
211
212 if (!mPollThread.joinable()) {
213 // if thread not initialized, start thread
214 mStopThread = false;
215 std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {
216 struct sched_param p = {};
217 p.sched_priority = 10;
218 if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
219 LOG(ERROR) << "Could not use SCHED_FIFO for looper thread: " << strerror(errno);
220 }
221
222 // set looper
223 Looper::setForThread(looper);
224
225 // Attach the thread to JavaVM so that pollAll do not crash if the thread
226 // eventually calls into Java.
227 JavaVMAttachArgs args{.version = JNI_VERSION_1_2,
228 .name = POLL_THREAD_NAME,
229 .group = nullptr};
230 JNIEnv* env;
231 if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
232 LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
233 }
234
235 LOG(INFO) << POLL_THREAD_NAME << " started.";
236 for (;;) {
237 int pollResult = looper->pollAll(-1 /* timeout */);
238 if (pollResult == Looper::POLL_WAKE) {
239 if (stopThread == true) {
240 LOG(INFO) << POLL_THREAD_NAME << ": requested to stop";
241 break;
242 } else {
243 LOG(INFO) << POLL_THREAD_NAME << ": spurious wake up, back to work";
244 }
245 } else {
246 LOG(ERROR) << POLL_THREAD_NAME << ": Looper::pollAll returns unexpected "
247 << pollResult;
248 break;
249 }
250 }
251
252 if (javaVm->DetachCurrentThread() != JNI_OK) {
253 LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
254 }
255
256 LOG(INFO) << POLL_THREAD_NAME << " is terminated.";
257 }};
258 mPollThread = std::move(pollThread);
259 }
260 return mLooper;
261 }
262
263 } // namespace implementation
264 } // namespace sensorservice
265 } // namespace frameworks
266 } // namespace android
267