• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <cinttypes>
18 #include <log/log.h>
19 #include <qemud.h>
20 #include <utils/SystemClock.h>
21 #include "multihal_sensors.h"
22 #include "sensor_list.h"
23 
24 namespace goldfish {
25 using ahs21::SensorType;
26 using ahs10::SensorFlagBits;
27 using ahs10::SensorStatus;
28 using ahs10::MetaDataEventType;
29 using ahs10::AdditionalInfoType;
30 
31 namespace {
32 constexpr int64_t kMaxSamplingPeriodNs = 1000000000;
33 }
34 
MultihalSensors()35 MultihalSensors::MultihalSensors()
36         : m_qemuSensorsFd(qemud_channel_open("sensors"))
37         , m_batchInfo(getSensorNumber()) {
38     if (!m_qemuSensorsFd.ok()) {
39         ALOGE("%s:%d: m_qemuSensorsFd is not opened", __func__, __LINE__);
40         ::abort();
41     }
42 
43     char buffer[64];
44     int len = snprintf(buffer, sizeof(buffer),
45                        "time:%" PRId64, ::android::elapsedRealtimeNano());
46     if (qemud_channel_send(m_qemuSensorsFd.get(), buffer, len) < 0) {
47         ALOGE("%s:%d: qemud_channel_send failed", __func__, __LINE__);
48         ::abort();
49     }
50 
51     using namespace std::literals;
52     const std::string_view kListSensorsCmd = "list-sensors"sv;
53 
54     if (qemud_channel_send(m_qemuSensorsFd.get(),
55                            kListSensorsCmd.data(),
56                            kListSensorsCmd.size()) < 0) {
57         ALOGE("%s:%d: qemud_channel_send failed", __func__, __LINE__);
58         ::abort();
59     }
60 
61     len = qemud_channel_recv(m_qemuSensorsFd.get(), buffer, sizeof(buffer) - 1);
62     if (len < 0) {
63         ALOGE("%s:%d: qemud_channel_recv failed", __func__, __LINE__);
64         ::abort();
65     }
66     buffer[len] = 0;
67     uint32_t hostSensorsMask = 0;
68     if (sscanf(buffer, "%u", &hostSensorsMask) != 1) {
69         ALOGE("%s:%d: Can't parse qemud response", __func__, __LINE__);
70         ::abort();
71     }
72 
73     m_availableSensorsMask = hostSensorsMask
74         & ((1u << getSensorNumber()) - 1);
75 
76     ALOGI("%s:%d: host sensors mask=%x, available sensors mask=%x",
77           __func__, __LINE__, hostSensorsMask, m_availableSensorsMask);
78 
79     if (!::android::base::Socketpair(AF_LOCAL, SOCK_STREAM, 0,
80                                      &m_callersFd, &m_sensorThreadFd)) {
81         ALOGE("%s:%d: Socketpair failed", __func__, __LINE__);
82         ::abort();
83     }
84 
85     setAdditionalInfoFrames();
86 
87     m_sensorThread = std::thread(&MultihalSensors::qemuSensorListenerThread, this);
88     m_batchThread = std::thread(&MultihalSensors::batchThread, this);
89 }
90 
~MultihalSensors()91 MultihalSensors::~MultihalSensors() {
92     setAllQemuSensors(false);
93 
94     m_batchRunning = false;
95     m_batchUpdated.notify_one();
96     m_batchThread.join();
97 
98     qemuSensorThreadSendCommand(kCMD_QUIT);
99     m_sensorThread.join();
100 }
101 
getName()102 const std::string MultihalSensors::getName() {
103     return "hal_sensors_2_1_impl_ranchu";
104 }
105 
debug(const hidl_handle & fd,const hidl_vec<hidl_string> & args)106 Return<void> MultihalSensors::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
107     (void)fd;
108     (void)args;
109     return {};
110 }
111 
getSensorsList_2_1(getSensorsList_2_1_cb _hidl_cb)112 Return<void> MultihalSensors::getSensorsList_2_1(getSensorsList_2_1_cb _hidl_cb) {
113     std::vector<SensorInfo> sensors;
114 
115     uint32_t mask = m_availableSensorsMask;
116     for (int i = 0; mask; ++i, mask >>= 1) {
117         if (mask & 1) {
118             sensors.push_back(*getSensorInfoByHandle(i));
119         }
120     }
121 
122     _hidl_cb(sensors);
123     return {};
124 }
125 
setOperationMode(const OperationMode mode)126 Return<Result> MultihalSensors::setOperationMode(const OperationMode mode) {
127     std::unique_lock<std::mutex> lock(m_mtx);
128 
129     if (m_activeSensorsMask) {
130         return Result::INVALID_OPERATION;
131     } else {
132         m_opMode = mode;
133         return Result::OK;
134     }
135 }
136 
activate(const int32_t sensorHandle,const bool enabled)137 Return<Result> MultihalSensors::activate(const int32_t sensorHandle,
138                                          const bool enabled) {
139     if (!isSensorHandleValid(sensorHandle)) {
140         return Result::BAD_VALUE;
141     }
142 
143     std::unique_lock<std::mutex> lock(m_mtx);
144     BatchInfo& batchInfo = m_batchInfo[sensorHandle];
145 
146     if (enabled) {
147         const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
148         LOG_ALWAYS_FATAL_IF(!sensor);
149         if (!(sensor->flags & static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE))) {
150             if (batchInfo.samplingPeriodNs <= 0) {
151                 return Result::BAD_VALUE;
152             }
153 
154             BatchEventRef batchEventRef;
155             batchEventRef.timestamp =
156                 ::android::elapsedRealtimeNano() + batchInfo.samplingPeriodNs;
157             batchEventRef.sensorHandle = sensorHandle;
158             batchEventRef.generation = ++batchInfo.generation;
159 
160             m_batchQueue.push(batchEventRef);
161             m_batchUpdated.notify_one();
162         } else if (sensor->type == SensorType::HEART_RATE){
163             // Heart rate sensor's first data after activation should be
164             // SENSOR_STATUS_UNRELIABLE.
165             Event event;
166             event.u.heartRate.status = SensorStatus::UNRELIABLE;
167             event.u.heartRate.bpm = 0;
168             event.timestamp = ::android::elapsedRealtimeNano();
169             event.sensorHandle = sensorHandle;
170             event.sensorType = SensorType::HEART_RATE;
171             doPostSensorEventLocked(*sensor, event);
172         }
173         sendAdditionalInfoReport(sensorHandle);
174         m_activeSensorsMask = m_activeSensorsMask | (1u << sensorHandle);
175     } else {
176         m_activeSensorsMask = m_activeSensorsMask & ~(1u << sensorHandle);
177     }
178     return Result::OK;
179 }
180 
batch(const int32_t sensorHandle,const int64_t samplingPeriodNs,const int64_t maxReportLatencyNs)181 Return<Result> MultihalSensors::batch(const int32_t sensorHandle,
182                                       const int64_t samplingPeriodNs,
183                                       const int64_t maxReportLatencyNs) {
184     (void)maxReportLatencyNs;
185 
186     if (!isSensorHandleValid(sensorHandle)) {
187         return Result::BAD_VALUE;
188     }
189 
190     const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
191     LOG_ALWAYS_FATAL_IF(!sensor);
192 
193     if (samplingPeriodNs < sensor->minDelay) {
194         return Result::BAD_VALUE;
195     }
196 
197     std::unique_lock<std::mutex> lock(m_mtx);
198     if (m_opMode == OperationMode::NORMAL) {
199         m_batchInfo[sensorHandle].samplingPeriodNs = samplingPeriodNs;
200 
201         auto minSamplingPeriodNs = kMaxSamplingPeriodNs;
202         auto activeSensorsMask = m_activeSensorsMask;
203         for (const auto& b : m_batchInfo) {
204             if (activeSensorsMask & 1) {
205                 const auto periodNs = b.samplingPeriodNs;
206                 if ((periodNs > 0) && (periodNs < minSamplingPeriodNs)) {
207                     minSamplingPeriodNs = periodNs;
208                 }
209             }
210 
211             activeSensorsMask >>= 1;
212         }
213 
214         const int delayMs = std::max(1, int(minSamplingPeriodNs / 1000000));
215 
216         char buffer[64];
217         const int len = snprintf(buffer, sizeof(buffer), "set-delay:%d", delayMs);
218 
219         if (qemud_channel_send(m_qemuSensorsFd.get(), buffer, len) < 0) {
220             ALOGE("%s:%d: qemud_channel_send failed", __func__, __LINE__);
221             ::abort();
222         }
223     }
224 
225     return Result::OK;
226 }
227 
flush(const int32_t sensorHandle)228 Return<Result> MultihalSensors::flush(const int32_t sensorHandle) {
229     if (!isSensorHandleValid(sensorHandle)) {
230         return Result::BAD_VALUE;
231     }
232 
233     const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
234     LOG_ALWAYS_FATAL_IF(!sensor);
235 
236     std::unique_lock<std::mutex> lock(m_mtx);
237     if (!isSensorActive(sensorHandle)) {
238         return Result::BAD_VALUE;
239     }
240 
241     Event event;
242     event.sensorHandle = sensorHandle;
243     event.sensorType = SensorType::META_DATA;
244     event.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
245 
246     doPostSensorEventLocked(*sensor, event);
247     sendAdditionalInfoReport(sensorHandle);
248 
249     return Result::OK;
250 }
251 
injectSensorData_2_1(const Event & event)252 Return<Result> MultihalSensors::injectSensorData_2_1(const Event& event) {
253     if (!isSensorHandleValid(event.sensorHandle)) {
254         return Result::BAD_VALUE;
255     }
256     if (event.sensorType == SensorType::ADDITIONAL_INFO) {
257         return Result::OK;
258     }
259 
260     std::unique_lock<std::mutex> lock(m_mtx);
261     if (m_opMode != OperationMode::DATA_INJECTION) {
262         return Result::INVALID_OPERATION;
263     }
264     const SensorInfo* sensor = getSensorInfoByHandle(event.sensorHandle);
265     LOG_ALWAYS_FATAL_IF(!sensor);
266     if (sensor->type != event.sensorType) {
267         return Result::BAD_VALUE;
268     }
269 
270     doPostSensorEventLocked(*sensor, event);
271     return Result::OK;
272 }
273 
initialize(const sp<IHalProxyCallback> & halProxyCallback)274 Return<Result> MultihalSensors::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
275     std::unique_lock<std::mutex> lock(m_mtx);
276     setAllQemuSensors(true);   // we need to start sampling sensors for batching
277     m_opMode = OperationMode::NORMAL;
278     m_halProxyCallback = halProxyCallback;
279     return Result::OK;
280 }
281 
postSensorEvent(const Event & event)282 void MultihalSensors::postSensorEvent(const Event& event) {
283     const SensorInfo* sensor = getSensorInfoByHandle(event.sensorHandle);
284     LOG_ALWAYS_FATAL_IF(!sensor);
285 
286     std::unique_lock<std::mutex> lock(m_mtx);
287     if (sensor->flags & static_cast<uint32_t>(SensorFlagBits::ON_CHANGE_MODE)) {
288         if (isSensorActive(event.sensorHandle)) {
289             doPostSensorEventLocked(*sensor, event);
290         }
291     } else {    // CONTINUOUS_MODE
292         m_batchInfo[event.sensorHandle].event = event;
293     }
294 }
295 
doPostSensorEventLocked(const SensorInfo & sensor,const Event & event)296 void MultihalSensors::doPostSensorEventLocked(const SensorInfo& sensor,
297                                               const Event& event) {
298     const bool isWakeupEvent =
299         sensor.flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
300 
301     m_halProxyCallback->postEvents(
302         {event},
303         m_halProxyCallback->createScopedWakelock(isWakeupEvent));
304 }
305 
setAdditionalInfoFrames()306 void MultihalSensors::setAdditionalInfoFrames() {
307     // https://developer.android.com/reference/android/hardware/SensorAdditionalInfo#TYPE_SENSOR_PLACEMENT
308     AdditionalInfo additionalInfoSensorPlacement = {
309             .type = AdditionalInfoType::AINFO_SENSOR_PLACEMENT,
310             .serial = 0,
311             .u.data_float{ {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5} },
312     };
313     const AdditionalInfo additionalInfoBegin = {
314             .type = AdditionalInfoType::AINFO_BEGIN,
315             .serial = 0,
316     };
317     const AdditionalInfo additionalInfoEnd = {
318             .type = AdditionalInfoType::AINFO_END,
319             .serial = 0,
320     };
321 
322     mAdditionalInfoFrames.insert(
323             mAdditionalInfoFrames.end(),
324             {additionalInfoBegin, additionalInfoSensorPlacement, additionalInfoEnd});
325 }
326 
sendAdditionalInfoReport(int sensorHandle)327 void MultihalSensors::sendAdditionalInfoReport(int sensorHandle) {
328     const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
329     const bool isWakeupEvent =
330         sensor->flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
331     std::vector<Event> events;
332 
333     for (const auto& frame : mAdditionalInfoFrames) {
334         events.emplace_back(Event{
335                 .timestamp = android::elapsedRealtimeNano(),
336                 .sensorHandle = sensorHandle,
337                 .sensorType = SensorType::ADDITIONAL_INFO,
338                 .u.additional = frame,
339         });
340     }
341 
342     if (!events.empty()) {
343         m_halProxyCallback->postEvents(
344                 events,
345                 m_halProxyCallback->createScopedWakelock(isWakeupEvent));
346     }
347 }
348 
qemuSensorThreadSendCommand(const char cmd) const349 bool MultihalSensors::qemuSensorThreadSendCommand(const char cmd) const {
350     return TEMP_FAILURE_RETRY(write(m_callersFd.get(), &cmd, 1)) == 1;
351 }
352 
isSensorHandleValid(int sensorHandle) const353 bool MultihalSensors::isSensorHandleValid(int sensorHandle) const {
354     if (!goldfish::isSensorHandleValid(sensorHandle)) {
355         return false;
356     }
357 
358     if (!(m_availableSensorsMask & (1u << sensorHandle))) {
359         return false;
360     }
361 
362     return true;
363 }
364 
batchThread()365 void MultihalSensors::batchThread() {
366     while (m_batchRunning) {
367         std::unique_lock<std::mutex> lock(m_mtx);
368         if (m_batchQueue.empty()) {
369             m_batchUpdated.wait(lock);
370         } else {
371             const int64_t d =
372                 m_batchQueue.top().timestamp - ::android::elapsedRealtimeNano();
373             m_batchUpdated.wait_for(lock, std::chrono::nanoseconds(d));
374         }
375 
376         const int64_t nowNs = ::android::elapsedRealtimeNano();
377         while (!m_batchQueue.empty() && (nowNs >= m_batchQueue.top().timestamp)) {
378             BatchEventRef evRef = m_batchQueue.top();
379             m_batchQueue.pop();
380 
381             const int sensorHandle = evRef.sensorHandle;
382             LOG_ALWAYS_FATAL_IF(!goldfish::isSensorHandleValid(sensorHandle));
383             if (!isSensorActive(sensorHandle)) {
384                 continue;
385             }
386 
387             BatchInfo &batchInfo = m_batchInfo[sensorHandle];
388             if (batchInfo.event.sensorType == SensorType::META_DATA) {
389                 ALOGW("%s:%d the host has not provided value yet for sensorHandle=%d",
390                       __func__, __LINE__, sensorHandle);
391             } else {
392                 batchInfo.event.timestamp = evRef.timestamp;
393                 const SensorInfo* sensor = getSensorInfoByHandle(sensorHandle);
394                 LOG_ALWAYS_FATAL_IF(!sensor);
395                 doPostSensorEventLocked(*sensor, batchInfo.event);
396             }
397 
398             if (evRef.generation == batchInfo.generation) {
399                 const int64_t samplingPeriodNs = batchInfo.samplingPeriodNs;
400                 LOG_ALWAYS_FATAL_IF(samplingPeriodNs <= 0);
401 
402                 evRef.timestamp += samplingPeriodNs;
403                 m_batchQueue.push(evRef);
404             }
405         }
406     }
407 }
408 
409 /// not supported //////////////////////////////////////////////////////////////
registerDirectChannel(const SharedMemInfo & mem,registerDirectChannel_cb _hidl_cb)410 Return<void> MultihalSensors::registerDirectChannel(const SharedMemInfo& mem,
411                                                     registerDirectChannel_cb _hidl_cb) {
412     (void)mem;
413     _hidl_cb(Result::INVALID_OPERATION, -1);
414     return {};
415 }
416 
unregisterDirectChannel(int32_t channelHandle)417 Return<Result> MultihalSensors::unregisterDirectChannel(int32_t channelHandle) {
418     (void)channelHandle;
419     return Result::INVALID_OPERATION;
420 }
421 
configDirectReport(int32_t sensorHandle,int32_t channelHandle,RateLevel rate,configDirectReport_cb _hidl_cb)422 Return<void> MultihalSensors::configDirectReport(int32_t sensorHandle,
423                                                  int32_t channelHandle,
424                                                  RateLevel rate,
425                                                  configDirectReport_cb _hidl_cb) {
426     (void)sensorHandle;
427     (void)channelHandle;
428     (void)rate;
429     _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
430     return {};
431 }
432 
433 }  // namespace goldfish
434