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 
     28 #include "EventQueue.h"
     29 #include "DirectReportChannel.h"
     30 #include "utils.h"
     31 
     32 #include <hwbinder/IPCThreadState.h>
     33 #include <utils/String8.h>
     34 
     35 namespace android {
     36 namespace frameworks {
     37 namespace sensorservice {
     38 namespace V1_0 {
     39 namespace implementation {
     40 
     41 using ::android::hardware::sensors::V1_0::SensorInfo;
     42 using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
     43 using ::android::hardware::hidl_vec;
     44 using ::android::hardware::Void;
     45 
     46 static const char* POLL_THREAD_NAME = "hidl_ssvc_poll";
     47 
     48 SensorManager::SensorManager(JavaVM* vm)
     49         : mLooper(new Looper(false /*allowNonCallbacks*/)), mStopThread(true), mJavaVm(vm) {
     50 }
     51 
     52 SensorManager::~SensorManager() {
     53     // Stops pollAll inside the thread.
     54     std::lock_guard<std::mutex> lock(mThreadMutex);
     55 
     56     mStopThread = true;
     57     if (mLooper != nullptr) {
     58         mLooper->wake();
     59     }
     60     if (mPollThread.joinable()) {
     61         mPollThread.join();
     62     }
     63 }
     64 
     65 // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
     66 Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
     67     ::android::Sensor const* const* list;
     68     ssize_t count = getInternalManager().getSensorList(&list);
     69     if (count < 0 || !list) {
     70         LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
     71         _hidl_cb({}, Result::UNKNOWN_ERROR);
     72         return Void();
     73     }
     74     hidl_vec<SensorInfo> ret;
     75     ret.resize(static_cast<size_t>(count));
     76     for (ssize_t i = 0; i < count; ++i) {
     77         ret[i] = convertSensor(*list[i]);
     78     }
     79     _hidl_cb(ret, Result::OK);
     80     return Void();
     81 }
     82 
     83 Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
     84     ::android::Sensor const* sensor = getInternalManager().getDefaultSensor(static_cast<int>(type));
     85     if (!sensor) {
     86         _hidl_cb({}, Result::NOT_EXIST);
     87         return Void();
     88     }
     89     _hidl_cb(convertSensor(*sensor), Result::OK);
     90     return Void();
     91 }
     92 
     93 template<typename Callback>
     94 void createDirectChannel(::android::SensorManager& manager, size_t size, int type,
     95         const native_handle_t* handle, const Callback& _hidl_cb) {
     96 
     97     int channelId = manager.createDirectChannel(
     98         size, type, handle);
     99     if (channelId < 0) {
    100         _hidl_cb(nullptr, convertResult(channelId));
    101         return;
    102     }
    103     if (channelId == 0) {
    104         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
    105         return;
    106     }
    107 
    108     _hidl_cb(sp<IDirectReportChannel>(new DirectReportChannel(manager, channelId)),
    109             Result::OK);
    110 }
    111 
    112 Return<void> SensorManager::createAshmemDirectChannel(
    113         const hidl_memory& mem, uint64_t size,
    114         createAshmemDirectChannel_cb _hidl_cb) {
    115     if (size > mem.size() || size < (uint64_t)SensorsEventFormatOffset::TOTAL_LENGTH) {
    116         _hidl_cb(nullptr, Result::BAD_VALUE);
    117         return Void();
    118     }
    119 
    120     createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
    121             mem.handle(), _hidl_cb);
    122 
    123     return Void();
    124 }
    125 
    126 Return<void> SensorManager::createGrallocDirectChannel(
    127         const hidl_handle& buffer, uint64_t size,
    128         createGrallocDirectChannel_cb _hidl_cb) {
    129 
    130     createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
    131             buffer.getNativeHandle(), _hidl_cb);
    132 
    133     return Void();
    134 }
    135 
    136 /* One global looper for all event queues created from this SensorManager. */
    137 sp<Looper> SensorManager::getLooper() {
    138     std::lock_guard<std::mutex> lock(mThreadMutex);
    139 
    140     if (!mPollThread.joinable()) {
    141         // if thread not initialized, start thread
    142         mStopThread = false;
    143         std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {
    144 
    145             struct sched_param p = {0};
    146             p.sched_priority = 10;
    147             if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
    148                 LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
    149                         << strerror(errno);
    150             }
    151 
    152             // set looper
    153             Looper::setForThread(looper);
    154 
    155             // Attach the thread to JavaVM so that pollAll do not crash if the thread
    156             // eventually calls into Java.
    157             JavaVMAttachArgs args{
    158                 .version = JNI_VERSION_1_2,
    159                 .name = POLL_THREAD_NAME,
    160                 .group = NULL
    161             };
    162             JNIEnv* env;
    163             if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
    164                 LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
    165             }
    166 
    167             LOG(INFO) << POLL_THREAD_NAME << " started.";
    168             for (;;) {
    169                 int pollResult = looper->pollAll(-1 /* timeout */);
    170                 if (pollResult == Looper::POLL_WAKE) {
    171                     if (stopThread == true) {
    172                         LOG(INFO) << POLL_THREAD_NAME << ": requested to stop";
    173                         break;
    174                     } else {
    175                         LOG(INFO) << POLL_THREAD_NAME << ": spurious wake up, back to work";
    176                     }
    177                 } else {
    178                     LOG(ERROR) << POLL_THREAD_NAME << ": Looper::pollAll returns unexpected "
    179                                << pollResult;
    180                     break;
    181                 }
    182             }
    183 
    184             if (javaVm->DetachCurrentThread() != JNI_OK) {
    185                 LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
    186             }
    187 
    188             LOG(INFO) << POLL_THREAD_NAME << " is terminated.";
    189         }};
    190         mPollThread = std::move(pollThread);
    191     }
    192     return mLooper;
    193 }
    194 
    195 ::android::SensorManager& SensorManager::getInternalManager() {
    196     std::lock_guard<std::mutex> lock(mInternalManagerMutex);
    197     if (mInternalManager == nullptr) {
    198         mInternalManager = &::android::SensorManager::getInstanceForPackage(
    199                 String16(ISensorManager::descriptor));
    200     }
    201     return *mInternalManager;
    202 }
    203 
    204 Return<void> SensorManager::createEventQueue(
    205         const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
    206     if (callback == nullptr) {
    207         _hidl_cb(nullptr, Result::BAD_VALUE);
    208         return Void();
    209     }
    210 
    211     sp<::android::Looper> looper = getLooper();
    212     if (looper == nullptr) {
    213         LOG(ERROR) << "::android::SensorManager::createEventQueue cannot initialize looper";
    214         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
    215         return Void();
    216     }
    217 
    218     String8 package(String8::format("hidl_client_pid_%d",
    219                                     android::hardware::IPCThreadState::self()->getCallingPid()));
    220     sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue(package);
    221     if (internalQueue == nullptr) {
    222         LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
    223         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
    224         return Void();
    225     }
    226 
    227     sp<IEventQueue> queue = new EventQueue(callback, looper, internalQueue);
    228     _hidl_cb(queue, Result::OK);
    229 
    230     return Void();
    231 }
    232 
    233 }  // namespace implementation
    234 }  // namespace V1_0
    235 }  // namespace sensorservice
    236 }  // namespace frameworks
    237 }  // namespace android
    238