Home | History | Annotate | Download | only in hidl
      1 /*
      2  * Copyright (C) 2017 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 "HidlSensorManager"
     20 #endif
     21 #include <android-base/logging.h>
     22 
     23 #include "SensorManager.h"
     24 
     25 #include <sched.h>
     26 
     27 #include <thread>
     28 
     29 #include "EventQueue.h"
     30 #include "DirectReportChannel.h"
     31 #include "utils.h"
     32 
     33 namespace android {
     34 namespace frameworks {
     35 namespace sensorservice {
     36 namespace V1_0 {
     37 namespace implementation {
     38 
     39 using ::android::hardware::sensors::V1_0::SensorInfo;
     40 using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
     41 using ::android::hardware::hidl_vec;
     42 using ::android::hardware::Void;
     43 using ::android::sp;
     44 
     45 static const char* POLL_THREAD_NAME = "hidl_ssvc_poll";
     46 
     47 SensorManager::SensorManager(JavaVM* vm)
     48         : mJavaVm(vm) {
     49 }
     50 
     51 SensorManager::~SensorManager() {
     52     // Stops pollAll inside the thread.
     53     std::unique_lock<std::mutex> lock(mLooperMutex);
     54     if (mLooper != nullptr) {
     55         mLooper->wake();
     56     }
     57 }
     58 
     59 // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
     60 Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
     61     ::android::Sensor const* const* list;
     62     ssize_t count = getInternalManager().getSensorList(&list);
     63     if (count < 0 || !list) {
     64         LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
     65         _hidl_cb({}, Result::UNKNOWN_ERROR);
     66         return Void();
     67     }
     68     hidl_vec<SensorInfo> ret;
     69     ret.resize(static_cast<size_t>(count));
     70     for (ssize_t i = 0; i < count; ++i) {
     71         ret[i] = convertSensor(*list[i]);
     72     }
     73     _hidl_cb(ret, Result::OK);
     74     return Void();
     75 }
     76 
     77 Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
     78     ::android::Sensor const* sensor = getInternalManager().getDefaultSensor(static_cast<int>(type));
     79     if (!sensor) {
     80         _hidl_cb({}, Result::NOT_EXIST);
     81         return Void();
     82     }
     83     _hidl_cb(convertSensor(*sensor), Result::OK);
     84     return Void();
     85 }
     86 
     87 template<typename Callback>
     88 void createDirectChannel(::android::SensorManager& manager, size_t size, int type,
     89         const native_handle_t* handle, const Callback& _hidl_cb) {
     90 
     91     int channelId = manager.createDirectChannel(
     92         size, type, handle);
     93     if (channelId < 0) {
     94         _hidl_cb(nullptr, convertResult(channelId));
     95         return;
     96     }
     97     if (channelId == 0) {
     98         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
     99         return;
    100     }
    101 
    102     _hidl_cb(sp<IDirectReportChannel>(new DirectReportChannel(manager, channelId)),
    103             Result::OK);
    104 }
    105 
    106 Return<void> SensorManager::createAshmemDirectChannel(
    107         const hidl_memory& mem, uint64_t size,
    108         createAshmemDirectChannel_cb _hidl_cb) {
    109     if (size > mem.size() || size < (uint64_t)SensorsEventFormatOffset::TOTAL_LENGTH) {
    110         _hidl_cb(nullptr, Result::BAD_VALUE);
    111         return Void();
    112     }
    113 
    114     createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
    115             mem.handle(), _hidl_cb);
    116 
    117     return Void();
    118 }
    119 
    120 Return<void> SensorManager::createGrallocDirectChannel(
    121         const hidl_handle& buffer, uint64_t size,
    122         createGrallocDirectChannel_cb _hidl_cb) {
    123 
    124     createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
    125             buffer.getNativeHandle(), _hidl_cb);
    126 
    127     return Void();
    128 }
    129 
    130 /* One global looper for all event queues created from this SensorManager. */
    131 sp<::android::Looper> SensorManager::getLooper() {
    132     std::unique_lock<std::mutex> lock(mLooperMutex);
    133     if (mLooper == nullptr) {
    134         std::condition_variable looperSet;
    135 
    136         std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet, javaVm = mJavaVm] {
    137 
    138             struct sched_param p = {0};
    139             p.sched_priority = 10;
    140             if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
    141                 LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
    142                         << strerror(errno);
    143             }
    144 
    145             std::unique_lock<std::mutex> lock(mutex);
    146             if (looper != nullptr) {
    147                 LOG(INFO) << "Another thread has already set the looper, exiting this one.";
    148                 return;
    149             }
    150             looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
    151             lock.unlock();
    152 
    153             // Attach the thread to JavaVM so that pollAll do not crash if the event
    154             // is from Java.
    155             JavaVMAttachArgs args{
    156                 .version = JNI_VERSION_1_2,
    157                 .name = POLL_THREAD_NAME,
    158                 .group = NULL
    159             };
    160             JNIEnv* env;
    161             if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
    162                 LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
    163             }
    164 
    165             looperSet.notify_one();
    166             int pollResult = looper->pollAll(-1 /* timeout */);
    167             if (pollResult != ALOOPER_POLL_WAKE) {
    168                 LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
    169             }
    170 
    171             if (javaVm->DetachCurrentThread() != JNI_OK) {
    172                 LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
    173             }
    174 
    175             LOG(INFO) << "Looper thread is terminated.";
    176         }}.detach();
    177         looperSet.wait(lock, [this]{ return this->mLooper != nullptr; });
    178     }
    179     return mLooper;
    180 }
    181 
    182 ::android::SensorManager& SensorManager::getInternalManager() {
    183     std::lock_guard<std::mutex> lock(mInternalManagerMutex);
    184     if (mInternalManager == nullptr) {
    185         mInternalManager = &::android::SensorManager::getInstanceForPackage(
    186                 String16(ISensorManager::descriptor));
    187     }
    188     return *mInternalManager;
    189 }
    190 
    191 Return<void> SensorManager::createEventQueue(
    192         const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
    193     if (callback == nullptr) {
    194         _hidl_cb(nullptr, Result::BAD_VALUE);
    195         return Void();
    196     }
    197 
    198     sp<::android::Looper> looper = getLooper();
    199     sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue();
    200     if (internalQueue == nullptr) {
    201         LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
    202         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
    203         return Void();
    204     }
    205 
    206     sp<IEventQueue> queue = new EventQueue(callback, looper, internalQueue);
    207     _hidl_cb(queue, Result::OK);
    208 
    209     return Void();
    210 }
    211 
    212 }  // namespace implementation
    213 }  // namespace V1_0
    214 }  // namespace sensorservice
    215 }  // namespace frameworks
    216 }  // namespace android
    217