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