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