SensorDevice.cpp revision 2bec6230661e66ce37d8a074df32e07553e3cb8c
1/*
2 * Copyright (C) 2010 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#include "SensorDevice.h"
17#include "SensorService.h"
18
19#include <android-base/logging.h>
20#include <sensors/convert.h>
21#include <utils/Atomic.h>
22#include <utils/Errors.h>
23#include <utils/Singleton.h>
24
25#include <chrono>
26#include <cinttypes>
27#include <thread>
28
29using android::hardware::hidl_vec;
30
31using namespace android::hardware::sensors::V1_0;
32using namespace android::hardware::sensors::V1_0::implementation;
33
34
35namespace android {
36// ---------------------------------------------------------------------------
37
38ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
39
40static status_t StatusFromResult(Result result) {
41    switch (result) {
42        case Result::OK:
43            return OK;
44        case Result::BAD_VALUE:
45            return BAD_VALUE;
46        case Result::PERMISSION_DENIED:
47            return PERMISSION_DENIED;
48        case Result::INVALID_OPERATION:
49            return INVALID_OPERATION;
50        case Result::NO_MEMORY:
51            return NO_MEMORY;
52    }
53}
54
55SensorDevice::SensorDevice() : mHidlTransportErrors(20) {
56    if (!connectHidlService()) {
57        return;
58    }
59    checkReturn(mSensors->getSensorsList(
60            [&](const auto &list) {
61                const size_t count = list.size();
62
63                mActivationCount.setCapacity(count);
64                Info model;
65                for (size_t i=0 ; i < count; i++) {
66                    sensor_t sensor;
67                    convertToSensor(list[i], &sensor);
68                    mSensorList.push_back(sensor);
69
70                    mActivationCount.add(list[i].sensorHandle, model);
71
72                    checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
73                }
74            }));
75
76    mIsDirectReportSupported =
77           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
78}
79
80bool SensorDevice::connectHidlService() {
81    // SensorDevice may wait upto 100ms * 10 = 1s for hidl service.
82    constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
83    size_t retry = 10;
84
85    while (true) {
86        int initStep = 0;
87        mSensors = ISensors::getService();
88        if (mSensors != nullptr) {
89            ++initStep;
90            // Poke ISensor service. If it has lingering connection from previous generation of
91            // system server, it will kill itself. There is no intention to handle the poll result,
92            // which will be done since the size is 0.
93            if(mSensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
94                // ok to continue
95                break;
96            }
97            // hidl service is restarting, pointer is invalid.
98            mSensors = nullptr;
99        }
100
101        if (--retry <= 0) {
102            ALOGE("Cannot connect to ISensors hidl service!");
103            break;
104        }
105        // Delay 100ms before retry, hidl service is expected to come up in short time after
106        // crash.
107        ALOGI("%s unsuccessful, try again soon (remaining retry %zu).",
108                (initStep == 0) ? "getService()" : "poll() check", retry);
109        std::this_thread::sleep_for(RETRY_DELAY);
110    }
111    return (mSensors != nullptr);
112}
113
114void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
115    // not need to check mSensors because this is is only called after successful poll()
116    if (connected) {
117        Info model;
118        mActivationCount.add(handle, model);
119        checkReturn(mSensors->activate(handle, 0 /* enabled */));
120    } else {
121        mActivationCount.removeItem(handle);
122    }
123}
124
125std::string SensorDevice::dump() const {
126    if (mSensors == nullptr) return "HAL not initialized\n";
127
128    String8 result;
129    result.appendFormat("Total %zu h/w sensors, %zu running:\n",
130                        mSensorList.size(), mActivationCount.size());
131
132    Mutex::Autolock _l(mLock);
133    for (const auto & s : mSensorList) {
134        int32_t handle = s.handle;
135        const Info& info = mActivationCount.valueFor(handle);
136        if (info.batchParams.isEmpty()) continue;
137
138        result.appendFormat("0x%08x) active-count = %zu; ", handle, info.batchParams.size());
139
140        result.append("sampling_period(ms) = {");
141        for (size_t j = 0; j < info.batchParams.size(); j++) {
142            const BatchParams& params = info.batchParams[j];
143            result.appendFormat("%.1f%s", params.mTSample / 1e6f,
144                j < info.batchParams.size() - 1 ? ", " : "");
145        }
146        result.appendFormat("}, selected = %.2f ms; ", info.bestBatchParams.mTSample / 1e6f);
147
148        result.append("batching_period(ms) = {");
149        for (size_t j = 0; j < info.batchParams.size(); j++) {
150            const BatchParams& params = info.batchParams[j];
151            result.appendFormat("%.1f%s", params.mTBatch / 1e6f,
152                    j < info.batchParams.size() - 1 ? ", " : "");
153        }
154        result.appendFormat("}, selected = %.2f ms\n", info.bestBatchParams.mTBatch / 1e6f);
155    }
156
157    return result.string();
158}
159
160ssize_t SensorDevice::getSensorList(sensor_t const** list) {
161    *list = &mSensorList[0];
162
163    return mSensorList.size();
164}
165
166status_t SensorDevice::initCheck() const {
167    return mSensors != NULL ? NO_ERROR : NO_INIT;
168}
169
170ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
171    if (mSensors == nullptr) return NO_INIT;
172
173    ssize_t err;
174    int numHidlTransportErrors = 0;
175    bool hidlTransportError = false;
176
177    do {
178        auto ret = mSensors->poll(
179                count,
180                [&](auto result,
181                    const auto &events,
182                    const auto &dynamicSensorsAdded) {
183                    if (result == Result::OK) {
184                        convertToSensorEvents(events, dynamicSensorsAdded, buffer);
185                        err = (ssize_t)events.size();
186                    } else {
187                        err = StatusFromResult(result);
188                    }
189                });
190
191        if (ret.isOk())  {
192            hidlTransportError = false;
193        } else {
194            hidlTransportError = true;
195            numHidlTransportErrors++;
196            if (numHidlTransportErrors > 50) {
197                // Log error and bail
198                ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
199                handleHidlDeath(ret.description());
200            } else {
201                std::this_thread::sleep_for(std::chrono::milliseconds(10));
202            }
203        }
204    } while (hidlTransportError);
205
206    if(numHidlTransportErrors > 0) {
207        ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
208        HidlTransportErrorLog errLog(time(NULL), numHidlTransportErrors);
209        mHidlTransportErrors.add(errLog);
210        mTotalHidlTransportErrors++;
211    }
212
213    return err;
214}
215
216void SensorDevice::autoDisable(void *ident, int handle) {
217    Info& info( mActivationCount.editValueFor(handle) );
218    Mutex::Autolock _l(mLock);
219    info.removeBatchParamsForIdent(ident);
220}
221
222status_t SensorDevice::activate(void* ident, int handle, int enabled) {
223    if (mSensors == nullptr) return NO_INIT;
224
225    status_t err(NO_ERROR);
226    bool actuateHardware = false;
227
228    Mutex::Autolock _l(mLock);
229    Info& info( mActivationCount.editValueFor(handle) );
230
231    ALOGD_IF(DEBUG_CONNECTIONS,
232             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
233             ident, handle, enabled, info.batchParams.size());
234
235    if (enabled) {
236        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
237
238        if (isClientDisabledLocked(ident)) {
239            ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
240                    ident, handle);
241            return INVALID_OPERATION;
242        }
243
244        if (info.batchParams.indexOfKey(ident) >= 0) {
245          if (info.numActiveClients() == 1) {
246              // This is the first connection, we need to activate the underlying h/w sensor.
247              actuateHardware = true;
248          }
249        } else {
250            // Log error. Every activate call should be preceded by a batch() call.
251            ALOGE("\t >>>ERROR: activate called without batch");
252        }
253    } else {
254        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
255
256        // If a connected dynamic sensor is deactivated, remove it from the
257        // dictionary.
258        auto it = mConnectedDynamicSensors.find(handle);
259        if (it != mConnectedDynamicSensors.end()) {
260            delete it->second;
261            mConnectedDynamicSensors.erase(it);
262        }
263
264        if (info.removeBatchParamsForIdent(ident) >= 0) {
265            if (info.numActiveClients() == 0) {
266                // This is the last connection, we need to de-activate the underlying h/w sensor.
267                actuateHardware = true;
268            } else {
269                // Call batch for this sensor with the previously calculated best effort
270                // batch_rate and timeout. One of the apps has unregistered for sensor
271                // events, and the best effort batch parameters might have changed.
272                ALOGD_IF(DEBUG_CONNECTIONS,
273                         "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64, handle,
274                         info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
275                checkReturn(mSensors->batch(
276                        handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
277            }
278        } else {
279            // sensor wasn't enabled for this ident
280        }
281
282        if (isClientDisabledLocked(ident)) {
283            return NO_ERROR;
284        }
285    }
286
287    if (actuateHardware) {
288        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
289                 enabled);
290        err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
291        ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
292                 strerror(-err));
293
294        if (err != NO_ERROR && enabled) {
295            // Failure when enabling the sensor. Clean up on failure.
296            info.removeBatchParamsForIdent(ident);
297        }
298    }
299
300    return err;
301}
302
303status_t SensorDevice::batch(
304        void* ident,
305        int handle,
306        int flags,
307        int64_t samplingPeriodNs,
308        int64_t maxBatchReportLatencyNs) {
309    if (mSensors == nullptr) return NO_INIT;
310
311    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
312        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
313    }
314    if (maxBatchReportLatencyNs < 0) {
315        maxBatchReportLatencyNs = 0;
316    }
317
318    ALOGD_IF(DEBUG_CONNECTIONS,
319             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
320             ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
321
322    Mutex::Autolock _l(mLock);
323    Info& info(mActivationCount.editValueFor(handle));
324
325    if (info.batchParams.indexOfKey(ident) < 0) {
326        BatchParams params(samplingPeriodNs, maxBatchReportLatencyNs);
327        info.batchParams.add(ident, params);
328    } else {
329        // A batch has already been called with this ident. Update the batch parameters.
330        info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
331    }
332
333    BatchParams prevBestBatchParams = info.bestBatchParams;
334    // Find the minimum of all timeouts and batch_rates for this sensor.
335    info.selectBatchParams();
336
337    ALOGD_IF(DEBUG_CONNECTIONS,
338             "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
339             " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
340             prevBestBatchParams.mTSample, info.bestBatchParams.mTSample,
341             prevBestBatchParams.mTBatch, info.bestBatchParams.mTBatch);
342
343    status_t err(NO_ERROR);
344    // If the min period or min timeout has changed since the last batch call, call batch.
345    if (prevBestBatchParams != info.bestBatchParams) {
346        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
347                 info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
348        err = StatusFromResult(
349                checkReturn(mSensors->batch(
350                    handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
351        if (err != NO_ERROR) {
352            ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
353                  mSensors.get(), handle, info.bestBatchParams.mTSample,
354                  info.bestBatchParams.mTBatch, strerror(-err));
355            info.removeBatchParamsForIdent(ident);
356        }
357    }
358    return err;
359}
360
361status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
362    return batch(ident, handle, 0, samplingPeriodNs, 0);
363}
364
365int SensorDevice::getHalDeviceVersion() const {
366    if (mSensors == nullptr) return -1;
367    return SENSORS_DEVICE_API_VERSION_1_4;
368}
369
370status_t SensorDevice::flush(void* ident, int handle) {
371    if (mSensors == nullptr) return NO_INIT;
372    if (isClientDisabled(ident)) return INVALID_OPERATION;
373    ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
374    return StatusFromResult(checkReturn(mSensors->flush(handle)));
375}
376
377bool SensorDevice::isClientDisabled(void* ident) {
378    Mutex::Autolock _l(mLock);
379    return isClientDisabledLocked(ident);
380}
381
382bool SensorDevice::isClientDisabledLocked(void* ident) {
383    return mDisabledClients.indexOf(ident) >= 0;
384}
385
386void SensorDevice::enableAllSensors() {
387    if (mSensors == nullptr) return;
388    Mutex::Autolock _l(mLock);
389    mDisabledClients.clear();
390    ALOGI("cleared mDisabledClients");
391    for (size_t i = 0; i< mActivationCount.size(); ++i) {
392        Info& info = mActivationCount.editValueAt(i);
393        if (info.batchParams.isEmpty()) continue;
394        info.selectBatchParams();
395        const int sensor_handle = mActivationCount.keyAt(i);
396        ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
397                   sensor_handle);
398        status_t err = StatusFromResult(
399                checkReturn(mSensors->batch(
400                    sensor_handle,
401                    info.bestBatchParams.mTSample,
402                    info.bestBatchParams.mTBatch)));
403        ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
404
405        if (err == NO_ERROR) {
406            err = StatusFromResult(
407                    checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
408            ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
409        }
410    }
411}
412
413void SensorDevice::disableAllSensors() {
414    if (mSensors == nullptr) return;
415    Mutex::Autolock _l(mLock);
416    for (size_t i = 0; i< mActivationCount.size(); ++i) {
417        const Info& info = mActivationCount.valueAt(i);
418        // Check if this sensor has been activated previously and disable it.
419        if (info.batchParams.size() > 0) {
420           const int sensor_handle = mActivationCount.keyAt(i);
421           ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
422                   sensor_handle);
423           checkReturn(mSensors->activate(sensor_handle, 0 /* enabled */));
424
425           // Add all the connections that were registered for this sensor to the disabled
426           // clients list.
427           for (size_t j = 0; j < info.batchParams.size(); ++j) {
428               mDisabledClients.add(info.batchParams.keyAt(j));
429               ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
430           }
431        }
432    }
433}
434
435status_t SensorDevice::injectSensorData(
436        const sensors_event_t *injected_sensor_event) {
437    if (mSensors == nullptr) return NO_INIT;
438    ALOGD_IF(DEBUG_CONNECTIONS,
439            "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
440            injected_sensor_event->sensor,
441            injected_sensor_event->timestamp, injected_sensor_event->data[0],
442            injected_sensor_event->data[1], injected_sensor_event->data[2],
443            injected_sensor_event->data[3], injected_sensor_event->data[4],
444            injected_sensor_event->data[5]);
445
446    Event ev;
447    convertFromSensorEvent(*injected_sensor_event, &ev);
448
449    return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
450}
451
452status_t SensorDevice::setMode(uint32_t mode) {
453    if (mSensors == nullptr) return NO_INIT;
454    return StatusFromResult(
455            checkReturn(mSensors->setOperationMode(
456                    static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
457}
458
459int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
460    if (mSensors == nullptr) return NO_INIT;
461    Mutex::Autolock _l(mLock);
462
463    SharedMemType type;
464    switch (memory->type) {
465        case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
466            type = SharedMemType::ASHMEM;
467            break;
468        case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
469            type = SharedMemType::GRALLOC;
470            break;
471        default:
472            return BAD_VALUE;
473    }
474
475    SharedMemFormat format;
476    if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
477        return BAD_VALUE;
478    }
479    format = SharedMemFormat::SENSORS_EVENT;
480
481    SharedMemInfo mem = {
482        .type = type,
483        .format = format,
484        .size = static_cast<uint32_t>(memory->size),
485        .memoryHandle = memory->handle,
486    };
487
488    int32_t ret;
489    checkReturn(mSensors->registerDirectChannel(mem,
490            [&ret](auto result, auto channelHandle) {
491                if (result == Result::OK) {
492                    ret = channelHandle;
493                } else {
494                    ret = StatusFromResult(result);
495                }
496            }));
497    return ret;
498}
499
500void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
501    if (mSensors == nullptr) return;
502    Mutex::Autolock _l(mLock);
503    checkReturn(mSensors->unregisterDirectChannel(channelHandle));
504}
505
506int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
507        int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
508    if (mSensors == nullptr) return NO_INIT;
509    Mutex::Autolock _l(mLock);
510
511    RateLevel rate;
512    switch(config->rate_level) {
513        case SENSOR_DIRECT_RATE_STOP:
514            rate = RateLevel::STOP;
515            break;
516        case SENSOR_DIRECT_RATE_NORMAL:
517            rate = RateLevel::NORMAL;
518            break;
519        case SENSOR_DIRECT_RATE_FAST:
520            rate = RateLevel::FAST;
521            break;
522        case SENSOR_DIRECT_RATE_VERY_FAST:
523            rate = RateLevel::VERY_FAST;
524            break;
525        default:
526            return BAD_VALUE;
527    }
528
529    int32_t ret;
530    checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
531            [&ret, rate] (auto result, auto token) {
532                if (rate == RateLevel::STOP) {
533                    ret = StatusFromResult(result);
534                } else {
535                    if (result == Result::OK) {
536                        ret = token;
537                    } else {
538                        ret = StatusFromResult(result);
539                    }
540                }
541            }));
542
543    return ret;
544}
545
546// ---------------------------------------------------------------------------
547
548int SensorDevice::Info::numActiveClients() {
549    SensorDevice& device(SensorDevice::getInstance());
550    int num = 0;
551    for (size_t i = 0; i < batchParams.size(); ++i) {
552        if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
553            ++num;
554        }
555    }
556    return num;
557}
558
559status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int,
560                                                    int64_t samplingPeriodNs,
561                                                    int64_t maxBatchReportLatencyNs) {
562    ssize_t index = batchParams.indexOfKey(ident);
563    if (index < 0) {
564        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64
565              " timeout=%" PRId64 ") failed (%s)",
566              ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
567        return BAD_INDEX;
568    }
569    BatchParams& params = batchParams.editValueAt(index);
570    params.mTSample = samplingPeriodNs;
571    params.mTBatch = maxBatchReportLatencyNs;
572    return NO_ERROR;
573}
574
575void SensorDevice::Info::selectBatchParams() {
576    BatchParams bestParams; // default to max Tsample and max Tbatch
577    SensorDevice& device(SensorDevice::getInstance());
578
579    for (size_t i = 0; i < batchParams.size(); ++i) {
580        if (device.isClientDisabledLocked(batchParams.keyAt(i))) {
581            continue;
582        }
583        bestParams.merge(batchParams[i]);
584    }
585    // if mTBatch <= mTSample, it is in streaming mode. set mTbatch to 0 to demand this explicitly.
586    if (bestParams.mTBatch <= bestParams.mTSample) {
587        bestParams.mTBatch = 0;
588    }
589    bestBatchParams = bestParams;
590}
591
592ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
593    ssize_t idx = batchParams.removeItem(ident);
594    if (idx >= 0) {
595        selectBatchParams();
596    }
597    return idx;
598}
599
600void SensorDevice::notifyConnectionDestroyed(void* ident) {
601    Mutex::Autolock _l(mLock);
602    mDisabledClients.remove(ident);
603}
604
605bool SensorDevice::isDirectReportSupported() const {
606    return mIsDirectReportSupported;
607}
608
609void SensorDevice::convertToSensorEvent(
610        const Event &src, sensors_event_t *dst) {
611    ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
612            src, dst);
613
614    if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
615        const DynamicSensorInfo &dyn = src.u.dynamic;
616
617        dst->dynamic_sensor_meta.connected = dyn.connected;
618        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
619        if (dyn.connected) {
620            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
621            CHECK(it != mConnectedDynamicSensors.end());
622
623            dst->dynamic_sensor_meta.sensor = it->second;
624
625            memcpy(dst->dynamic_sensor_meta.uuid,
626                   dyn.uuid.data(),
627                   sizeof(dst->dynamic_sensor_meta.uuid));
628        }
629    }
630}
631
632void SensorDevice::convertToSensorEvents(
633        const hidl_vec<Event> &src,
634        const hidl_vec<SensorInfo> &dynamicSensorsAdded,
635        sensors_event_t *dst) {
636    // Allocate a sensor_t structure for each dynamic sensor added and insert
637    // it into the dictionary of connected dynamic sensors keyed by handle.
638    for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
639        const SensorInfo &info = dynamicSensorsAdded[i];
640
641        auto it = mConnectedDynamicSensors.find(info.sensorHandle);
642        CHECK(it == mConnectedDynamicSensors.end());
643
644        sensor_t *sensor = new sensor_t;
645        convertToSensor(info, sensor);
646
647        mConnectedDynamicSensors.insert(
648                std::make_pair(sensor->handle, sensor));
649    }
650
651    for (size_t i = 0; i < src.size(); ++i) {
652        convertToSensorEvent(src[i], &dst[i]);
653    }
654}
655
656void SensorDevice::handleHidlDeath(const std::string & detail) {
657    // restart is the only option at present.
658    LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
659}
660
661// ---------------------------------------------------------------------------
662}; // namespace android
663