Home | History | Annotate | Download | only in nanotool
      1 /*
      2  * Copyright (C) 2016 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 "contexthub.h"
     18 
     19 #include <cstring>
     20 #include <errno.h>
     21 #include <vector>
     22 
     23 #include "apptohostevent.h"
     24 #include "log.h"
     25 #include "resetreasonevent.h"
     26 #include "sensorevent.h"
     27 #include "util.h"
     28 
     29 namespace android {
     30 
     31 #define UNUSED_PARAM(param) (void) (param)
     32 
     33 constexpr int kCalibrationTimeoutMs(10000);
     34 constexpr int kTestTimeoutMs(10000);
     35 constexpr int kBridgeVersionTimeoutMs(500);
     36 
     37 struct SensorTypeNames {
     38     SensorType sensor_type;
     39     const char *name_abbrev;
     40 };
     41 
     42 static const SensorTypeNames sensor_names_[] = {
     43     { SensorType::Accel,                "accel" },
     44     { SensorType::AnyMotion,            "anymo" },
     45     { SensorType::NoMotion,             "nomo" },
     46     { SensorType::SignificantMotion,    "sigmo" },
     47     { SensorType::Flat,                 "flat" },
     48     { SensorType::Gyro,                 "gyro" },
     49     //{ SensorType::GyroUncal,            "gyro_uncal" },
     50     { SensorType::Magnetometer,         "mag" },
     51     //{ SensorType::MagnetometerUncal,    "mag_uncal" },
     52     { SensorType::Barometer,            "baro" },
     53     { SensorType::Temperature,          "temp" },
     54     { SensorType::AmbientLightSensor,   "als" },
     55     { SensorType::Proximity,            "prox" },
     56     { SensorType::Orientation,          "orien" },
     57     //{ SensorType::HeartRateECG,         "ecg" },
     58     //{ SensorType::HeartRatePPG,         "ppg" },
     59     { SensorType::Gravity,              "gravity" },
     60     { SensorType::LinearAccel,          "linear_acc" },
     61     { SensorType::RotationVector,       "rotation" },
     62     { SensorType::GeomagneticRotationVector, "geomag" },
     63     { SensorType::GameRotationVector,   "game" },
     64     { SensorType::StepCount,            "step_cnt" },
     65     { SensorType::StepDetect,           "step_det" },
     66     { SensorType::Gesture,              "gesture" },
     67     { SensorType::Tilt,                 "tilt" },
     68     { SensorType::DoubleTwist,          "twist" },
     69     { SensorType::DoubleTap,            "doubletap" },
     70     { SensorType::WindowOrientation,    "win_orien" },
     71     { SensorType::Hall,                 "hall" },
     72     { SensorType::Activity,             "activity" },
     73     { SensorType::Vsync,                "vsync" },
     74     { SensorType::WristTilt,            "wrist_tilt" },
     75     { SensorType::Humidity,             "humidity" },
     76 };
     77 
     78 struct SensorTypeAlias {
     79     SensorType sensor_type;
     80     SensorType sensor_alias;
     81     const char *name_abbrev;
     82 };
     83 
     84 static const SensorTypeAlias sensor_aliases_[] = {
     85     { SensorType::Accel, SensorType::CompressedAccel, "compressed_accel" },
     86 };
     87 
     88 bool SensorTypeIsAliasOf(SensorType sensor_type, SensorType alias) {
     89     for (size_t i = 0; i < ARRAY_LEN(sensor_aliases_); i++) {
     90         if (sensor_aliases_[i].sensor_type == sensor_type
     91                 && sensor_aliases_[i].sensor_alias == alias) {
     92             return true;
     93         }
     94     }
     95 
     96     return false;
     97 }
     98 
     99 SensorType ContextHub::SensorAbbrevNameToType(const char *sensor_name_abbrev) {
    100     for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
    101         if (strcmp(sensor_names_[i].name_abbrev, sensor_name_abbrev) == 0) {
    102             return sensor_names_[i].sensor_type;
    103         }
    104     }
    105 
    106     return SensorType::Invalid_;
    107 }
    108 
    109 SensorType ContextHub::SensorAbbrevNameToType(const std::string& abbrev_name) {
    110     return ContextHub::SensorAbbrevNameToType(abbrev_name.c_str());
    111 }
    112 
    113 std::string ContextHub::SensorTypeToAbbrevName(SensorType sensor_type) {
    114     for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
    115         if (sensor_names_[i].sensor_type == sensor_type) {
    116             return std::string(sensor_names_[i].name_abbrev);
    117         }
    118     }
    119 
    120     for (unsigned int i = 0; i < ARRAY_LEN(sensor_aliases_); i++) {
    121         if (sensor_aliases_[i].sensor_alias == sensor_type) {
    122             return std::string(sensor_aliases_[i].name_abbrev);
    123         }
    124     }
    125 
    126     char buffer[24];
    127     snprintf(buffer, sizeof(buffer), "unknown (%d)",
    128              static_cast<int>(sensor_type));
    129     return std::string(buffer);
    130 }
    131 
    132 std::string ContextHub::ListAllSensorAbbrevNames() {
    133     std::string sensor_list;
    134     for (unsigned int i = 0; i < ARRAY_LEN(sensor_names_); i++) {
    135         sensor_list += sensor_names_[i].name_abbrev;
    136         if (i < ARRAY_LEN(sensor_names_) - 1) {
    137             sensor_list += ", ";
    138         }
    139     }
    140 
    141     return sensor_list;
    142 }
    143 
    144 bool ContextHub::Flash(const std::string& filename) {
    145     FILE *firmware_file = fopen(filename.c_str(), "r");
    146     if (!firmware_file) {
    147         LOGE("Failed to open firmware image: %d (%s)", errno, strerror(errno));
    148         return false;
    149     }
    150 
    151     fseek(firmware_file, 0, SEEK_END);
    152     long file_size = ftell(firmware_file);
    153     fseek(firmware_file, 0, SEEK_SET);
    154 
    155     auto firmware_data = std::vector<uint8_t>(file_size);
    156     size_t bytes_read = fread(firmware_data.data(), sizeof(uint8_t),
    157         file_size, firmware_file);
    158     fclose(firmware_file);
    159 
    160     if (bytes_read != static_cast<size_t>(file_size)) {
    161         LOGE("Read of firmware file returned %zu, expected %ld",
    162             bytes_read, file_size);
    163         return false;
    164     }
    165     return FlashSensorHub(firmware_data);
    166 }
    167 
    168 bool ContextHub::CalibrateSensors(const std::vector<SensorSpec>& sensors) {
    169     bool success = ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
    170         return CalibrateSingleSensor(spec);
    171     });
    172 
    173     if (success) {
    174         success = SaveCalibration();
    175     }
    176     return success;
    177 }
    178 
    179 bool ContextHub::TestSensors(const std::vector<SensorSpec>& sensors) {
    180     bool success = ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
    181         return TestSingleSensor(spec);
    182     });
    183 
    184     return success;
    185 }
    186 
    187 bool ContextHub::EnableSensor(const SensorSpec& spec) {
    188     ConfigureSensorRequest req;
    189 
    190     req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
    191     req.config.sensor_type = static_cast<uint8_t>(spec.sensor_type);
    192     req.config.command = static_cast<uint8_t>(
    193         ConfigureSensorRequest::CommandType::Enable);
    194     if (spec.special_rate != SensorSpecialRate::None) {
    195         req.config.rate = static_cast<uint32_t>(spec.special_rate);
    196     } else {
    197         req.config.rate = ConfigureSensorRequest::FloatRateToFixedPoint(
    198             spec.rate_hz);
    199     }
    200     req.config.latency = spec.latency_ns;
    201 
    202     LOGI("Enabling sensor %d at rate %.0f Hz (special 0x%x) and latency %.2f ms",
    203          spec.sensor_type, spec.rate_hz, spec.special_rate,
    204          spec.latency_ns / 1000000.0f);
    205     auto result = WriteEvent(req);
    206     if (result == TransportResult::Success) {
    207         sensor_is_active_[static_cast<int>(spec.sensor_type)] = true;
    208         return true;
    209     }
    210 
    211     LOGE("Could not enable sensor %d", spec.sensor_type);
    212     return false;
    213 }
    214 
    215 bool ContextHub::EnableSensors(const std::vector<SensorSpec>& sensors) {
    216     return ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
    217         return EnableSensor(spec);
    218     });
    219 }
    220 
    221 bool ContextHub::DisableSensor(SensorType sensor_type) {
    222     ConfigureSensorRequest req;
    223 
    224     req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
    225     req.config.sensor_type = static_cast<uint8_t>(sensor_type);
    226     req.config.command = static_cast<uint8_t>(
    227         ConfigureSensorRequest::CommandType::Disable);
    228 
    229     // Note that nanohub treats us as a single client, so if we call enable
    230     // twice then disable once, the sensor will be disabled
    231     LOGI("Disabling sensor %d", sensor_type);
    232     auto result = WriteEvent(req);
    233     if (result == TransportResult::Success) {
    234         sensor_is_active_[static_cast<int>(sensor_type)] = false;
    235         return true;
    236     }
    237 
    238     LOGE("Could not disable sensor %d", sensor_type);
    239     return false;
    240 }
    241 
    242 bool ContextHub::DisableSensors(const std::vector<SensorSpec>& sensors) {
    243     return ForEachSensor(sensors, [this](const SensorSpec &spec) -> bool {
    244         return DisableSensor(spec.sensor_type);
    245     });
    246 }
    247 
    248 bool ContextHub::DisableAllSensors() {
    249     bool success = true;
    250 
    251     for (size_t i = 0; i < ARRAY_LEN(sensor_names_); i++) {
    252         success &= DisableSensor(sensor_names_[i].sensor_type);
    253     }
    254 
    255     return success;
    256 }
    257 
    258 bool ContextHub::DisableActiveSensors() {
    259     bool success = true;
    260 
    261     LOGD("Disabling all active sensors");
    262     for (size_t i = 0; i < ARRAY_LEN(sensor_names_); i++) {
    263         if (sensor_is_active_[static_cast<int>(sensor_names_[i].sensor_type)]) {
    264             success &= DisableSensor(sensor_names_[i].sensor_type);
    265         }
    266     }
    267 
    268     return success;
    269 }
    270 
    271 void ContextHub::PrintAllEvents(unsigned int limit) {
    272     bool continuous = (limit == 0);
    273     auto event_printer = [&limit, continuous](const SensorEvent& event) -> bool {
    274         printf("%s", event.ToString().c_str());
    275         return (continuous || --limit > 0);
    276     };
    277     ReadSensorEvents(event_printer);
    278 }
    279 
    280 bool ContextHub::PrintBridgeVersion() {
    281     BridgeVersionInfoRequest request;
    282     TransportResult result = WriteEvent(request);
    283     if (result != TransportResult::Success) {
    284         LOGE("Failed to send bridge version info request: %d",
    285              static_cast<int>(result));
    286         return false;
    287     }
    288 
    289     bool success = false;
    290     auto event_handler = [&success](const AppToHostEvent &event) -> bool {
    291         bool keep_going = true;
    292         auto rsp = reinterpret_cast<const BrHostEventData *>(event.GetDataPtr());
    293         if (event.GetAppId() != kAppIdBridge) {
    294             LOGD("Ignored event from unexpected app");
    295         } else if (event.GetDataLen() < sizeof(BrHostEventData)) {
    296             LOGE("Got short app to host event from bridge: length %u, expected "
    297                  "at least %zu", event.GetDataLen(), sizeof(BrHostEventData));
    298         } else if (rsp->msgId != BRIDGE_HOST_EVENT_MSG_VERSION_INFO) {
    299             LOGD("Ignored bridge event with unexpected message ID %u", rsp->msgId);
    300         } else if (rsp->status) {
    301             LOGE("Bridge version info request failed with status %u", rsp->status);
    302             keep_going = false;
    303         } else if (event.GetDataLen() < (sizeof(BrHostEventData) +
    304                                          sizeof(BrVersionInfoRsp))) {
    305             LOGE("Got successful version info response with short payload: "
    306                  "length %u, expected at least %zu", event.GetDataLen(),
    307                  (sizeof(BrHostEventData) + sizeof(BrVersionInfoRsp)));
    308             keep_going = false;
    309         } else {
    310             auto ver = reinterpret_cast<const struct BrVersionInfoRsp *>(
    311                 rsp->payload);
    312             printf("Bridge version info:\n"
    313                    "  HW type:         0x%04x\n"
    314                    "  OS version:      0x%04x\n"
    315                    "  Variant version: 0x%08x\n"
    316                    "  Bridge version:  0x%08x\n",
    317                    ver->hwType, ver->osVer, ver->variantVer, ver->bridgeVer);
    318             keep_going = false;
    319             success = true;
    320         }
    321 
    322         return keep_going;
    323     };
    324 
    325     ReadAppEvents(event_handler, kBridgeVersionTimeoutMs);
    326     return success;
    327 }
    328 
    329 void ContextHub::PrintSensorEvents(SensorType type, int limit) {
    330     bool continuous = (limit == 0);
    331     auto event_printer = [type, &limit, continuous](const SensorEvent& event) -> bool {
    332         SensorType event_source = event.GetSensorType();
    333         if (event_source == type || SensorTypeIsAliasOf(type, event_source)) {
    334             printf("%s", event.ToString().c_str());
    335             limit -= event.GetNumSamples();
    336         }
    337         return (continuous || limit > 0);
    338     };
    339     ReadSensorEvents(event_printer);
    340 }
    341 
    342 void ContextHub::PrintSensorEvents(const std::vector<SensorSpec>& sensors, int limit) {
    343     bool continuous = (limit == 0);
    344     auto event_printer = [&sensors, &limit, continuous](const SensorEvent& event) -> bool {
    345         SensorType event_source = event.GetSensorType();
    346         for (unsigned int i = 0; i < sensors.size(); i++) {
    347             if (sensors[i].sensor_type == event_source
    348                     || SensorTypeIsAliasOf(sensors[i].sensor_type, event_source)) {
    349                 printf("%s", event.ToString().c_str());
    350                 limit -= event.GetNumSamples();
    351                 break;
    352             }
    353         }
    354         return (continuous || limit > 0);
    355     };
    356     ReadSensorEvents(event_printer);
    357 }
    358 
    359 // Protected methods -----------------------------------------------------------
    360 
    361 bool ContextHub::CalibrateSingleSensor(const SensorSpec& sensor) {
    362     ConfigureSensorRequest req;
    363 
    364     req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
    365     req.config.sensor_type = static_cast<uint8_t>(sensor.sensor_type);
    366     req.config.command = static_cast<uint8_t>(
    367         ConfigureSensorRequest::CommandType::Calibrate);
    368 
    369     LOGI("Issuing calibration request to sensor %d (%s)", sensor.sensor_type,
    370          ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
    371     auto result = WriteEvent(req);
    372     if (result != TransportResult::Success) {
    373         LOGE("Failed to calibrate sensor %d", sensor.sensor_type);
    374         return false;
    375     }
    376 
    377     bool success = false;
    378     auto cal_event_handler = [this, &sensor, &success](const AppToHostEvent &event) -> bool {
    379         if (event.IsCalibrationEventForSensor(sensor.sensor_type)) {
    380             success = HandleCalibrationResult(sensor, event);
    381             return false;
    382         }
    383         return true;
    384     };
    385 
    386     result = ReadAppEvents(cal_event_handler, kCalibrationTimeoutMs);
    387     if (result != TransportResult::Success) {
    388       LOGE("Error reading calibration response %d", static_cast<int>(result));
    389       return false;
    390     }
    391 
    392     return success;
    393 }
    394 
    395 bool ContextHub::TestSingleSensor(const SensorSpec& sensor) {
    396     ConfigureSensorRequest req;
    397 
    398     req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
    399     req.config.sensor_type = static_cast<uint8_t>(sensor.sensor_type);
    400     req.config.command = static_cast<uint8_t>(
    401         ConfigureSensorRequest::CommandType::SelfTest);
    402 
    403     LOGI("Issuing test request to sensor %d (%s)", sensor.sensor_type,
    404          ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
    405     auto result = WriteEvent(req);
    406     if (result != TransportResult::Success) {
    407         LOGE("Failed to test sensor %d", sensor.sensor_type);
    408         return false;
    409     }
    410 
    411     bool success = false;
    412     auto test_event_handler = [this, &sensor, &success](const AppToHostEvent &event) -> bool {
    413         if (event.IsTestEventForSensor(sensor.sensor_type)) {
    414             success = HandleTestResult(sensor, event);
    415             return false;
    416         }
    417         return true;
    418     };
    419 
    420     result = ReadAppEvents(test_event_handler, kTestTimeoutMs);
    421     if (result != TransportResult::Success) {
    422       LOGE("Error reading test response %d", static_cast<int>(result));
    423       return false;
    424     }
    425 
    426     return success;
    427 }
    428 
    429 bool ContextHub::ForEachSensor(const std::vector<SensorSpec>& sensors,
    430         std::function<bool(const SensorSpec&)> callback) {
    431     bool success = true;
    432 
    433     for (unsigned int i = 0; success && i < sensors.size(); i++) {
    434         success &= callback(sensors[i]);
    435     }
    436 
    437     return success;
    438 }
    439 
    440 bool ContextHub::HandleCalibrationResult(const SensorSpec& sensor,
    441         const AppToHostEvent &event) {
    442     auto hdr = reinterpret_cast<const SensorAppEventHeader *>(event.GetDataPtr());
    443     if (hdr->status) {
    444         LOGE("Calibration of sensor %d (%s) failed with status %u",
    445              sensor.sensor_type,
    446              ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str(),
    447              hdr->status);
    448         return false;
    449     }
    450 
    451     bool success = false;
    452     switch (sensor.sensor_type) {
    453       case SensorType::Accel:
    454       case SensorType::Gyro: {
    455         auto result = reinterpret_cast<const TripleAxisCalibrationResult *>(
    456             event.GetDataPtr());
    457         success = SetCalibration(sensor.sensor_type, result->xBias,
    458                                  result->yBias, result->zBias);
    459         break;
    460       }
    461 
    462       case SensorType::Barometer: {
    463         auto result = reinterpret_cast<const FloatCalibrationResult *>(
    464             event.GetDataPtr());
    465         if (sensor.have_cal_ref) {
    466             success = SetCalibration(sensor.sensor_type,
    467                                      (sensor.cal_ref - result->value));
    468         }
    469         break;
    470       }
    471 
    472       case SensorType::Proximity: {
    473         auto result = reinterpret_cast<const FourAxisCalibrationResult *>(
    474             event.GetDataPtr());
    475         success = SetCalibration(sensor.sensor_type, result->xBias,
    476                                  result->yBias, result->zBias, result->wBias);
    477         break;
    478       }
    479 
    480       case SensorType::AmbientLightSensor: {
    481         auto result = reinterpret_cast<const FloatCalibrationResult *>(
    482             event.GetDataPtr());
    483         if (sensor.have_cal_ref && (result->value != 0.0f)) {
    484             success = SetCalibration(sensor.sensor_type,
    485                                      (sensor.cal_ref / result->value));
    486         }
    487         break;
    488       }
    489 
    490       default:
    491         LOGE("Calibration not supported for sensor type %d",
    492              static_cast<int>(sensor.sensor_type));
    493     }
    494 
    495     return success;
    496 }
    497 
    498 bool ContextHub::HandleTestResult(const SensorSpec& sensor,
    499         const AppToHostEvent &event) {
    500     auto hdr = reinterpret_cast<const SensorAppEventHeader *>(event.GetDataPtr());
    501     if (!hdr->status) {
    502         LOGI("Self-test of sensor %d (%s) succeeded",
    503              sensor.sensor_type,
    504              ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str());
    505         return true;
    506     } else {
    507         LOGE("Self-test of sensor %d (%s) failed with status %u",
    508              sensor.sensor_type,
    509              ContextHub::SensorTypeToAbbrevName(sensor.sensor_type).c_str(),
    510              hdr->status);
    511         return false;
    512     }
    513 }
    514 
    515 ContextHub::TransportResult ContextHub::ReadAppEvents(
    516         std::function<bool(const AppToHostEvent&)> callback, int timeout_ms) {
    517     using Milliseconds = std::chrono::milliseconds;
    518 
    519     TransportResult result;
    520     bool timeout_required = timeout_ms > 0;
    521     bool keep_going = true;
    522 
    523     while (keep_going) {
    524         if (timeout_required && timeout_ms <= 0) {
    525             return TransportResult::Timeout;
    526         }
    527 
    528         std::unique_ptr<ReadEventResponse> event;
    529 
    530         SteadyClock start_time = std::chrono::steady_clock::now();
    531         result = ReadEvent(&event, timeout_ms);
    532         SteadyClock end_time = std::chrono::steady_clock::now();
    533 
    534         auto delta = end_time - start_time;
    535         timeout_ms -= std::chrono::duration_cast<Milliseconds>(delta).count();
    536 
    537         if (result == TransportResult::Success && event->IsAppToHostEvent()) {
    538             AppToHostEvent *app_event = reinterpret_cast<AppToHostEvent*>(
    539                 event.get());
    540             keep_going = callback(*app_event);
    541         } else {
    542             if (result != TransportResult::Success) {
    543                 LOGE("Error %d while reading", static_cast<int>(result));
    544                 if (result != TransportResult::ParseFailure) {
    545                     return result;
    546                 }
    547             } else {
    548                 LOGD("Ignoring non-app-to-host event");
    549             }
    550         }
    551     }
    552 
    553     return TransportResult::Success;
    554 }
    555 
    556 void ContextHub::ReadSensorEvents(std::function<bool(const SensorEvent&)> callback) {
    557     TransportResult result;
    558     bool keep_going = true;
    559 
    560     while (keep_going) {
    561         std::unique_ptr<ReadEventResponse> event;
    562         result = ReadEvent(&event);
    563         if (result == TransportResult::Success && event->IsSensorEvent()) {
    564             SensorEvent *sensor_event = reinterpret_cast<SensorEvent*>(
    565                 event.get());
    566             keep_going = callback(*sensor_event);
    567         } else {
    568             if (result != TransportResult::Success) {
    569                 LOGE("Error %d while reading", static_cast<int>(result));
    570                 if (result != TransportResult::ParseFailure) {
    571                     break;
    572                 }
    573             } else {
    574                 LOGD("Ignoring non-sensor event");
    575             }
    576         }
    577     }
    578 }
    579 
    580 bool ContextHub::SendCalibrationData(SensorType sensor_type,
    581         const std::vector<uint8_t>& cal_data) {
    582     ConfigureSensorRequest req;
    583 
    584     req.config.event_type = static_cast<uint32_t>(EventType::ConfigureSensor);
    585     req.config.sensor_type = static_cast<uint8_t>(sensor_type);
    586     req.config.command = static_cast<uint8_t>(
    587         ConfigureSensorRequest::CommandType::ConfigData);
    588     req.SetAdditionalData(cal_data);
    589 
    590     auto result = WriteEvent(req);
    591     return (result == TransportResult::Success);
    592 }
    593 
    594 ContextHub::TransportResult ContextHub::WriteEvent(
    595         const WriteEventRequest& request) {
    596     return WriteEvent(request.GetBytes());
    597 }
    598 
    599 ContextHub::TransportResult ContextHub::ReadEvent(
    600         std::unique_ptr<ReadEventResponse>* response, int timeout_ms) {
    601     std::vector<uint8_t> responseBuf(256);
    602     ContextHub::TransportResult result = ReadEvent(responseBuf, timeout_ms);
    603     if (result == TransportResult::Success) {
    604         *response = ReadEventResponse::FromBytes(responseBuf);
    605         if (*response == nullptr) {
    606             result = TransportResult::ParseFailure;
    607         }
    608     }
    609     return result;
    610 }
    611 
    612 // Stubs for subclasses that don't implement calibration support
    613 bool ContextHub::LoadCalibration() {
    614     LOGE("Loading calibration data not implemented");
    615     return false;
    616 }
    617 
    618 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t data) {
    619     UNUSED_PARAM(sensor_type);
    620     UNUSED_PARAM(data);
    621     return false;
    622 }
    623 
    624 bool ContextHub::SetCalibration(SensorType sensor_type, float data) {
    625     UNUSED_PARAM(sensor_type);
    626     UNUSED_PARAM(data);
    627     return false;
    628 }
    629 
    630 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t x,
    631         int32_t y, int32_t z) {
    632     UNUSED_PARAM(sensor_type);
    633     UNUSED_PARAM(x);
    634     UNUSED_PARAM(y);
    635     UNUSED_PARAM(z);
    636     return false;
    637 }
    638 
    639 bool ContextHub::SetCalibration(SensorType sensor_type, int32_t x,
    640         int32_t y, int32_t z, int32_t w) {
    641     UNUSED_PARAM(sensor_type);
    642     UNUSED_PARAM(x);
    643     UNUSED_PARAM(y);
    644     UNUSED_PARAM(z);
    645     UNUSED_PARAM(w);
    646     return false;
    647 }
    648 
    649 bool ContextHub::SaveCalibration() {
    650     LOGE("Saving calibration data not implemented");
    651     return false;
    652 }
    653 
    654 }  // namespace android
    655