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 #include "HidRawSensorDevice.h"
18 #include "HidRawSensor.h"
19 #include "HidSensorDef.h"
20 
21 #include <utils/Log.h>
22 #include <fcntl.h>
23 #include <linux/input.h>
24 #include <linux/hidraw.h>
25 #include <sys/ioctl.h>
26 
27 #include <set>
28 
29 namespace android {
30 namespace SensorHalExt {
31 
32 using namespace Hid::Sensor::SensorTypeUsage;
33 using namespace Hid::Sensor::PropertyUsage;
34 
35 const std::unordered_set<unsigned int> HidRawSensorDevice::sInterested{
36         ACCELEROMETER_3D, GYROMETER_3D, COMPASS_3D, CUSTOM};
37 
enableSchedFifoMode()38 void HidRawSensorDevice::enableSchedFifoMode() {
39   constexpr int kHidRawSensorPriority = 10;  // Matches with sensor service priority
40   struct sched_param param = {0};
41   param.sched_priority = kHidRawSensorPriority;
42   if (sched_setscheduler(getTid(), SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
43     ALOGE("Couldn't set SCHED_FIFO for HidRawSensor thread: %s", strerror(errno));
44   }
45 }
46 
create(const std::string & devName)47 sp<HidRawSensorDevice> HidRawSensorDevice::create(const std::string &devName) {
48     sp<HidRawSensorDevice> device(new HidRawSensorDevice(devName));
49     // offset +1 strong count added by constructor
50     device->decStrong(device.get());
51 
52     if (device->mValid) {
53         return device;
54     } else {
55         return nullptr;
56     }
57 }
58 
HidRawSensorDevice(const std::string & devName)59 HidRawSensorDevice::HidRawSensorDevice(const std::string &devName)
60         : RefBase(), HidRawDevice(devName, sInterested),
61           Thread(false /*canCallJava*/), mValid(false) {
62     // create HidRawSensor objects from digest
63     // HidRawSensor object will take sp<HidRawSensorDevice> as parameter, so increment strong count
64     // to prevent "this" being destructed.
65     this->incStrong(this);
66 
67     if (!HidRawDevice::isValid()) {
68         return;
69     }
70 
71     for (const auto &digest : mDigestVector) { // for each usage - vec<ReportPacket> pair
72         uint32_t usage = static_cast<uint32_t>(digest.fullUsage);
73         sp<HidRawSensor> s(new HidRawSensor(this, usage, digest.packets));
74         if (s->isValid()) {
75             for (const auto &packet : digest.packets) {
76                 if (packet.type == HidParser::REPORT_TYPE_INPUT) { // only used for input mapping
77                     mSensors.emplace(packet.id/* report id*/, s);
78                 }
79             }
80         }
81     }
82     if (mSensors.size() == 0) {
83         return;
84     }
85 
86     run("HidRawSensor", PRIORITY_URGENT_DISPLAY);
87     enableSchedFifoMode();
88     mValid = true;
89 }
90 
~HidRawSensorDevice()91 HidRawSensorDevice::~HidRawSensorDevice() {
92     ALOGV("~HidRawSensorDevice %p", this);
93     requestExitAndWait();
94     ALOGV("~HidRawSensorDevice %p, thread exited", this);
95 }
96 
threadLoop()97 bool HidRawSensorDevice::threadLoop() {
98     ALOGV("Hid Raw Device thread started %p", this);
99     std::vector<uint8_t> buffer;
100     bool ret;
101     uint8_t usageId;
102 
103     while(!Thread::exitPending()) {
104         ret = receiveReport(&usageId, &buffer);
105         if (!ret) {
106             break;
107         }
108 
109         auto i = mSensors.find(usageId);
110         if (i == mSensors.end()) {
111             ALOGW("Input of unknow usage id %u received", usageId);
112             continue;
113         }
114 
115         i->second->handleInput(usageId, buffer);
116     }
117 
118     ALOGI("Hid Raw Device thread ended for %p", this);
119     return false;
120 }
121 
getSensors() const122 BaseSensorVector HidRawSensorDevice::getSensors() const {
123     BaseSensorVector ret;
124     std::set<sp<BaseSensorObject>> set;
125     for (const auto &s : mSensors) {
126         if (set.find(s.second) == set.end()) {
127             ret.push_back(s.second);
128             set.insert(s.second);
129         }
130     }
131     return ret;
132 }
133 
134 } // namespace SensorHalExt
135 } // namespace android
136