unplugged-system/frameworks/native/services/sensorservice/aidl/SensorManager.cpp

254 lines
9.9 KiB
C++

/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// LOG_TAG defined via build flag.
#ifndef LOG_TAG
#define LOG_TAG "AidlSensorManager"
#endif
#include "DirectReportChannel.h"
#include "EventQueue.h"
#include "SensorManagerAidl.h"
#include "utils.h"
#include <aidl/android/hardware/sensors/ISensors.h>
#include <android-base/logging.h>
#include <android/binder_ibinder.h>
#include <sched.h>
namespace android {
namespace frameworks {
namespace sensorservice {
namespace implementation {
using ::aidl::android::frameworks::sensorservice::IDirectReportChannel;
using ::aidl::android::frameworks::sensorservice::IEventQueue;
using ::aidl::android::frameworks::sensorservice::IEventQueueCallback;
using ::aidl::android::frameworks::sensorservice::ISensorManager;
using ::aidl::android::hardware::common::Ashmem;
using ::aidl::android::hardware::sensors::ISensors;
using ::aidl::android::hardware::sensors::SensorInfo;
using ::aidl::android::hardware::sensors::SensorType;
using ::android::frameworks::sensorservice::implementation::SensorManagerAidl;
static const char* POLL_THREAD_NAME = "aidl_ssvc_poll";
SensorManagerAidl::SensorManagerAidl(JavaVM* vm)
: mLooper(new Looper(false)), mStopThread(true), mJavaVm(vm) {}
SensorManagerAidl::~SensorManagerAidl() {
// Stops pollAll inside the thread.
std::lock_guard<std::mutex> lock(mThreadMutex);
mStopThread = true;
if (mLooper != nullptr) {
mLooper->wake();
}
if (mPollThread.joinable()) {
mPollThread.join();
}
::android::SensorManager::removeInstanceForPackage(
String16(ISensorManager::descriptor));
}
ndk::ScopedAStatus createDirectChannel(::android::SensorManager& manager, size_t size, int type,
const native_handle_t* handle,
std::shared_ptr<IDirectReportChannel>* chan) {
int channelId = manager.createDirectChannel(size, type, handle);
if (channelId < 0) {
return convertResult(channelId);
}
if (channelId == 0) {
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
}
*chan = ndk::SharedRefBase::make<DirectReportChannel>(manager, channelId);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus SensorManagerAidl::createAshmemDirectChannel(
const Ashmem& in_mem, int64_t in_size,
std::shared_ptr<IDirectReportChannel>* _aidl_return) {
if (in_size > in_mem.size || in_size < ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH) {
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_BAD_VALUE);
}
native_handle_t* handle = native_handle_create(1, 0);
handle->data[0] = dup(in_mem.fd.get());
auto status = createDirectChannel(getInternalManager(), in_size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
handle, _aidl_return);
int result = native_handle_close(handle);
CHECK(result == 0) << "Failed to close the native_handle_t: " << result;
result = native_handle_delete(handle);
CHECK(result == 0) << "Failed to delete the native_handle_t: " << result;
return status;
}
ndk::ScopedAStatus SensorManagerAidl::createGrallocDirectChannel(
const ndk::ScopedFileDescriptor& in_mem, int64_t in_size,
std::shared_ptr<IDirectReportChannel>* _aidl_return) {
native_handle_t* handle = native_handle_create(1, 0);
handle->data[0] = dup(in_mem.get());
auto status = createDirectChannel(getInternalManager(), in_size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
handle, _aidl_return);
int result = native_handle_close(handle);
CHECK(result == 0) << "Failed to close the native_handle_t: " << result;
result = native_handle_delete(handle);
CHECK(result == 0) << "Failed to delete the native_handle_t: " << result;
return status;
}
ndk::ScopedAStatus SensorManagerAidl::createEventQueue(
const std::shared_ptr<IEventQueueCallback>& in_callback,
std::shared_ptr<IEventQueue>* _aidl_return) {
if (in_callback == nullptr) {
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_BAD_VALUE);
}
sp<::android::Looper> looper = getLooper();
if (looper == nullptr) {
LOG(ERROR) << "::android::SensorManagerAidl::createEventQueue cannot initialize looper";
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
}
String8 package(String8::format("aidl_client_pid_%d", AIBinder_getCallingPid()));
sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue(package);
if (internalQueue == nullptr) {
LOG(ERROR) << "::android::SensorManagerAidl::createEventQueue returns nullptr.";
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
}
*_aidl_return = ndk::SharedRefBase::make<EventQueue>(in_callback, looper, internalQueue);
return ndk::ScopedAStatus::ok();
}
SensorInfo convertSensor(Sensor src) {
SensorInfo dst;
dst.sensorHandle = src.getHandle();
dst.name = src.getName();
dst.vendor = src.getVendor();
dst.version = src.getVersion();
dst.type = static_cast<SensorType>(src.getType());
dst.typeAsString = src.getStringType();
// maxRange uses maxValue because ::android::Sensor wraps the
// internal sensor_t in this way.
dst.maxRange = src.getMaxValue();
dst.resolution = src.getResolution();
dst.power = src.getPowerUsage();
dst.minDelayUs = src.getMinDelay();
dst.fifoReservedEventCount = src.getFifoReservedEventCount();
dst.fifoMaxEventCount = src.getFifoMaxEventCount();
dst.requiredPermission = src.getRequiredPermission();
dst.maxDelayUs = src.getMaxDelay();
dst.flags = src.getFlags();
return dst;
}
ndk::ScopedAStatus SensorManagerAidl::getDefaultSensor(SensorType in_type,
SensorInfo* _aidl_return) {
::android::Sensor const* sensor =
getInternalManager().getDefaultSensor(static_cast<int>(in_type));
if (!sensor) {
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_NOT_EXIST);
}
*_aidl_return = convertSensor(*sensor);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus SensorManagerAidl::getSensorList(std::vector<SensorInfo>* _aidl_return) {
Sensor const* const* list;
_aidl_return->clear();
ssize_t count = getInternalManager().getSensorList(&list);
if (count < 0 || list == nullptr) {
LOG(ERROR) << "SensorMAanger::getSensorList failed with count: " << count;
return ndk::ScopedAStatus::fromServiceSpecificError(ISensorManager::RESULT_UNKNOWN_ERROR);
}
_aidl_return->reserve(static_cast<size_t>(count));
for (ssize_t i = 0; i < count; ++i) {
_aidl_return->push_back(convertSensor(*list[i]));
}
return ndk::ScopedAStatus::ok();
}
::android::SensorManager& SensorManagerAidl::getInternalManager() {
return ::android::SensorManager::getInstanceForPackage(
String16(ISensorManager::descriptor));
}
/* One global looper for all event queues created from this SensorManager. */
sp<Looper> SensorManagerAidl::getLooper() {
std::lock_guard<std::mutex> lock(mThreadMutex);
if (!mPollThread.joinable()) {
// if thread not initialized, start thread
mStopThread = false;
std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {
struct sched_param p = {};
p.sched_priority = 10;
if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
LOG(ERROR) << "Could not use SCHED_FIFO for looper thread: " << strerror(errno);
}
// set looper
Looper::setForThread(looper);
// Attach the thread to JavaVM so that pollAll do not crash if the thread
// eventually calls into Java.
JavaVMAttachArgs args{.version = JNI_VERSION_1_2,
.name = POLL_THREAD_NAME,
.group = nullptr};
JNIEnv* env;
if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
}
LOG(INFO) << POLL_THREAD_NAME << " started.";
for (;;) {
int pollResult = looper->pollAll(-1 /* timeout */);
if (pollResult == Looper::POLL_WAKE) {
if (stopThread == true) {
LOG(INFO) << POLL_THREAD_NAME << ": requested to stop";
break;
} else {
LOG(INFO) << POLL_THREAD_NAME << ": spurious wake up, back to work";
}
} else {
LOG(ERROR) << POLL_THREAD_NAME << ": Looper::pollAll returns unexpected "
<< pollResult;
break;
}
}
if (javaVm->DetachCurrentThread() != JNI_OK) {
LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
}
LOG(INFO) << POLL_THREAD_NAME << " is terminated.";
}};
mPollThread = std::move(pollThread);
}
return mLooper;
}
} // namespace implementation
} // namespace sensorservice
} // namespace frameworks
} // namespace android