Home | History | Annotate | Download | only in sensorhal
      1 /*
      2  * Copyright (C) 2015 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 #define LOG_TAG "nanohub"
     18 #define LOG_NDEBUG 1
     19 
     20 #include "hubconnection.h"
     21 
     22 // TODO: remove the includes that introduce LIKELY and UNLIKELY (firmware/os/inc/toolchain.h)
     23 #undef LIKELY
     24 #undef UNLIKELY
     25 
     26 #include "file.h"
     27 #include "JSONObject.h"
     28 
     29 #include <errno.h>
     30 #include <unistd.h>
     31 #include <math.h>
     32 #include <inttypes.h>
     33 #include <sched.h>
     34 #include <sys/inotify.h>
     35 
     36 #include <linux/input.h>
     37 #include <linux/uinput.h>
     38 
     39 #include <android/frameworks/schedulerservice/1.0/ISchedulingPolicyService.h>
     40 #include <cutils/ashmem.h>
     41 #include <cutils/properties.h>
     42 #include <hardware_legacy/power.h>
     43 #include <media/stagefright/foundation/ADebug.h>
     44 #include <utils/Log.h>
     45 #include <utils/SystemClock.h>
     46 
     47 #include <algorithm>
     48 #include <cmath>
     49 #include <sstream>
     50 #include <vector>
     51 
     52 #define APP_ID_GET_VENDOR(appid)       ((appid) >> 24)
     53 #define APP_ID_MAKE(vendor, app)       ((((uint64_t)(vendor)) << 24) | ((app) & 0x00FFFFFF))
     54 #define APP_ID_VENDOR_GOOGLE           0x476f6f676cULL // "Googl"
     55 #define APP_ID_APP_BMI160              2
     56 
     57 #define SENS_TYPE_TO_EVENT(_sensorType) (EVT_NO_FIRST_SENSOR_EVENT + (_sensorType))
     58 
     59 #define NANOHUB_FILE_PATH       "/dev/nanohub"
     60 #define NANOHUB_LOCK_DIR        "/data/vendor/sensor/nanohub_lock"
     61 #define NANOHUB_LOCK_FILE       NANOHUB_LOCK_DIR "/lock"
     62 #define MAG_BIAS_FILE_PATH      "/sys/class/power_supply/battery/compass_compensation"
     63 #define DOUBLE_TOUCH_FILE_PATH  "/sys/android_touch/synaptics_rmi4_dsx/wake_event"
     64 
     65 #define NANOHUB_LOCK_DIR_PERMS  (S_IRUSR | S_IWUSR | S_IXUSR)
     66 
     67 #define SENSOR_RATE_ONCHANGE    0xFFFFFF01UL
     68 #define SENSOR_RATE_ONESHOT     0xFFFFFF02UL
     69 
     70 #define MIN_MAG_SQ              (10.0f * 10.0f)
     71 #define MAX_MAG_SQ              (80.0f * 80.0f)
     72 
     73 #define OS_LOG_EVENT            0x474F4C41  // ascii: ALOG
     74 
     75 #ifdef LID_STATE_REPORTING_ENABLED
     76 const char LID_STATE_PROPERTY[] = "sensors.contexthub.lid_state";
     77 const char LID_STATE_UNKNOWN[]  = "unknown";
     78 const char LID_STATE_OPEN[]     = "open";
     79 const char LID_STATE_CLOSED[]   = "closed";
     80 #endif  // LID_STATE_REPORTING_ENABLED
     81 
     82 static const uint32_t delta_time_encoded = 1;
     83 static const uint32_t delta_time_shift_table[2] = {9, 0};
     84 
     85 #ifdef USE_SENSORSERVICE_TO_GET_FIFO
     86 // TODO(b/35219747): retain sched_fifo before eval is done to avoid
     87 // performance regression.
     88 const char SCHED_FIFO_PRIOIRTY[] = "sensor.hubconnection.sched_fifo";
     89 #endif
     90 
     91 namespace android {
     92 
     93 // static
     94 Mutex HubConnection::sInstanceLock;
     95 
     96 // static
     97 HubConnection *HubConnection::sInstance = NULL;
     98 
     99 HubConnection *HubConnection::getInstance()
    100 {
    101     Mutex::Autolock autoLock(sInstanceLock);
    102     if (sInstance == NULL) {
    103         sInstance = new HubConnection;
    104     }
    105     return sInstance;
    106 }
    107 
    108 static bool isActivitySensor(int sensorIndex) {
    109     return sensorIndex >= COMMS_SENSOR_ACTIVITY_FIRST
    110         && sensorIndex <= COMMS_SENSOR_ACTIVITY_LAST;
    111 }
    112 
    113 HubConnection::HubConnection()
    114     : Thread(false /* canCallJava */),
    115       mRing(10 *1024),
    116       mActivityEventHandler(NULL),
    117       mScaleAccel(1.0f),
    118       mScaleMag(1.0f),
    119       mStepCounterOffset(0ull),
    120       mLastStepCount(0ull)
    121 {
    122     mMagBias[0] = mMagBias[1] = mMagBias[2] = 0.0f;
    123     mMagAccuracy = SENSOR_STATUS_UNRELIABLE;
    124     mMagAccuracyRestore = SENSOR_STATUS_UNRELIABLE;
    125     mGyroBias[0] = mGyroBias[1] = mGyroBias[2] = 0.0f;
    126     mAccelBias[0] = mAccelBias[1] = mAccelBias[2] = 0.0f;
    127     memset(&mGyroOtcData, 0, sizeof(mGyroOtcData));
    128 
    129     memset(&mSensorState, 0x00, sizeof(mSensorState));
    130     mFd = open(NANOHUB_FILE_PATH, O_RDWR);
    131     mPollFds[0].fd = mFd;
    132     mPollFds[0].events = POLLIN;
    133     mPollFds[0].revents = 0;
    134     mNumPollFds = 1;
    135 
    136     mWakelockHeld = false;
    137     mWakeEventCount = 0;
    138 
    139     initNanohubLock();
    140 
    141 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
    142     mUsbMagBias = 0;
    143     mMagBiasPollIndex = -1;
    144     int magBiasFd = open(MAG_BIAS_FILE_PATH, O_RDONLY);
    145     if (magBiasFd < 0) {
    146         ALOGW("Mag bias file open failed: %s", strerror(errno));
    147     } else {
    148         mPollFds[mNumPollFds].fd = magBiasFd;
    149         mPollFds[mNumPollFds].events = 0;
    150         mPollFds[mNumPollFds].revents = 0;
    151         mMagBiasPollIndex = mNumPollFds;
    152         mNumPollFds++;
    153     }
    154 #endif  // USB_MAG_BIAS_REPORTING_ENABLED
    155 
    156 #ifdef DOUBLE_TOUCH_ENABLED
    157     mDoubleTouchPollIndex = -1;
    158     int doubleTouchFd = open(DOUBLE_TOUCH_FILE_PATH, O_RDONLY);
    159     if (doubleTouchFd < 0) {
    160         ALOGW("Double touch file open failed: %s", strerror(errno));
    161     } else {
    162         mPollFds[mNumPollFds].fd = doubleTouchFd;
    163         mPollFds[mNumPollFds].events = 0;
    164         mPollFds[mNumPollFds].revents = 0;
    165         mDoubleTouchPollIndex = mNumPollFds;
    166         mNumPollFds++;
    167     }
    168 #endif  // DOUBLE_TOUCH_ENABLED
    169 
    170     mSensorState[COMMS_SENSOR_ACCEL].sensorType = SENS_TYPE_ACCEL;
    171     mSensorState[COMMS_SENSOR_ACCEL].alt = COMMS_SENSOR_ACCEL_UNCALIBRATED;
    172     mSensorState[COMMS_SENSOR_ACCEL_UNCALIBRATED].sensorType = SENS_TYPE_ACCEL;
    173     mSensorState[COMMS_SENSOR_ACCEL_UNCALIBRATED].alt = COMMS_SENSOR_ACCEL;
    174     mSensorState[COMMS_SENSOR_GYRO].sensorType = SENS_TYPE_GYRO;
    175     mSensorState[COMMS_SENSOR_GYRO].alt = COMMS_SENSOR_GYRO_UNCALIBRATED;
    176     mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].sensorType = SENS_TYPE_GYRO;
    177     mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].alt = COMMS_SENSOR_GYRO;
    178     mSensorState[COMMS_SENSOR_MAG].sensorType = SENS_TYPE_MAG;
    179     mSensorState[COMMS_SENSOR_MAG].alt = COMMS_SENSOR_MAG_UNCALIBRATED;
    180     mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].sensorType = SENS_TYPE_MAG;
    181     mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].alt = COMMS_SENSOR_MAG;
    182     mSensorState[COMMS_SENSOR_LIGHT].sensorType = SENS_TYPE_ALS;
    183     mSensorState[COMMS_SENSOR_PROXIMITY].sensorType = SENS_TYPE_PROX;
    184     mSensorState[COMMS_SENSOR_PRESSURE].sensorType = SENS_TYPE_BARO;
    185     mSensorState[COMMS_SENSOR_TEMPERATURE].sensorType = SENS_TYPE_TEMP;
    186     mSensorState[COMMS_SENSOR_ORIENTATION].sensorType = SENS_TYPE_ORIENTATION;
    187     mSensorState[COMMS_SENSOR_WINDOW_ORIENTATION].sensorType = SENS_TYPE_WIN_ORIENTATION;
    188     mSensorState[COMMS_SENSOR_WINDOW_ORIENTATION].rate = SENSOR_RATE_ONCHANGE;
    189     mSensorState[COMMS_SENSOR_STEP_DETECTOR].sensorType = SENS_TYPE_STEP_DETECT;
    190     mSensorState[COMMS_SENSOR_STEP_DETECTOR].rate = SENSOR_RATE_ONCHANGE;
    191     mSensorState[COMMS_SENSOR_STEP_COUNTER].sensorType = SENS_TYPE_STEP_COUNT;
    192     mSensorState[COMMS_SENSOR_SIGNIFICANT_MOTION].sensorType = SENS_TYPE_SIG_MOTION;
    193     mSensorState[COMMS_SENSOR_SIGNIFICANT_MOTION].rate = SENSOR_RATE_ONESHOT;
    194     mSensorState[COMMS_SENSOR_GRAVITY].sensorType = SENS_TYPE_GRAVITY;
    195     mSensorState[COMMS_SENSOR_LINEAR_ACCEL].sensorType = SENS_TYPE_LINEAR_ACCEL;
    196     mSensorState[COMMS_SENSOR_ROTATION_VECTOR].sensorType = SENS_TYPE_ROTATION_VECTOR;
    197     mSensorState[COMMS_SENSOR_GEO_MAG].sensorType = SENS_TYPE_GEO_MAG_ROT_VEC;
    198     mSensorState[COMMS_SENSOR_GAME_ROTATION_VECTOR].sensorType = SENS_TYPE_GAME_ROT_VECTOR;
    199     mSensorState[COMMS_SENSOR_HALL].sensorType = SENS_TYPE_HALL;
    200     mSensorState[COMMS_SENSOR_HALL].rate = SENSOR_RATE_ONCHANGE;
    201     mSensorState[COMMS_SENSOR_SYNC].sensorType = SENS_TYPE_VSYNC;
    202     mSensorState[COMMS_SENSOR_SYNC].rate = SENSOR_RATE_ONCHANGE;
    203     mSensorState[COMMS_SENSOR_TILT].sensorType = SENS_TYPE_TILT;
    204     mSensorState[COMMS_SENSOR_TILT].rate = SENSOR_RATE_ONCHANGE;
    205     mSensorState[COMMS_SENSOR_GESTURE].sensorType = SENS_TYPE_GESTURE;
    206     mSensorState[COMMS_SENSOR_GESTURE].rate = SENSOR_RATE_ONESHOT;
    207     mSensorState[COMMS_SENSOR_DOUBLE_TWIST].sensorType = SENS_TYPE_DOUBLE_TWIST;
    208     mSensorState[COMMS_SENSOR_DOUBLE_TWIST].rate = SENSOR_RATE_ONCHANGE;
    209     mSensorState[COMMS_SENSOR_DOUBLE_TAP].sensorType = SENS_TYPE_DOUBLE_TAP;
    210     mSensorState[COMMS_SENSOR_DOUBLE_TAP].rate = SENSOR_RATE_ONCHANGE;
    211     mSensorState[COMMS_SENSOR_WRIST_TILT].sensorType = SENS_TYPE_WRIST_TILT;
    212     mSensorState[COMMS_SENSOR_WRIST_TILT].rate = SENSOR_RATE_ONCHANGE;
    213     mSensorState[COMMS_SENSOR_DOUBLE_TOUCH].sensorType = SENS_TYPE_DOUBLE_TOUCH;
    214     mSensorState[COMMS_SENSOR_DOUBLE_TOUCH].rate = SENSOR_RATE_ONESHOT;
    215     mSensorState[COMMS_SENSOR_ACTIVITY_IN_VEHICLE_START].sensorType = SENS_TYPE_ACTIVITY_IN_VEHICLE_START;
    216     mSensorState[COMMS_SENSOR_ACTIVITY_IN_VEHICLE_START].rate = SENSOR_RATE_ONCHANGE;
    217     mSensorState[COMMS_SENSOR_ACTIVITY_IN_VEHICLE_STOP].sensorType = SENS_TYPE_ACTIVITY_IN_VEHICLE_STOP;
    218     mSensorState[COMMS_SENSOR_ACTIVITY_IN_VEHICLE_STOP].rate = SENSOR_RATE_ONCHANGE;
    219     mSensorState[COMMS_SENSOR_ACTIVITY_ON_BICYCLE_START].sensorType = SENS_TYPE_ACTIVITY_ON_BICYCLE_START;
    220     mSensorState[COMMS_SENSOR_ACTIVITY_ON_BICYCLE_START].rate = SENSOR_RATE_ONCHANGE;
    221     mSensorState[COMMS_SENSOR_ACTIVITY_ON_BICYCLE_STOP].sensorType = SENS_TYPE_ACTIVITY_ON_BICYCLE_STOP;
    222     mSensorState[COMMS_SENSOR_ACTIVITY_ON_BICYCLE_STOP].rate = SENSOR_RATE_ONCHANGE;
    223     mSensorState[COMMS_SENSOR_ACTIVITY_WALKING_START].sensorType = SENS_TYPE_ACTIVITY_WALKING_START;
    224     mSensorState[COMMS_SENSOR_ACTIVITY_WALKING_START].rate = SENSOR_RATE_ONCHANGE;
    225     mSensorState[COMMS_SENSOR_ACTIVITY_WALKING_STOP].sensorType = SENS_TYPE_ACTIVITY_WALKING_STOP;
    226     mSensorState[COMMS_SENSOR_ACTIVITY_WALKING_STOP].rate = SENSOR_RATE_ONCHANGE;
    227     mSensorState[COMMS_SENSOR_ACTIVITY_RUNNING_START].sensorType = SENS_TYPE_ACTIVITY_RUNNING_START;
    228     mSensorState[COMMS_SENSOR_ACTIVITY_RUNNING_START].rate = SENSOR_RATE_ONCHANGE;
    229     mSensorState[COMMS_SENSOR_ACTIVITY_RUNNING_STOP].sensorType = SENS_TYPE_ACTIVITY_RUNNING_STOP;
    230     mSensorState[COMMS_SENSOR_ACTIVITY_RUNNING_STOP].rate = SENSOR_RATE_ONCHANGE;
    231     mSensorState[COMMS_SENSOR_ACTIVITY_STILL_START].sensorType = SENS_TYPE_ACTIVITY_STILL_START;
    232     mSensorState[COMMS_SENSOR_ACTIVITY_STILL_START].rate = SENSOR_RATE_ONCHANGE;
    233     mSensorState[COMMS_SENSOR_ACTIVITY_STILL_STOP].sensorType = SENS_TYPE_ACTIVITY_STILL_STOP;
    234     mSensorState[COMMS_SENSOR_ACTIVITY_STILL_STOP].rate = SENSOR_RATE_ONCHANGE;
    235     mSensorState[COMMS_SENSOR_ACTIVITY_TILTING].sensorType = SENS_TYPE_ACTIVITY_TILTING;
    236     mSensorState[COMMS_SENSOR_ACTIVITY_TILTING].rate = SENSOR_RATE_ONCHANGE;
    237     mSensorState[COMMS_SENSOR_GAZE].sensorType = SENS_TYPE_GAZE;
    238     mSensorState[COMMS_SENSOR_GAZE].rate = SENSOR_RATE_ONESHOT;
    239     mSensorState[COMMS_SENSOR_UNGAZE].sensorType = SENS_TYPE_UNGAZE;
    240     mSensorState[COMMS_SENSOR_UNGAZE].rate = SENSOR_RATE_ONESHOT;
    241     mSensorState[COMMS_SENSOR_HUMIDITY].sensorType = SENS_TYPE_HUMIDITY;
    242 
    243 #ifdef LID_STATE_REPORTING_ENABLED
    244     initializeUinputNode();
    245 
    246     // set initial lid state
    247     if (property_set(LID_STATE_PROPERTY, LID_STATE_UNKNOWN) < 0) {
    248         ALOGW("could not set lid_state property");
    249     }
    250 
    251     // enable hall sensor for folio
    252     if (mFd >= 0) {
    253         queueActivate(COMMS_SENSOR_HALL, true /* enable */);
    254     }
    255 #endif  // LID_STATE_REPORTING_ENABLED
    256 
    257 #ifdef DIRECT_REPORT_ENABLED
    258     mDirectChannelHandle = 1;
    259     mSensorToChannel.emplace(COMMS_SENSOR_ACCEL, std::unordered_map<int32_t, int32_t>());
    260     mSensorToChannel.emplace(COMMS_SENSOR_GYRO, std::unordered_map<int32_t, int32_t>());
    261     mSensorToChannel.emplace(COMMS_SENSOR_MAG, std::unordered_map<int32_t, int32_t>());
    262 #endif // DIRECT_REPORT_ENABLED
    263 }
    264 
    265 HubConnection::~HubConnection()
    266 {
    267     close(mFd);
    268 }
    269 
    270 void HubConnection::onFirstRef()
    271 {
    272     run("HubConnection", PRIORITY_URGENT_DISPLAY);
    273 #ifdef USE_SENSORSERVICE_TO_GET_FIFO
    274     if (property_get_bool(SCHED_FIFO_PRIOIRTY, true)) {
    275         ALOGV("Try activate sched-fifo priority for HubConnection thread");
    276         mEnableSchedFifoThread = std::thread(enableSchedFifoMode, this);
    277     }
    278 #else
    279     enableSchedFifoMode(this);
    280 #endif
    281 }
    282 
    283 // Set main thread to SCHED_FIFO to lower sensor event latency when system is under load
    284 void HubConnection::enableSchedFifoMode(sp<HubConnection> hub) {
    285 #ifdef USE_SENSORSERVICE_TO_GET_FIFO
    286     using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService;
    287     using ::android::hardware::Return;
    288 
    289     // SchedulingPolicyService will not start until system server start.
    290     // Thus, cannot block on this.
    291     sp<ISchedulingPolicyService> scheduler = ISchedulingPolicyService::getService();
    292 
    293     if (scheduler == nullptr) {
    294         ALOGW("Couldn't get scheduler scheduler to set SCHED_FIFO.");
    295     } else {
    296         Return<int32_t> max = scheduler->getMaxAllowedPriority();
    297         if (!max.isOk()) {
    298             ALOGW("Failed to retrieve maximum allowed priority for HubConnection.");
    299             return;
    300         }
    301         Return<bool> ret = scheduler->requestPriority(::getpid(), hub->getTid(), max);
    302         if (!ret.isOk() || !ret) {
    303             ALOGW("Failed to set SCHED_FIFO for HubConnection.");
    304         } else {
    305             ALOGV("Enabled sched fifo thread mode (prio %d)", static_cast<int32_t>(max));
    306         }
    307     }
    308 #else
    309 #define HUBCONNECTION_SCHED_FIFO_PRIORITY 10
    310     struct sched_param param = {0};
    311     param.sched_priority = HUBCONNECTION_SCHED_FIFO_PRIORITY;
    312     if (sched_setscheduler(hub->getTid(), SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
    313         ALOGW("Couldn't set SCHED_FIFO for HubConnection thread");
    314     }
    315 #endif
    316 }
    317 
    318 status_t HubConnection::initCheck() const
    319 {
    320     return mFd < 0 ? UNKNOWN_ERROR : OK;
    321 }
    322 
    323 status_t HubConnection::getAliveCheck()
    324 {
    325     return OK;
    326 }
    327 
    328 static sp<JSONObject> readSettings(File *file) {
    329     off64_t size = file->seekTo(0, SEEK_END);
    330     file->seekTo(0, SEEK_SET);
    331 
    332     sp<JSONObject> root;
    333 
    334     if (size > 0) {
    335         char *buf = (char *)malloc(size);
    336         CHECK_EQ(file->read(buf, size), (ssize_t)size);
    337         file->seekTo(0, SEEK_SET);
    338 
    339         sp<JSONCompound> in = JSONCompound::Parse(buf, size);
    340         free(buf);
    341         buf = NULL;
    342 
    343         if (in != NULL && in->isObject()) {
    344             root = (JSONObject *)in.get();
    345         }
    346     }
    347 
    348     if (root == NULL) {
    349         root = new JSONObject;
    350     }
    351 
    352     return root;
    353 }
    354 
    355 static bool getCalibrationInt32(
    356         const sp<JSONObject> &settings, const char *key, int32_t *out,
    357         size_t numArgs) {
    358     sp<JSONArray> array;
    359     for (size_t i = 0; i < numArgs; i++) {
    360         out[i] = 0;
    361     }
    362     if (!settings->getArray(key, &array)) {
    363         return false;
    364     } else {
    365         for (size_t i = 0; i < numArgs; i++) {
    366             if (!array->getInt32(i, &out[i])) {
    367                 return false;
    368             }
    369         }
    370     }
    371     return true;
    372 }
    373 
    374 static bool getCalibrationFloat(
    375         const sp<JSONObject> &settings, const char *key, float out[3]) {
    376     sp<JSONArray> array;
    377     for (size_t i = 0; i < 3; i++) {
    378         out[i] = 0.0f;
    379     }
    380     if (!settings->getArray(key, &array)) {
    381         return false;
    382     } else {
    383         for (size_t i = 0; i < 3; i++) {
    384             if (!array->getFloat(i, &out[i])) {
    385                 return false;
    386             }
    387         }
    388     }
    389     return true;
    390 }
    391 
    392 static std::vector<int32_t> getInt32Setting(const sp<JSONObject> &settings, const char *key) {
    393     std::vector<int32_t> ret;
    394 
    395     sp<JSONArray> array;
    396     if (settings->getArray(key, &array)) {
    397         ret.resize(array->size());
    398         for (size_t i = 0; i < array->size(); ++i) {
    399             array->getInt32(i, &ret[i]);
    400         }
    401     }
    402     return ret;
    403 }
    404 
    405 static std::vector<float> getFloatSetting(const sp<JSONObject> &settings, const char *key) {
    406     std::vector<float> ret;
    407 
    408     sp<JSONArray> array;
    409     if (settings->getArray(key, &array)) {
    410         ret.resize(array->size());
    411         for (size_t i = 0; i < array->size(); ++i) {
    412             array->getFloat(i, &ret[i]);
    413         }
    414     }
    415     return ret;
    416 }
    417 
    418 static void loadSensorSettings(sp<JSONObject>* settings,
    419                                sp<JSONObject>* saved_settings) {
    420     File settings_file(CONTEXTHUB_SETTINGS_PATH, "r");
    421     File saved_settings_file(CONTEXTHUB_SAVED_SETTINGS_PATH, "r");
    422 
    423     status_t err;
    424     if ((err = settings_file.initCheck()) != OK) {
    425         ALOGW("settings file open failed: %d (%s)",
    426               err,
    427               strerror(-err));
    428 
    429         *settings = new JSONObject;
    430     } else {
    431         *settings = readSettings(&settings_file);
    432     }
    433 
    434     if ((err = saved_settings_file.initCheck()) != OK) {
    435         ALOGW("saved settings file open failed: %d (%s)",
    436               err,
    437               strerror(-err));
    438         *saved_settings = new JSONObject;
    439     } else {
    440         *saved_settings = readSettings(&saved_settings_file);
    441     }
    442 }
    443 
    444 void HubConnection::saveSensorSettings() const {
    445     File saved_settings_file(CONTEXTHUB_SAVED_SETTINGS_PATH, "w");
    446     sp<JSONObject> settingsObject = new JSONObject;
    447 
    448     status_t err;
    449     if ((err = saved_settings_file.initCheck()) != OK) {
    450         ALOGW("saved settings file open failed %d (%s)",
    451               err,
    452               strerror(-err));
    453         return;
    454     }
    455 
    456     // Build a settings object.
    457     sp<JSONArray> magArray = new JSONArray;
    458 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
    459     magArray->addFloat(mMagBias[0] + mUsbMagBias);
    460 #else
    461     magArray->addFloat(mMagBias[0]);
    462 #endif  // USB_MAG_BIAS_REPORTING_ENABLED
    463     magArray->addFloat(mMagBias[1]);
    464     magArray->addFloat(mMagBias[2]);
    465     settingsObject->setArray(MAG_BIAS_TAG, magArray);
    466 
    467     // Add gyro settings
    468     sp<JSONArray> gyroArray = new JSONArray;
    469     gyroArray->addFloat(mGyroBias[0]);
    470     gyroArray->addFloat(mGyroBias[1]);
    471     gyroArray->addFloat(mGyroBias[2]);
    472     settingsObject->setArray(GYRO_SW_BIAS_TAG, gyroArray);
    473 
    474     // Add accel settings
    475     sp<JSONArray> accelArray = new JSONArray;
    476     accelArray->addFloat(mAccelBias[0]);
    477     accelArray->addFloat(mAccelBias[1]);
    478     accelArray->addFloat(mAccelBias[2]);
    479     settingsObject->setArray(ACCEL_SW_BIAS_TAG, accelArray);
    480 
    481     // Add overtemp calibration values for gyro
    482     sp<JSONArray> gyroOtcDataArray = new JSONArray;
    483     const float *f;
    484     size_t i;
    485     for (f = reinterpret_cast<const float *>(&mGyroOtcData), i = 0;
    486             i < sizeof(mGyroOtcData)/sizeof(float); ++i, ++f) {
    487         gyroOtcDataArray->addFloat(*f);
    488     }
    489     settingsObject->setArray(GYRO_OTC_DATA_TAG, gyroOtcDataArray);
    490 
    491     // Write the JSON string to disk.
    492     AString serializedSettings = settingsObject->toString();
    493     size_t size = serializedSettings.size();
    494     if ((err = saved_settings_file.write(serializedSettings.c_str(), size)) != (ssize_t)size) {
    495         ALOGW("saved settings file write failed %d (%s)",
    496               err,
    497               strerror(-err));
    498     }
    499 }
    500 
    501 sensors_event_t *HubConnection::initEv(sensors_event_t *ev, uint64_t timestamp, uint32_t type, uint32_t sensor)
    502 {
    503     memset(ev, 0x00, sizeof(sensors_event_t));
    504     ev->version = sizeof(sensors_event_t);
    505     ev->timestamp = timestamp;
    506     ev->type = type;
    507     ev->sensor = sensor;
    508 
    509     return ev;
    510 }
    511 
    512 ssize_t HubConnection::getWakeEventCount()
    513 {
    514     return mWakeEventCount;
    515 }
    516 
    517 ssize_t HubConnection::decrementWakeEventCount()
    518 {
    519     return --mWakeEventCount;
    520 }
    521 
    522 bool HubConnection::isWakeEvent(int32_t sensor)
    523 {
    524     switch (sensor) {
    525     case COMMS_SENSOR_PROXIMITY:
    526     case COMMS_SENSOR_SIGNIFICANT_MOTION:
    527     case COMMS_SENSOR_TILT:
    528     case COMMS_SENSOR_DOUBLE_TWIST:
    529     case COMMS_SENSOR_GESTURE:
    530         return true;
    531     default:
    532         return false;
    533     }
    534 }
    535 
    536 void HubConnection::protectIfWakeEvent(int32_t sensor)
    537 {
    538     if (isWakeEvent(sensor)) {
    539         if (mWakelockHeld == false) {
    540             acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKELOCK_NAME);
    541             mWakelockHeld = true;
    542         }
    543         mWakeEventCount++;
    544     }
    545 }
    546 
    547 void HubConnection::releaseWakeLockIfAppropriate()
    548 {
    549     if (mWakelockHeld && (mWakeEventCount == 0)) {
    550         mWakelockHeld = false;
    551         release_wake_lock(WAKELOCK_NAME);
    552     }
    553 }
    554 
    555 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct OneAxisSample *sample, __attribute__((unused)) bool highAccuracy)
    556 {
    557     sensors_event_t nev[1];
    558     int cnt = 0;
    559 
    560     switch (sensor) {
    561     case COMMS_SENSOR_ACTIVITY_IN_VEHICLE_START:
    562     case COMMS_SENSOR_ACTIVITY_IN_VEHICLE_STOP:
    563     case COMMS_SENSOR_ACTIVITY_ON_BICYCLE_START:
    564     case COMMS_SENSOR_ACTIVITY_ON_BICYCLE_STOP:
    565     case COMMS_SENSOR_ACTIVITY_WALKING_START:
    566     case COMMS_SENSOR_ACTIVITY_WALKING_STOP:
    567     case COMMS_SENSOR_ACTIVITY_RUNNING_START:
    568     case COMMS_SENSOR_ACTIVITY_RUNNING_STOP:
    569     case COMMS_SENSOR_ACTIVITY_STILL_START:
    570     case COMMS_SENSOR_ACTIVITY_STILL_STOP:
    571     case COMMS_SENSOR_ACTIVITY_TILTING:
    572         if (mActivityEventHandler != NULL) {
    573             mActivityEventHandler->OnActivityEvent(sensor, sample->idata & 0xff,
    574                                                    timestamp);
    575         }
    576         break;
    577     case COMMS_SENSOR_PRESSURE:
    578         initEv(&nev[cnt++], timestamp, type, sensor)->pressure = sample->fdata;
    579         break;
    580     case COMMS_SENSOR_HUMIDITY:
    581         initEv(&nev[cnt++], timestamp, type, sensor)->relative_humidity = sample->fdata;
    582         break;
    583     case COMMS_SENSOR_TEMPERATURE:
    584         initEv(&nev[cnt++], timestamp, type, sensor)->temperature = sample->fdata;
    585         break;
    586     case COMMS_SENSOR_PROXIMITY:
    587         initEv(&nev[cnt++], timestamp, type, sensor)->distance = sample->fdata;
    588         break;
    589     case COMMS_SENSOR_LIGHT:
    590         initEv(&nev[cnt++], timestamp, type, sensor)->light = sample->fdata;
    591         break;
    592     case COMMS_SENSOR_STEP_COUNTER:
    593         // We'll stash away the last step count in case we need to reset
    594         // the hub. This last step count would then become the new offset.
    595         mLastStepCount = mStepCounterOffset + sample->idata;
    596         initEv(&nev[cnt++], timestamp, type, sensor)->u64.step_counter = mLastStepCount;
    597         break;
    598     case COMMS_SENSOR_STEP_DETECTOR:
    599     case COMMS_SENSOR_SIGNIFICANT_MOTION:
    600     case COMMS_SENSOR_TILT:
    601     case COMMS_SENSOR_DOUBLE_TWIST:
    602     case COMMS_SENSOR_WRIST_TILT:
    603         initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = 1.0f;
    604         break;
    605     case COMMS_SENSOR_GAZE:
    606     case COMMS_SENSOR_UNGAZE:
    607     case COMMS_SENSOR_GESTURE:
    608     case COMMS_SENSOR_SYNC:
    609     case COMMS_SENSOR_DOUBLE_TOUCH:
    610         initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = sample->idata;
    611         break;
    612     case COMMS_SENSOR_HALL:
    613 #ifdef LID_STATE_REPORTING_ENABLED
    614         sendFolioEvent(sample->idata);
    615 #endif  // LID_STATE_REPORTING_ENABLED
    616         break;
    617     case COMMS_SENSOR_WINDOW_ORIENTATION:
    618         initEv(&nev[cnt++], timestamp, type, sensor)->data[0] = sample->idata;
    619         break;
    620     default:
    621         break;
    622     }
    623 
    624     if (cnt > 0) {
    625         // If event is a wake event, protect it with a wakelock
    626         protectIfWakeEvent(sensor);
    627         write(nev, cnt);
    628     }
    629 }
    630 
    631 uint8_t HubConnection::magAccuracyUpdate(sensors_vec_t *sv)
    632 {
    633     float magSq = sv->x * sv->x + sv->y * sv->y + sv->z * sv->z;
    634 
    635     if (magSq < MIN_MAG_SQ || magSq > MAX_MAG_SQ) {
    636         // save last good accuracy (either MEDIUM or HIGH)
    637         if (mMagAccuracy != SENSOR_STATUS_UNRELIABLE)
    638             mMagAccuracyRestore = mMagAccuracy;
    639         mMagAccuracy = SENSOR_STATUS_UNRELIABLE;
    640     } else if (mMagAccuracy == SENSOR_STATUS_UNRELIABLE) {
    641         // restore
    642         mMagAccuracy = mMagAccuracyRestore;
    643     }
    644 
    645     return mMagAccuracy;
    646 }
    647 
    648 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct RawThreeAxisSample *sample, __attribute__((unused)) bool highAccuracy)
    649 {
    650     sensors_vec_t *sv;
    651     uncalibrated_event_t *ue;
    652     sensors_event_t nev[2];
    653     int cnt = 0;
    654 
    655     switch (sensor) {
    656     case COMMS_SENSOR_ACCEL:
    657         sv = &initEv(&nev[cnt], timestamp, type, sensor)->acceleration;
    658         sv->x = sample->ix * mScaleAccel;
    659         sv->y = sample->iy * mScaleAccel;
    660         sv->z = sample->iz * mScaleAccel;
    661         sv->status = SENSOR_STATUS_ACCURACY_HIGH;
    662         sendDirectReportEvent(&nev[cnt], 1);
    663 
    664         if (mSensorState[sensor].enable) {
    665             ++cnt;
    666         }
    667 
    668         if (mSensorState[COMMS_SENSOR_ACCEL_UNCALIBRATED].enable) {
    669             ue = &initEv(&nev[cnt++], timestamp,
    670                 SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED,
    671                 COMMS_SENSOR_ACCEL_UNCALIBRATED)->uncalibrated_accelerometer;
    672             ue->x_uncalib = sample->ix * mScaleAccel + mAccelBias[0];
    673             ue->y_uncalib = sample->iy * mScaleAccel + mAccelBias[1];
    674             ue->z_uncalib = sample->iz * mScaleAccel + mAccelBias[2];
    675             ue->x_bias = mAccelBias[0];
    676             ue->y_bias = mAccelBias[1];
    677             ue->z_bias = mAccelBias[2];
    678         }
    679         break;
    680     case COMMS_SENSOR_MAG:
    681         sv = &initEv(&nev[cnt], timestamp, type, sensor)->magnetic;
    682         sv->x = sample->ix * mScaleMag;
    683         sv->y = sample->iy * mScaleMag;
    684         sv->z = sample->iz * mScaleMag;
    685         sv->status = magAccuracyUpdate(sv);
    686         sendDirectReportEvent(&nev[cnt], 1);
    687 
    688         if (mSensorState[sensor].enable) {
    689             ++cnt;
    690         }
    691 
    692         if (mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].enable) {
    693             ue = &initEv(&nev[cnt++], timestamp,
    694                 SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
    695                 COMMS_SENSOR_MAG_UNCALIBRATED)->uncalibrated_magnetic;
    696             ue->x_uncalib = sample->ix * mScaleMag + mMagBias[0];
    697             ue->y_uncalib = sample->iy * mScaleMag + mMagBias[1];
    698             ue->z_uncalib = sample->iz * mScaleMag + mMagBias[2];
    699             ue->x_bias = mMagBias[0];
    700             ue->y_bias = mMagBias[1];
    701             ue->z_bias = mMagBias[2];
    702         }
    703     default:
    704         break;
    705     }
    706 
    707     if (cnt > 0) {
    708         // If event is a wake event, protect it with a wakelock
    709         protectIfWakeEvent(sensor);
    710         write(nev, cnt);
    711     }
    712 }
    713 
    714 void HubConnection::processSample(uint64_t timestamp, uint32_t type, uint32_t sensor, struct ThreeAxisSample *sample, bool highAccuracy)
    715 {
    716     sensors_vec_t *sv;
    717     uncalibrated_event_t *ue;
    718     sensors_event_t *ev;
    719     sensors_event_t nev[2];
    720     static const float heading_accuracy = M_PI / 6.0f;
    721     float w;
    722     int cnt = 0;
    723 
    724     switch (sensor) {
    725     case COMMS_SENSOR_ACCEL:
    726         sv = &initEv(&nev[cnt], timestamp, type, sensor)->acceleration;
    727         sv->x = sample->x;
    728         sv->y = sample->y;
    729         sv->z = sample->z;
    730         sv->status = SENSOR_STATUS_ACCURACY_HIGH;
    731         sendDirectReportEvent(&nev[cnt], 1);
    732 
    733         if (mSensorState[sensor].enable) {
    734             ++cnt;
    735         }
    736 
    737         if (mSensorState[COMMS_SENSOR_ACCEL_UNCALIBRATED].enable) {
    738             ue = &initEv(&nev[cnt++], timestamp,
    739                 SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED,
    740                 COMMS_SENSOR_ACCEL_UNCALIBRATED)->uncalibrated_accelerometer;
    741             ue->x_uncalib = sample->x + mAccelBias[0];
    742             ue->y_uncalib = sample->y + mAccelBias[1];
    743             ue->z_uncalib = sample->z + mAccelBias[2];
    744             ue->x_bias = mAccelBias[0];
    745             ue->y_bias = mAccelBias[1];
    746             ue->z_bias = mAccelBias[2];
    747         }
    748         break;
    749     case COMMS_SENSOR_GYRO:
    750         sv = &initEv(&nev[cnt], timestamp, type, sensor)->gyro;
    751         sv->x = sample->x;
    752         sv->y = sample->y;
    753         sv->z = sample->z;
    754         sv->status = SENSOR_STATUS_ACCURACY_HIGH;
    755         sendDirectReportEvent(&nev[cnt], 1);
    756 
    757         if (mSensorState[sensor].enable) {
    758             ++cnt;
    759         }
    760 
    761         if (mSensorState[COMMS_SENSOR_GYRO_UNCALIBRATED].enable) {
    762             ue = &initEv(&nev[cnt++], timestamp,
    763                 SENSOR_TYPE_GYROSCOPE_UNCALIBRATED,
    764                 COMMS_SENSOR_GYRO_UNCALIBRATED)->uncalibrated_gyro;
    765             ue->x_uncalib = sample->x + mGyroBias[0];
    766             ue->y_uncalib = sample->y + mGyroBias[1];
    767             ue->z_uncalib = sample->z + mGyroBias[2];
    768             ue->x_bias = mGyroBias[0];
    769             ue->y_bias = mGyroBias[1];
    770             ue->z_bias = mGyroBias[2];
    771         }
    772         break;
    773     case COMMS_SENSOR_ACCEL_BIAS:
    774         mAccelBias[0] = sample->x;
    775         mAccelBias[1] = sample->y;
    776         mAccelBias[2] = sample->z;
    777         saveSensorSettings();
    778         break;
    779     case COMMS_SENSOR_GYRO_BIAS:
    780         mGyroBias[0] = sample->x;
    781         mGyroBias[1] = sample->y;
    782         mGyroBias[2] = sample->z;
    783         saveSensorSettings();
    784         break;
    785     case COMMS_SENSOR_MAG:
    786         sv = &initEv(&nev[cnt], timestamp, type, sensor)->magnetic;
    787         sv->x = sample->x;
    788         sv->y = sample->y;
    789         sv->z = sample->z;
    790         sv->status = magAccuracyUpdate(sv);
    791         sendDirectReportEvent(&nev[cnt], 1);
    792 
    793         if (mSensorState[sensor].enable) {
    794             ++cnt;
    795         }
    796 
    797         if (mSensorState[COMMS_SENSOR_MAG_UNCALIBRATED].enable) {
    798             ue = &initEv(&nev[cnt++], timestamp,
    799                 SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
    800                 COMMS_SENSOR_MAG_UNCALIBRATED)->uncalibrated_magnetic;
    801             ue->x_uncalib = sample->x + mMagBias[0];
    802             ue->y_uncalib = sample->y + mMagBias[1];
    803             ue->z_uncalib = sample->z + mMagBias[2];
    804             ue->x_bias = mMagBias[0];
    805             ue->y_bias = mMagBias[1];
    806             ue->z_bias = mMagBias[2];
    807         }
    808         break;
    809     case COMMS_SENSOR_MAG_BIAS:
    810         mMagAccuracy = highAccuracy ? SENSOR_STATUS_ACCURACY_HIGH : SENSOR_STATUS_ACCURACY_MEDIUM;
    811         mMagBias[0] = sample->x;
    812         mMagBias[1] = sample->y;
    813         mMagBias[2] = sample->z;
    814 
    815         saveSensorSettings();
    816         break;
    817     case COMMS_SENSOR_ORIENTATION:
    818     case COMMS_SENSOR_LINEAR_ACCEL:
    819     case COMMS_SENSOR_GRAVITY:
    820         sv = &initEv(&nev[cnt++], timestamp, type, sensor)->orientation;
    821         sv->x = sample->x;
    822         sv->y = sample->y;
    823         sv->z = sample->z;
    824         sv->status = mMagAccuracy;
    825         break;
    826     case COMMS_SENSOR_DOUBLE_TAP:
    827         ev = initEv(&nev[cnt++], timestamp, type, sensor);
    828         ev->data[0] = sample->x;
    829         ev->data[1] = sample->y;
    830         ev->data[2] = sample->z;
    831         break;
    832     case COMMS_SENSOR_ROTATION_VECTOR:
    833         ev = initEv(&nev[cnt++], timestamp, type, sensor);
    834         w = sample->x * sample->x + sample->y * sample->y + sample->z * sample->z;
    835         if (w < 1.0f)
    836             w = sqrt(1.0f - w);
    837         else
    838             w = 0.0f;
    839         ev->data[0] = sample->x;
    840         ev->data[1] = sample->y;
    841         ev->data[2] = sample->z;
    842         ev->data[3] = w;
    843         ev->data[4] = (4 - mMagAccuracy) * heading_accuracy;
    844         break;
    845     case COMMS_SENSOR_GEO_MAG:
    846     case COMMS_SENSOR_GAME_ROTATION_VECTOR:
    847         ev = initEv(&nev[cnt++], timestamp, type, sensor);
    848         w = sample->x * sample->x + sample->y * sample->y + sample->z * sample->z;
    849         if (w < 1.0f)
    850             w = sqrt(1.0f - w);
    851         else
    852             w = 0.0f;
    853         ev->data[0] = sample->x;
    854         ev->data[1] = sample->y;
    855         ev->data[2] = sample->z;
    856         ev->data[3] = w;
    857         break;
    858     default:
    859         break;
    860     }
    861 
    862     if (cnt > 0) {
    863         // If event is a wake event, protect it with a wakelock
    864         protectIfWakeEvent(sensor);
    865         write(nev, cnt);
    866     }
    867 }
    868 
    869 void HubConnection::discardInotifyEvent() {
    870     // Read & discard an inotify event. We only use the presence of an event as
    871     // a trigger to perform the file existence check (for simplicity)
    872     if (mInotifyPollIndex >= 0) {
    873         char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
    874         int ret = ::read(mPollFds[mInotifyPollIndex].fd, buf, sizeof(buf));
    875         ALOGV("Discarded %d bytes of inotify data", ret);
    876     }
    877 }
    878 
    879 void HubConnection::waitOnNanohubLock() {
    880     if (mInotifyPollIndex < 0) {
    881         return;
    882     }
    883     struct pollfd *pfd = &mPollFds[mInotifyPollIndex];
    884 
    885     // While the lock file exists, poll on the inotify fd (with timeout)
    886     while (access(NANOHUB_LOCK_FILE, F_OK) == 0) {
    887         ALOGW("Nanohub is locked; blocking read thread");
    888         int ret = poll(pfd, 1, 5000);
    889         if ((ret > 0) && (pfd->revents & POLLIN)) {
    890             discardInotifyEvent();
    891         }
    892     }
    893 }
    894 
    895 void HubConnection::restoreSensorState()
    896 {
    897     Mutex::Autolock autoLock(mLock);
    898 
    899     sendCalibrationOffsets();
    900 
    901     for (int i = 0; i < NUM_COMMS_SENSORS_PLUS_1; i++) {
    902         if (mSensorState[i].sensorType && mSensorState[i].enable) {
    903             struct ConfigCmd cmd;
    904 
    905             initConfigCmd(&cmd, i);
    906 
    907             ALOGV("restoring: sensor=%d, handle=%d, enable=%d, period=%" PRId64 ", latency=%" PRId64,
    908                   cmd.sensorType, i, mSensorState[i].enable, frequency_q10_to_period_ns(mSensorState[i].rate),
    909                   mSensorState[i].latency);
    910 
    911             int ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
    912             if (ret != sizeof(cmd)) {
    913                 ALOGW("failed to send config command to restore sensor %d\n", cmd.sensorType);
    914             }
    915 
    916             cmd.cmd = CONFIG_CMD_FLUSH;
    917 
    918             for (int j = 0; j < mSensorState[i].flushCnt; j++) {
    919                 int ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
    920                 if (ret != sizeof(cmd)) {
    921                     ALOGW("failed to send flush command to sensor %d\n", cmd.sensorType);
    922                 }
    923             }
    924         }
    925     }
    926 
    927     mStepCounterOffset = mLastStepCount;
    928 
    929     if (mActivityEventHandler != NULL) {
    930         mActivityEventHandler->OnSensorHubReset();
    931     }
    932 }
    933 
    934 void HubConnection::postOsLog(uint8_t *buf, ssize_t len)
    935 {
    936     // if len is less than 6, it's either an invalid or an empty log message.
    937     if (len < 6)
    938         return;
    939 
    940     buf[len] = 0x00;
    941     switch (buf[4]) {
    942     case 'E':
    943         ALOGE("osLog: %s", &buf[5]);
    944         break;
    945     case 'W':
    946         ALOGW("osLog: %s", &buf[5]);
    947         break;
    948     case 'I':
    949         // The other side of this is too chatty, reducing the priority to VERBOSE
    950         ALOGV("osLog: %s", &buf[5]);
    951         break;
    952     case 'D':
    953         // The other side of this is too chatty, reducing the priority to VERBOSE
    954         ALOGV("osLog: %s", &buf[5]);
    955         break;
    956     default:
    957         break;
    958     }
    959 }
    960 
    961 void HubConnection::processAppData(uint8_t *buf, ssize_t len) {
    962     if (len < static_cast<ssize_t>(sizeof(AppToSensorHalDataBuffer)))
    963         return;
    964 
    965     AppToSensorHalDataPayload *data =
    966             &(reinterpret_cast<AppToSensorHalDataBuffer *>(buf)->payload);
    967     if (data->size + sizeof(AppToSensorHalDataBuffer) != len) {
    968         ALOGW("Received corrupted data update packet, len %zd, size %u", len, data->size);
    969         return;
    970     }
    971 
    972     switch (data->type & APP_TO_SENSOR_HAL_TYPE_MASK) {
    973     case HALINTF_TYPE_GYRO_OTC_DATA:
    974         if (data->size != sizeof(GyroOtcData)) {
    975             ALOGW("Corrupted HALINTF_TYPE_GYRO_OTC_DATA with size %u", data->size);
    976             return;
    977         }
    978         mGyroOtcData = data->gyroOtcData[0];
    979         saveSensorSettings();
    980         break;
    981     default:
    982         ALOGW("Unknown app to hal data type 0x%04x", data->type);
    983         break;
    984     }
    985 }
    986 
    987 ssize_t HubConnection::processBuf(uint8_t *buf, size_t len)
    988 {
    989     struct nAxisEvent *data = (struct nAxisEvent *)buf;
    990     uint32_t type, sensor, bias, currSensor;
    991     int i, numSamples;
    992     bool one, rawThree, three;
    993     sensors_event_t ev;
    994     uint64_t timestamp;
    995     ssize_t ret = 0;
    996 
    997     if (len >= sizeof(data->evtType)) {
    998         ret = sizeof(data->evtType);
    999         one = three = rawThree = false;
   1000         bias = 0;
   1001         switch (data->evtType) {
   1002         case OS_LOG_EVENT:
   1003             postOsLog(buf, len);
   1004             return 0;
   1005         case EVT_APP_TO_SENSOR_HAL_DATA:
   1006             processAppData(buf, len);
   1007             return 0;
   1008         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACCEL):
   1009             type = SENSOR_TYPE_ACCELEROMETER;
   1010             sensor = COMMS_SENSOR_ACCEL;
   1011             bias = COMMS_SENSOR_ACCEL_BIAS;
   1012             three = true;
   1013             break;
   1014         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACCEL_RAW):
   1015             type = SENSOR_TYPE_ACCELEROMETER;
   1016             sensor = COMMS_SENSOR_ACCEL;
   1017             rawThree = true;
   1018             break;
   1019         case SENS_TYPE_TO_EVENT(SENS_TYPE_GYRO):
   1020             type = SENSOR_TYPE_GYROSCOPE;
   1021             sensor = COMMS_SENSOR_GYRO;
   1022             bias = COMMS_SENSOR_GYRO_BIAS;
   1023             three = true;
   1024             break;
   1025         case SENS_TYPE_TO_EVENT(SENS_TYPE_MAG):
   1026             type = SENSOR_TYPE_MAGNETIC_FIELD;
   1027             sensor = COMMS_SENSOR_MAG;
   1028             bias = COMMS_SENSOR_MAG_BIAS;
   1029             three = true;
   1030             break;
   1031         case SENS_TYPE_TO_EVENT(SENS_TYPE_MAG_RAW):
   1032             type = SENSOR_TYPE_MAGNETIC_FIELD;
   1033             sensor = COMMS_SENSOR_MAG;
   1034             rawThree = true;
   1035             break;
   1036         case SENS_TYPE_TO_EVENT(SENS_TYPE_ALS):
   1037             type = SENSOR_TYPE_LIGHT;
   1038             sensor = COMMS_SENSOR_LIGHT;
   1039             one = true;
   1040             break;
   1041         case SENS_TYPE_TO_EVENT(SENS_TYPE_PROX):
   1042             type = SENSOR_TYPE_PROXIMITY;
   1043             sensor = COMMS_SENSOR_PROXIMITY;
   1044             one = true;
   1045             break;
   1046         case SENS_TYPE_TO_EVENT(SENS_TYPE_BARO):
   1047             type = SENSOR_TYPE_PRESSURE;
   1048             sensor = COMMS_SENSOR_PRESSURE;
   1049             one = true;
   1050             break;
   1051         case SENS_TYPE_TO_EVENT(SENS_TYPE_HUMIDITY):
   1052             type = SENSOR_TYPE_RELATIVE_HUMIDITY;
   1053             sensor = COMMS_SENSOR_HUMIDITY;
   1054             one = true;
   1055             break;
   1056         case SENS_TYPE_TO_EVENT(SENS_TYPE_TEMP):
   1057             // nanohub only has one temperature sensor type, which is mapped to
   1058             // internal temp because we currently don't have ambient temp
   1059             type = SENSOR_TYPE_INTERNAL_TEMPERATURE;
   1060             sensor = COMMS_SENSOR_TEMPERATURE;
   1061             one = true;
   1062             break;
   1063         case SENS_TYPE_TO_EVENT(SENS_TYPE_ORIENTATION):
   1064             type = SENSOR_TYPE_ORIENTATION;
   1065             sensor = COMMS_SENSOR_ORIENTATION;
   1066             three = true;
   1067             break;
   1068         case SENS_TYPE_TO_EVENT(SENS_TYPE_WIN_ORIENTATION):
   1069             type = SENSOR_TYPE_DEVICE_ORIENTATION;
   1070             sensor = COMMS_SENSOR_WINDOW_ORIENTATION;
   1071             one = true;
   1072             break;
   1073         case SENS_TYPE_TO_EVENT(SENS_TYPE_STEP_DETECT):
   1074             type = SENSOR_TYPE_STEP_DETECTOR;
   1075             sensor = COMMS_SENSOR_STEP_DETECTOR;
   1076             one = true;
   1077             break;
   1078         case SENS_TYPE_TO_EVENT(SENS_TYPE_STEP_COUNT):
   1079             type = SENSOR_TYPE_STEP_COUNTER;
   1080             sensor = COMMS_SENSOR_STEP_COUNTER;
   1081             one = true;
   1082             break;
   1083         case SENS_TYPE_TO_EVENT(SENS_TYPE_SIG_MOTION):
   1084             type = SENSOR_TYPE_SIGNIFICANT_MOTION;
   1085             sensor = COMMS_SENSOR_SIGNIFICANT_MOTION;
   1086             one = true;
   1087             break;
   1088         case SENS_TYPE_TO_EVENT(SENS_TYPE_GRAVITY):
   1089             type = SENSOR_TYPE_GRAVITY;
   1090             sensor = COMMS_SENSOR_GRAVITY;
   1091             three = true;
   1092             break;
   1093         case SENS_TYPE_TO_EVENT(SENS_TYPE_LINEAR_ACCEL):
   1094             type = SENSOR_TYPE_LINEAR_ACCELERATION;
   1095             sensor = COMMS_SENSOR_LINEAR_ACCEL;
   1096             three = true;
   1097             break;
   1098         case SENS_TYPE_TO_EVENT(SENS_TYPE_ROTATION_VECTOR):
   1099             type = SENSOR_TYPE_ROTATION_VECTOR;
   1100             sensor = COMMS_SENSOR_ROTATION_VECTOR;
   1101             three = true;
   1102             break;
   1103         case SENS_TYPE_TO_EVENT(SENS_TYPE_GEO_MAG_ROT_VEC):
   1104             type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
   1105             sensor = COMMS_SENSOR_GEO_MAG;
   1106             three = true;
   1107             break;
   1108         case SENS_TYPE_TO_EVENT(SENS_TYPE_GAME_ROT_VECTOR):
   1109             type = SENSOR_TYPE_GAME_ROTATION_VECTOR;
   1110             sensor = COMMS_SENSOR_GAME_ROTATION_VECTOR;
   1111             three = true;
   1112             break;
   1113         case SENS_TYPE_TO_EVENT(SENS_TYPE_HALL):
   1114             type = 0;
   1115             sensor = COMMS_SENSOR_HALL;
   1116             one = true;
   1117             break;
   1118         case SENS_TYPE_TO_EVENT(SENS_TYPE_VSYNC):
   1119             type = SENSOR_TYPE_SYNC;
   1120             sensor = COMMS_SENSOR_SYNC;
   1121             one = true;
   1122             break;
   1123         case SENS_TYPE_TO_EVENT(SENS_TYPE_TILT):
   1124             type = SENSOR_TYPE_TILT_DETECTOR;
   1125             sensor = COMMS_SENSOR_TILT;
   1126             one = true;
   1127             break;
   1128         case SENS_TYPE_TO_EVENT(SENS_TYPE_GESTURE):
   1129             type = SENSOR_TYPE_PICK_UP_GESTURE;
   1130             sensor = COMMS_SENSOR_GESTURE;
   1131             one = true;
   1132             break;
   1133         case SENS_TYPE_TO_EVENT(SENS_TYPE_DOUBLE_TWIST):
   1134             type = SENSOR_TYPE_DOUBLE_TWIST;
   1135             sensor = COMMS_SENSOR_DOUBLE_TWIST;
   1136             one = true;
   1137             break;
   1138         case SENS_TYPE_TO_EVENT(SENS_TYPE_DOUBLE_TAP):
   1139             type = SENSOR_TYPE_DOUBLE_TAP;
   1140             sensor = COMMS_SENSOR_DOUBLE_TAP;
   1141             three = true;
   1142             break;
   1143         case SENS_TYPE_TO_EVENT(SENS_TYPE_WRIST_TILT):
   1144             type = SENSOR_TYPE_WRIST_TILT_GESTURE;
   1145             sensor = COMMS_SENSOR_WRIST_TILT;
   1146             one = true;
   1147             break;
   1148         case SENS_TYPE_TO_EVENT(SENS_TYPE_DOUBLE_TOUCH):
   1149             type = SENSOR_TYPE_DOUBLE_TOUCH;
   1150             sensor = COMMS_SENSOR_DOUBLE_TOUCH;
   1151             one = true;
   1152             break;
   1153         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_IN_VEHICLE_START):
   1154             type = 0;
   1155             sensor = COMMS_SENSOR_ACTIVITY_IN_VEHICLE_START;
   1156             one = true;
   1157             break;
   1158         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_IN_VEHICLE_STOP):
   1159             type = 0;
   1160             sensor = COMMS_SENSOR_ACTIVITY_IN_VEHICLE_STOP;
   1161             one = true;
   1162             break;
   1163         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_ON_BICYCLE_START):
   1164             type = 0;
   1165             sensor = COMMS_SENSOR_ACTIVITY_ON_BICYCLE_START;
   1166             one = true;
   1167             break;
   1168         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_ON_BICYCLE_STOP):
   1169             type = 0;
   1170             sensor = COMMS_SENSOR_ACTIVITY_ON_BICYCLE_STOP;
   1171             one = true;
   1172             break;
   1173         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_WALKING_START):
   1174             type = 0;
   1175             sensor = COMMS_SENSOR_ACTIVITY_WALKING_START;
   1176             one = true;
   1177             break;
   1178         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_WALKING_STOP):
   1179             type = 0;
   1180             sensor = COMMS_SENSOR_ACTIVITY_WALKING_STOP;
   1181             one = true;
   1182             break;
   1183         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_RUNNING_START):
   1184             type = 0;
   1185             sensor = COMMS_SENSOR_ACTIVITY_RUNNING_START;
   1186             one = true;
   1187             break;
   1188         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_RUNNING_STOP):
   1189             type = 0;
   1190             sensor = COMMS_SENSOR_ACTIVITY_RUNNING_STOP;
   1191             one = true;
   1192             break;
   1193         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_STILL_START):
   1194             type = 0;
   1195             sensor = COMMS_SENSOR_ACTIVITY_STILL_START;
   1196             one = true;
   1197             break;
   1198         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_STILL_STOP):
   1199             type = 0;
   1200             sensor = COMMS_SENSOR_ACTIVITY_STILL_STOP;
   1201             one = true;
   1202             break;
   1203         case SENS_TYPE_TO_EVENT(SENS_TYPE_ACTIVITY_TILTING):
   1204             type = 0;
   1205             sensor = COMMS_SENSOR_ACTIVITY_TILTING;
   1206             one = true;
   1207             break;
   1208         case SENS_TYPE_TO_EVENT(SENS_TYPE_GAZE):
   1209             type = SENSOR_TYPE_GAZE;
   1210             sensor = COMMS_SENSOR_GAZE;
   1211             one = true;
   1212             break;
   1213         case SENS_TYPE_TO_EVENT(SENS_TYPE_UNGAZE):
   1214             type = SENSOR_TYPE_UNGAZE;
   1215             sensor = COMMS_SENSOR_UNGAZE;
   1216             one = true;
   1217             break;
   1218         case EVT_RESET_REASON:
   1219             uint32_t resetReason;
   1220             memcpy(&resetReason, data->buffer, sizeof(resetReason));
   1221             ALOGI("Observed hub reset: 0x%08" PRIx32, resetReason);
   1222             restoreSensorState();
   1223             return 0;
   1224         default:
   1225             ALOGW("unknown evtType: 0x%08x len: %zu\n", data->evtType, len);
   1226             return -1;
   1227         }
   1228     } else {
   1229         ALOGW("too little data: len=%zu\n", len);
   1230         return -1;
   1231     }
   1232 
   1233     if (len >= sizeof(data->evtType) + sizeof(data->referenceTime) + sizeof(data->firstSample)) {
   1234         ret += sizeof(data->referenceTime);
   1235         timestamp = data->referenceTime;
   1236         numSamples = data->firstSample.numSamples;
   1237         for (i=0; i<numSamples; i++) {
   1238             if (data->firstSample.biasPresent && data->firstSample.biasSample == i)
   1239                 currSensor = bias;
   1240             else
   1241                 currSensor = sensor;
   1242 
   1243             if (one) {
   1244                 if (ret + sizeof(data->oneSamples[i]) > len) {
   1245                     ALOGW("sensor %d (one): ret=%zd, numSamples=%d, i=%d\n", currSensor, ret, numSamples, i);
   1246                     return -1;
   1247                 }
   1248                 if (i > 0)
   1249                     timestamp += ((uint64_t)data->oneSamples[i].deltaTime) << delta_time_shift_table[data->oneSamples[i].deltaTime & delta_time_encoded];
   1250                 processSample(timestamp, type, currSensor, &data->oneSamples[i], data->firstSample.highAccuracy);
   1251                 ret += sizeof(data->oneSamples[i]);
   1252             } else if (rawThree) {
   1253                 if (ret + sizeof(data->rawThreeSamples[i]) > len) {
   1254                     ALOGW("sensor %d (rawThree): ret=%zd, numSamples=%d, i=%d\n", currSensor, ret, numSamples, i);
   1255                     return -1;
   1256                 }
   1257                 if (i > 0)
   1258                     timestamp += ((uint64_t)data->rawThreeSamples[i].deltaTime) << delta_time_shift_table[data->rawThreeSamples[i].deltaTime & delta_time_encoded];
   1259                 processSample(timestamp, type, currSensor, &data->rawThreeSamples[i], data->firstSample.highAccuracy);
   1260                 ret += sizeof(data->rawThreeSamples[i]);
   1261             } else if (three) {
   1262                 if (ret + sizeof(data->threeSamples[i]) > len) {
   1263                     ALOGW("sensor %d (three): ret=%zd, numSamples=%d, i=%d\n", currSensor, ret, numSamples, i);
   1264                     return -1;
   1265                 }
   1266                 if (i > 0)
   1267                     timestamp += ((uint64_t)data->threeSamples[i].deltaTime) << delta_time_shift_table[data->threeSamples[i].deltaTime & delta_time_encoded];
   1268                 processSample(timestamp, type, currSensor, &data->threeSamples[i], data->firstSample.highAccuracy);
   1269                 ret += sizeof(data->threeSamples[i]);
   1270             } else {
   1271                 ALOGW("sensor %d (unknown): cannot processSample\n", currSensor);
   1272                 return -1;
   1273             }
   1274         }
   1275 
   1276         if (!numSamples)
   1277             ret += sizeof(data->firstSample);
   1278 
   1279         for (i=0; i<data->firstSample.numFlushes; i++) {
   1280             if (isActivitySensor(sensor) && mActivityEventHandler != NULL) {
   1281                 mActivityEventHandler->OnFlush();
   1282             } else {
   1283                 memset(&ev, 0x00, sizeof(sensors_event_t));
   1284                 ev.version = META_DATA_VERSION;
   1285                 ev.timestamp = 0;
   1286                 ev.type = SENSOR_TYPE_META_DATA;
   1287                 ev.sensor = 0;
   1288                 ev.meta_data.what = META_DATA_FLUSH_COMPLETE;
   1289                 if (mSensorState[sensor].alt && mSensorState[mSensorState[sensor].alt].flushCnt > 0) {
   1290                     mSensorState[mSensorState[sensor].alt].flushCnt --;
   1291                     ev.meta_data.sensor = mSensorState[sensor].alt;
   1292                 } else {
   1293                     mSensorState[sensor].flushCnt --;
   1294                     ev.meta_data.sensor = sensor;
   1295                 }
   1296 
   1297                 write(&ev, 1);
   1298                 ALOGV("flushing %d", ev.meta_data.sensor);
   1299             }
   1300         }
   1301     } else {
   1302         ALOGW("too little data for sensor %d: len=%zu\n", sensor, len);
   1303         return -1;
   1304     }
   1305 
   1306     return ret;
   1307 }
   1308 
   1309 void HubConnection::sendCalibrationOffsets()
   1310 {
   1311     sp<JSONObject> settings;
   1312     sp<JSONObject> saved_settings;
   1313     struct {
   1314         int32_t hw[3];
   1315         float sw[3];
   1316     } accel;
   1317 
   1318     int32_t proximity, proximity_array[4];
   1319     float barometer, humidity, light;
   1320     bool accel_hw_cal_exists, accel_sw_cal_exists;
   1321 
   1322     loadSensorSettings(&settings, &saved_settings);
   1323 
   1324     accel_hw_cal_exists = getCalibrationInt32(settings, ACCEL_BIAS_TAG, accel.hw, 3);
   1325     accel_sw_cal_exists = getCalibrationFloat(saved_settings, ACCEL_SW_BIAS_TAG, accel.sw);
   1326     if (accel_hw_cal_exists || accel_sw_cal_exists) {
   1327         // Store SW bias so we can remove bias for uncal data
   1328         mAccelBias[0] = accel.sw[0];
   1329         mAccelBias[1] = accel.sw[1];
   1330         mAccelBias[2] = accel.sw[2];
   1331 
   1332         queueDataInternal(COMMS_SENSOR_ACCEL, &accel, sizeof(accel));
   1333     }
   1334 
   1335     ALOGV("Use new configuration format");
   1336     std::vector<int32_t> hardwareGyroBias = getInt32Setting(settings, GYRO_BIAS_TAG);
   1337     std::vector<float> softwareGyroBias = getFloatSetting(saved_settings, GYRO_SW_BIAS_TAG);
   1338     if (hardwareGyroBias.size() == 3 || softwareGyroBias.size() == 3) {
   1339         struct {
   1340             AppToSensorHalDataPayload header;
   1341             GyroCalBias data;
   1342         } packet = {
   1343             .header = {
   1344                 .size = sizeof(GyroCalBias),
   1345                 .type = HALINTF_TYPE_GYRO_CAL_BIAS }
   1346         };
   1347         if (hardwareGyroBias.size() == 3) {
   1348             std::copy(hardwareGyroBias.begin(), hardwareGyroBias.end(),
   1349                       packet.data.hardwareBias);
   1350         }
   1351         if (softwareGyroBias.size() == 3) {
   1352             // Store SW bias so we can remove bias for uncal data
   1353             std::copy(softwareGyroBias.begin(), softwareGyroBias.end(),
   1354                       mGyroBias);
   1355 
   1356             std::copy(softwareGyroBias.begin(), softwareGyroBias.end(),
   1357                       packet.data.softwareBias);
   1358         }
   1359         // send packet to hub
   1360         queueDataInternal(COMMS_SENSOR_GYRO, &packet, sizeof(packet));
   1361     }
   1362 
   1363     // over temp cal
   1364     std::vector<float> gyroOtcData = getFloatSetting(saved_settings, GYRO_OTC_DATA_TAG);
   1365     if (gyroOtcData.size() == sizeof(GyroOtcData) / sizeof(float)) {
   1366         std::copy(gyroOtcData.begin(), gyroOtcData.end(),
   1367                   reinterpret_cast<float*>(&mGyroOtcData));
   1368         struct {
   1369             AppToSensorHalDataPayload header;
   1370             GyroOtcData data;
   1371         } packet = {
   1372             .header = {
   1373                 .size = sizeof(GyroOtcData),
   1374                 .type = HALINTF_TYPE_GYRO_OTC_DATA },
   1375             .data = mGyroOtcData
   1376         };
   1377 
   1378         // send it to hub
   1379         queueDataInternal(COMMS_SENSOR_GYRO, &packet, sizeof(packet));
   1380     } else {
   1381         ALOGW("Illegal otc_gyro data size = %zu", gyroOtcData.size());
   1382     }
   1383 
   1384     std::vector<float> magBiasData = getFloatSetting(saved_settings, MAG_BIAS_TAG);
   1385     if (magBiasData.size() == 3) {
   1386         // Store SW bias so we can remove bias for uncal data
   1387         std::copy(magBiasData.begin(), magBiasData.end(), mMagBias);
   1388 
   1389         struct {
   1390             AppToSensorHalDataPayload header;
   1391             MagCalBias mag;
   1392         } packet = {
   1393             .header = {
   1394                 .size = sizeof(MagCalBias),
   1395                 .type = HALINTF_TYPE_MAG_CAL_BIAS }
   1396         };
   1397         std::copy(magBiasData.begin(), magBiasData.end(), packet.mag.bias);
   1398         queueDataInternal(COMMS_SENSOR_MAG, &packet, sizeof(packet));
   1399     }
   1400 
   1401     if (settings->getFloat("barometer", &barometer))
   1402         queueDataInternal(COMMS_SENSOR_PRESSURE, &barometer, sizeof(barometer));
   1403 
   1404     if (settings->getFloat("humidity", &humidity))
   1405         queueDataInternal(COMMS_SENSOR_HUMIDITY, &humidity, sizeof(humidity));
   1406 
   1407     if (settings->getInt32("proximity", &proximity))
   1408         queueDataInternal(COMMS_SENSOR_PROXIMITY, &proximity, sizeof(proximity));
   1409 
   1410     if (getCalibrationInt32(settings, "proximity", proximity_array, 4))
   1411         queueDataInternal(COMMS_SENSOR_PROXIMITY, proximity_array, sizeof(proximity_array));
   1412 
   1413     if (settings->getFloat("light", &light))
   1414         queueDataInternal(COMMS_SENSOR_LIGHT, &light, sizeof(light));
   1415 }
   1416 
   1417 bool HubConnection::threadLoop() {
   1418     ALOGV("threadLoop: starting");
   1419 
   1420     if (mFd < 0) {
   1421         ALOGW("threadLoop: exiting prematurely: nanohub is unavailable");
   1422         return false;
   1423     }
   1424     waitOnNanohubLock();
   1425 
   1426     sendCalibrationOffsets();
   1427 
   1428     while (!Thread::exitPending()) {
   1429         ssize_t ret;
   1430 
   1431         do {
   1432             ret = poll(mPollFds, mNumPollFds, -1);
   1433         } while (ret < 0 && errno == EINTR);
   1434 
   1435         if (mInotifyPollIndex >= 0 && mPollFds[mInotifyPollIndex].revents & POLLIN) {
   1436             discardInotifyEvent();
   1437             waitOnNanohubLock();
   1438         }
   1439 
   1440 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
   1441         if (mMagBiasPollIndex >= 0 && mPollFds[mMagBiasPollIndex].revents & POLLERR) {
   1442             // Read from mag bias file
   1443             char buf[16];
   1444             lseek(mPollFds[mMagBiasPollIndex].fd, 0, SEEK_SET);
   1445             ::read(mPollFds[mMagBiasPollIndex].fd, buf, 16);
   1446             float bias = atof(buf);
   1447             mUsbMagBias = bias;
   1448             queueUsbMagBias();
   1449         }
   1450 #endif // USB_MAG_BIAS_REPORTING_ENABLED
   1451 
   1452 #ifdef DOUBLE_TOUCH_ENABLED
   1453         if (mDoubleTouchPollIndex >= 0 && mPollFds[mDoubleTouchPollIndex].revents & POLLERR) {
   1454             // Read from double touch file
   1455             char buf[16];
   1456             lseek(mPollFds[mDoubleTouchPollIndex].fd, 0, SEEK_SET);
   1457             ::read(mPollFds[mDoubleTouchPollIndex].fd, buf, 16);
   1458             sensors_event_t gestureEvent;
   1459             initEv(&gestureEvent, elapsedRealtimeNano(), SENSOR_TYPE_PICK_UP_GESTURE, COMMS_SENSOR_GESTURE)->data[0] = 8;
   1460             write(&gestureEvent, 1);
   1461         }
   1462 #endif // DOUBLE_TOUCH_ENABLED
   1463 
   1464         if (mPollFds[0].revents & POLLIN) {
   1465             uint8_t recv[256];
   1466             ssize_t len = ::read(mFd, recv, sizeof(recv));
   1467 
   1468             if (len >= 0) {
   1469                 for (ssize_t offset = 0; offset < len;) {
   1470                     ret = processBuf(recv + offset, len - offset);
   1471 
   1472                     if (ret > 0)
   1473                         offset += ret;
   1474                     else
   1475                         break;
   1476                 }
   1477             } else {
   1478                 ALOGW("read -1: errno=%d\n", errno);
   1479             }
   1480         }
   1481     }
   1482 
   1483     return false;
   1484 }
   1485 
   1486 ssize_t HubConnection::read(sensors_event_t *ev, size_t size) {
   1487     return mRing.read(ev, size);
   1488 }
   1489 
   1490 void HubConnection::setActivityCallback(ActivityEventHandler *eventHandler)
   1491 {
   1492     Mutex::Autolock autoLock(mLock);
   1493     mActivityEventHandler = eventHandler;
   1494 }
   1495 
   1496 void HubConnection::initConfigCmd(struct ConfigCmd *cmd, int handle)
   1497 {
   1498     uint8_t alt = mSensorState[handle].alt;
   1499 
   1500     memset(cmd, 0x00, sizeof(*cmd));
   1501 
   1502     cmd->evtType = EVT_NO_SENSOR_CONFIG_EVENT;
   1503     cmd->sensorType = mSensorState[handle].sensorType;
   1504 
   1505     if (alt && mSensorState[alt].enable && mSensorState[handle].enable) {
   1506         cmd->cmd = CONFIG_CMD_ENABLE;
   1507         if (mSensorState[alt].rate > mSensorState[handle].rate)
   1508             cmd->rate = mSensorState[alt].rate;
   1509         else
   1510             cmd->rate = mSensorState[handle].rate;
   1511         if (mSensorState[alt].latency < mSensorState[handle].latency)
   1512             cmd->latency = mSensorState[alt].latency;
   1513         else
   1514             cmd->latency = mSensorState[handle].latency;
   1515     } else if (alt && mSensorState[alt].enable) {
   1516         cmd->cmd = mSensorState[alt].enable ? CONFIG_CMD_ENABLE : CONFIG_CMD_DISABLE;
   1517         cmd->rate = mSensorState[alt].rate;
   1518         cmd->latency = mSensorState[alt].latency;
   1519     } else { /* !alt || !mSensorState[alt].enable */
   1520         cmd->cmd = mSensorState[handle].enable ? CONFIG_CMD_ENABLE : CONFIG_CMD_DISABLE;
   1521         cmd->rate = mSensorState[handle].rate;
   1522         cmd->latency = mSensorState[handle].latency;
   1523     }
   1524 
   1525     // will be a nop if direct report mode is not enabled
   1526     mergeDirectReportRequest(cmd, handle);
   1527 }
   1528 
   1529 void HubConnection::queueActivate(int handle, bool enable)
   1530 {
   1531     struct ConfigCmd cmd;
   1532     int ret;
   1533 
   1534     Mutex::Autolock autoLock(mLock);
   1535 
   1536     if (isValidHandle(handle)) {
   1537         mSensorState[handle].enable = enable;
   1538 
   1539         initConfigCmd(&cmd, handle);
   1540 
   1541         ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   1542         if (ret == sizeof(cmd))
   1543             ALOGV("queueActivate: sensor=%d, handle=%d, enable=%d",
   1544                     cmd.sensorType, handle, enable);
   1545         else
   1546             ALOGW("queueActivate: failed to send command: sensor=%d, handle=%d, enable=%d",
   1547                     cmd.sensorType, handle, enable);
   1548     } else {
   1549         ALOGV("queueActivate: unhandled handle=%d, enable=%d", handle, enable);
   1550     }
   1551 }
   1552 
   1553 void HubConnection::queueSetDelay(int handle, nsecs_t sampling_period_ns)
   1554 {
   1555     struct ConfigCmd cmd;
   1556     int ret;
   1557 
   1558     Mutex::Autolock autoLock(mLock);
   1559 
   1560     if (isValidHandle(handle)) {
   1561         if (sampling_period_ns > 0 &&
   1562                 mSensorState[handle].rate != SENSOR_RATE_ONCHANGE &&
   1563                 mSensorState[handle].rate != SENSOR_RATE_ONESHOT) {
   1564             mSensorState[handle].rate = period_ns_to_frequency_q10(sampling_period_ns);
   1565         }
   1566 
   1567         initConfigCmd(&cmd, handle);
   1568 
   1569         ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   1570         if (ret == sizeof(cmd))
   1571             ALOGV("queueSetDelay: sensor=%d, handle=%d, period=%" PRId64,
   1572                     cmd.sensorType, handle, sampling_period_ns);
   1573         else
   1574             ALOGW("queueSetDelay: failed to send command: sensor=%d, handle=%d, period=%" PRId64,
   1575                     cmd.sensorType, handle, sampling_period_ns);
   1576     } else {
   1577         ALOGV("queueSetDelay: unhandled handle=%d, period=%" PRId64, handle, sampling_period_ns);
   1578     }
   1579 }
   1580 
   1581 void HubConnection::queueBatch(
   1582         int handle,
   1583         nsecs_t sampling_period_ns,
   1584         nsecs_t max_report_latency_ns)
   1585 {
   1586     struct ConfigCmd cmd;
   1587     int ret;
   1588 
   1589     Mutex::Autolock autoLock(mLock);
   1590 
   1591     if (isValidHandle(handle)) {
   1592         if (sampling_period_ns > 0 &&
   1593                 mSensorState[handle].rate != SENSOR_RATE_ONCHANGE &&
   1594                 mSensorState[handle].rate != SENSOR_RATE_ONESHOT) {
   1595             mSensorState[handle].rate = period_ns_to_frequency_q10(sampling_period_ns);
   1596         }
   1597         mSensorState[handle].latency = max_report_latency_ns;
   1598 
   1599         initConfigCmd(&cmd, handle);
   1600 
   1601         ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   1602         if (ret == sizeof(cmd))
   1603             ALOGV("queueBatch: sensor=%d, handle=%d, period=%" PRId64 ", latency=%" PRId64,
   1604                     cmd.sensorType, handle, sampling_period_ns, max_report_latency_ns);
   1605         else
   1606             ALOGW("queueBatch: failed to send command: sensor=%d, handle=%d, period=%" PRId64 ", latency=%" PRId64,
   1607                     cmd.sensorType, handle, sampling_period_ns, max_report_latency_ns);
   1608     } else {
   1609         ALOGV("queueBatch: unhandled handle=%d, period=%" PRId64 ", latency=%" PRId64,
   1610                 handle, sampling_period_ns, max_report_latency_ns);
   1611     }
   1612 }
   1613 
   1614 void HubConnection::queueFlush(int handle)
   1615 {
   1616     struct ConfigCmd cmd;
   1617     int ret;
   1618 
   1619     Mutex::Autolock autoLock(mLock);
   1620 
   1621     if (isValidHandle(handle)) {
   1622         mSensorState[handle].flushCnt++;
   1623 
   1624         initConfigCmd(&cmd, handle);
   1625         cmd.cmd = CONFIG_CMD_FLUSH;
   1626 
   1627         ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   1628         if (ret == sizeof(cmd)) {
   1629             ALOGV("queueFlush: sensor=%d, handle=%d",
   1630                     cmd.sensorType, handle);
   1631         } else {
   1632             ALOGW("queueFlush: failed to send command: sensor=%d, handle=%d"
   1633                   " with error %s", cmd.sensorType, handle, strerror(errno));
   1634         }
   1635     } else {
   1636         ALOGV("queueFlush: unhandled handle=%d", handle);
   1637     }
   1638 }
   1639 
   1640 void HubConnection::queueDataInternal(int handle, void *data, size_t length)
   1641 {
   1642     struct ConfigCmd *cmd = (struct ConfigCmd *)malloc(sizeof(struct ConfigCmd) + length);
   1643     size_t ret;
   1644 
   1645     if (cmd && isValidHandle(handle)) {
   1646         initConfigCmd(cmd, handle);
   1647         memcpy(cmd->data, data, length);
   1648         cmd->cmd = CONFIG_CMD_CFG_DATA;
   1649 
   1650         ret = TEMP_FAILURE_RETRY(::write(mFd, cmd, sizeof(*cmd) + length));
   1651         if (ret == sizeof(*cmd) + length)
   1652             ALOGV("queueData: sensor=%d, length=%zu",
   1653                     cmd->sensorType, length);
   1654         else
   1655             ALOGW("queueData: failed to send command: sensor=%d, length=%zu",
   1656                     cmd->sensorType, length);
   1657     } else {
   1658         ALOGV("queueData: unhandled handle=%d", handle);
   1659     }
   1660     free(cmd);
   1661 }
   1662 
   1663 void HubConnection::queueData(int handle, void *data, size_t length)
   1664 {
   1665     Mutex::Autolock autoLock(mLock);
   1666     queueDataInternal(handle, data, length);
   1667 }
   1668 
   1669 void HubConnection::setOperationParameter(const additional_info_event_t &info) {
   1670     switch (info.type) {
   1671         case AINFO_LOCAL_GEOMAGNETIC_FIELD: {
   1672             ALOGV("local geomag field update: strength %fuT, dec %fdeg, inc %fdeg",
   1673                   static_cast<double>(info.data_float[0]),
   1674                   info.data_float[1] * 180 / M_PI,
   1675                   info.data_float[2] * 180 / M_PI);
   1676 
   1677             struct {
   1678                 AppToSensorHalDataPayload header;
   1679                 MagLocalField magLocalField;
   1680             } packet = {
   1681                 .header = {
   1682                     .size = sizeof(MagLocalField),
   1683                     .type = HALINTF_TYPE_MAG_LOCAL_FIELD },
   1684                 .magLocalField = {
   1685                     .strength = info.data_float[0],
   1686                     .declination = info.data_float[1],
   1687                     .inclination = info.data_float[2]}
   1688             };
   1689             queueDataInternal(COMMS_SENSOR_MAG, &packet, sizeof(packet));
   1690             break;
   1691         }
   1692         default:
   1693             break;
   1694     }
   1695 }
   1696 
   1697 void HubConnection::initNanohubLock() {
   1698     // Create the lock directory (if it doesn't already exist)
   1699     if (mkdir(NANOHUB_LOCK_DIR, NANOHUB_LOCK_DIR_PERMS) < 0 && errno != EEXIST) {
   1700         ALOGW("Couldn't create Nanohub lock directory: %s", strerror(errno));
   1701         return;
   1702     }
   1703 
   1704     mInotifyPollIndex = -1;
   1705     int inotifyFd = inotify_init1(IN_NONBLOCK);
   1706     if (inotifyFd < 0) {
   1707         ALOGW("Couldn't initialize inotify: %s", strerror(errno));
   1708     } else if (inotify_add_watch(inotifyFd, NANOHUB_LOCK_DIR, IN_CREATE | IN_DELETE) < 0) {
   1709         ALOGW("Couldn't add inotify watch: %s", strerror(errno));
   1710         close(inotifyFd);
   1711     } else {
   1712         mPollFds[mNumPollFds].fd = inotifyFd;
   1713         mPollFds[mNumPollFds].events = POLLIN;
   1714         mPollFds[mNumPollFds].revents = 0;
   1715         mInotifyPollIndex = mNumPollFds;
   1716         mNumPollFds++;
   1717     }
   1718 }
   1719 
   1720 ssize_t HubConnection::write(const sensors_event_t *ev, size_t n) {
   1721     return mRing.write(ev, n);
   1722 }
   1723 
   1724 #ifdef USB_MAG_BIAS_REPORTING_ENABLED
   1725 void HubConnection::queueUsbMagBias()
   1726 {
   1727     struct MsgCmd *cmd = (struct MsgCmd *)malloc(sizeof(struct MsgCmd) + sizeof(float));
   1728     size_t ret;
   1729 
   1730     if (cmd) {
   1731         cmd->evtType = EVT_APP_FROM_HOST;
   1732         cmd->msg.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, APP_ID_APP_BMI160);
   1733         cmd->msg.dataLen = sizeof(float);
   1734         memcpy((float *)(cmd+1), &mUsbMagBias, sizeof(float));
   1735 
   1736         ret = TEMP_FAILURE_RETRY(::write(mFd, cmd, sizeof(*cmd) + sizeof(float)));
   1737         if (ret == sizeof(*cmd) + sizeof(float))
   1738             ALOGV("queueUsbMagBias: bias=%f\n", mUsbMagBias);
   1739         else
   1740             ALOGW("queueUsbMagBias: failed to send command: bias=%f\n", mUsbMagBias);
   1741         free(cmd);
   1742     }
   1743 }
   1744 #endif  // USB_MAG_BIAS_REPORTING_ENABLED
   1745 
   1746 #ifdef LID_STATE_REPORTING_ENABLED
   1747 status_t HubConnection::initializeUinputNode()
   1748 {
   1749     int ret = 0;
   1750 
   1751     // Open uinput dev node
   1752     mUinputFd = TEMP_FAILURE_RETRY(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
   1753     if (mUinputFd < 0) {
   1754         ALOGW("could not open uinput node: %s", strerror(errno));
   1755         return UNKNOWN_ERROR;
   1756     }
   1757 
   1758     // Enable SW_LID events
   1759     ret  = TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_EVBIT, EV_SW));
   1760     ret |= TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_EVBIT, EV_SYN));
   1761     ret |= TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_SET_SWBIT, SW_LID));
   1762     if (ret < 0) {
   1763         ALOGW("could not send ioctl to uinput node: %s", strerror(errno));
   1764         return UNKNOWN_ERROR;
   1765     }
   1766 
   1767     // Create uinput node for SW_LID
   1768     struct uinput_user_dev uidev;
   1769     memset(&uidev, 0, sizeof(uidev));
   1770     snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-folio");
   1771     uidev.id.bustype = BUS_SPI;
   1772     uidev.id.vendor  = 0;
   1773     uidev.id.product = 0;
   1774     uidev.id.version = 0;
   1775 
   1776     ret = TEMP_FAILURE_RETRY(::write(mUinputFd, &uidev, sizeof(uidev)));
   1777     if (ret < 0) {
   1778         ALOGW("write to uinput node failed: %s", strerror(errno));
   1779         return UNKNOWN_ERROR;
   1780     }
   1781 
   1782     ret = TEMP_FAILURE_RETRY(ioctl(mUinputFd, UI_DEV_CREATE));
   1783     if (ret < 0) {
   1784         ALOGW("could not send ioctl to uinput node: %s", strerror(errno));
   1785         return UNKNOWN_ERROR;
   1786     }
   1787 
   1788     return OK;
   1789 }
   1790 
   1791 void HubConnection::sendFolioEvent(int32_t data) {
   1792     ssize_t ret = 0;
   1793     struct input_event ev;
   1794 
   1795     memset(&ev, 0, sizeof(ev));
   1796 
   1797     ev.type = EV_SW;
   1798     ev.code = SW_LID;
   1799     ev.value =  data;
   1800     ret = TEMP_FAILURE_RETRY(::write(mUinputFd, &ev, sizeof(ev)));
   1801     if (ret < 0) {
   1802         ALOGW("write to uinput node failed: %s", strerror(errno));
   1803         return;
   1804     }
   1805 
   1806     // Force flush with EV_SYN event
   1807     ev.type = EV_SYN;
   1808     ev.code = SYN_REPORT;
   1809     ev.value =  0;
   1810     ret = TEMP_FAILURE_RETRY(::write(mUinputFd, &ev, sizeof(ev)));
   1811     if (ret < 0) {
   1812         ALOGW("write to uinput node failed: %s", strerror(errno));
   1813         return;
   1814     }
   1815 
   1816     // Set lid state property
   1817     if (property_set(LID_STATE_PROPERTY,
   1818                      (data ? LID_STATE_CLOSED : LID_STATE_OPEN)) < 0) {
   1819         ALOGW("could not set lid_state property");
   1820     }
   1821 }
   1822 #endif  // LID_STATE_REPORTING_ENABLED
   1823 
   1824 #ifdef DIRECT_REPORT_ENABLED
   1825 void HubConnection::sendDirectReportEvent(const sensors_event_t *nev, size_t n) {
   1826     // short circuit to avoid lock operation
   1827     if (n == 0) {
   1828         return;
   1829     }
   1830 
   1831     // no intention to block sensor delivery thread. when lock is needed ignore
   1832     // the event (this only happens when the channel is reconfiured, so it's ok
   1833     if (mDirectChannelLock.tryLock() == NO_ERROR) {
   1834         while (n--) {
   1835             auto i = mSensorToChannel.find(nev->sensor);
   1836             if (i != mSensorToChannel.end()) {
   1837                 for (auto &j : i->second) {
   1838                     mDirectChannel[j.first]->write(nev);
   1839                 }
   1840             }
   1841             ++nev;
   1842         }
   1843         mDirectChannelLock.unlock();
   1844     }
   1845 }
   1846 
   1847 void HubConnection::mergeDirectReportRequest(struct ConfigCmd *cmd, int handle) {
   1848     auto j = mSensorToChannel.find(handle);
   1849     if (j != mSensorToChannel.end()) {
   1850         bool enable = false;
   1851         rate_q10_t rate;
   1852 
   1853         if (!j->second.empty()) {
   1854             int maxRateLevel = SENSOR_DIRECT_RATE_STOP;
   1855             for (auto &i : j->second) {
   1856                 maxRateLevel = (i.second) > maxRateLevel ? i.second : maxRateLevel;
   1857             }
   1858             switch(maxRateLevel) {
   1859                 case SENSOR_DIRECT_RATE_NORMAL:
   1860                     enable = true;
   1861                     rate = period_ns_to_frequency_q10(20000000ull); // NORMAL = 50Hz
   1862                     break;
   1863                 case SENSOR_DIRECT_RATE_FAST:
   1864                     enable = true;
   1865                     rate = period_ns_to_frequency_q10(5000000ull);  // FAST = 200Hz
   1866                     break;
   1867                 default:
   1868                     break;
   1869             }
   1870         }
   1871 
   1872         if (enable) {
   1873             cmd->rate = (rate > cmd->rate || cmd->cmd == CONFIG_CMD_DISABLE) ? rate : cmd->rate;
   1874             cmd->latency = 0;
   1875             cmd->cmd = CONFIG_CMD_ENABLE;
   1876         }
   1877     }
   1878 }
   1879 
   1880 int HubConnection::addDirectChannel(const struct sensors_direct_mem_t *mem) {
   1881     std::unique_ptr<DirectChannelBase> ch;
   1882     int ret = NO_MEMORY;
   1883 
   1884     switch(mem->type) {
   1885         case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
   1886             ch = std::make_unique<AshmemDirectChannel>(mem);
   1887             break;
   1888         case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
   1889             ch = std::make_unique<GrallocDirectChannel>(mem);
   1890             break;
   1891         default:
   1892             ret = INVALID_OPERATION;
   1893     }
   1894 
   1895     if (ch) {
   1896         if (ch->isValid()) {
   1897             Mutex::Autolock autoLock(mDirectChannelLock);
   1898             ret = mDirectChannelHandle++;
   1899             mDirectChannel.insert(std::make_pair(ret, std::move(ch)));
   1900         } else {
   1901             ret = ch->getError();
   1902             ALOGW("Direct channel object(type:%d) has error %d upon init", mem->type, ret);
   1903         }
   1904     }
   1905 
   1906     return ret;
   1907 }
   1908 
   1909 int HubConnection::removeDirectChannel(int channel_handle) {
   1910     // make sure no active sensor in this channel
   1911     std::vector<int32_t> activeSensorList;
   1912     stopAllDirectReportOnChannel(channel_handle, &activeSensorList);
   1913 
   1914     // sensor service is responsible for stop all sensors before remove direct
   1915     // channel. Thus, this is an error.
   1916     if (!activeSensorList.empty()) {
   1917         std::stringstream ss;
   1918         std::copy(activeSensorList.begin(), activeSensorList.end(),
   1919                 std::ostream_iterator<int32_t>(ss, ","));
   1920         ALOGW("Removing channel %d when sensors (%s) are not stopped.",
   1921                 channel_handle, ss.str().c_str());
   1922     }
   1923 
   1924     // remove the channel record
   1925     Mutex::Autolock autoLock(mDirectChannelLock);
   1926     mDirectChannel.erase(channel_handle);
   1927     return NO_ERROR;
   1928 }
   1929 
   1930 int HubConnection::stopAllDirectReportOnChannel(
   1931         int channel_handle, std::vector<int32_t> *activeSensorList) {
   1932     Mutex::Autolock autoLock(mDirectChannelLock);
   1933     if (mDirectChannel.find(channel_handle) == mDirectChannel.end()) {
   1934         return BAD_VALUE;
   1935     }
   1936 
   1937     std::vector<int32_t> sensorToStop;
   1938     for (auto &it : mSensorToChannel) {
   1939         auto j = it.second.find(channel_handle);
   1940         if (j != it.second.end()) {
   1941             it.second.erase(j);
   1942             if (it.second.empty()) {
   1943                 sensorToStop.push_back(it.first);
   1944             }
   1945         }
   1946     }
   1947 
   1948     if (activeSensorList != nullptr) {
   1949         *activeSensorList = sensorToStop;
   1950     }
   1951 
   1952     // re-evaluate and send config for all sensor that need to be stopped
   1953     bool ret = true;
   1954     for (auto sensor_handle : sensorToStop) {
   1955         Mutex::Autolock autoLock2(mLock);
   1956         struct ConfigCmd cmd;
   1957         initConfigCmd(&cmd, sensor_handle);
   1958 
   1959         int result = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   1960         ret = ret && (result == sizeof(cmd));
   1961     }
   1962     return ret ? NO_ERROR : BAD_VALUE;
   1963 }
   1964 
   1965 int HubConnection::configDirectReport(int sensor_handle, int channel_handle, int rate_level) {
   1966     if (sensor_handle == -1 && rate_level == SENSOR_DIRECT_RATE_STOP) {
   1967         return stopAllDirectReportOnChannel(channel_handle, nullptr);
   1968     }
   1969 
   1970     if (!isValidHandle(sensor_handle)) {
   1971         return BAD_VALUE;
   1972     }
   1973 
   1974     // clamp to fast
   1975     if (rate_level > SENSOR_DIRECT_RATE_FAST) {
   1976         rate_level = SENSOR_DIRECT_RATE_FAST;
   1977     }
   1978 
   1979     // manage direct channel data structure
   1980     Mutex::Autolock autoLock(mDirectChannelLock);
   1981     auto i = mDirectChannel.find(channel_handle);
   1982     if (i == mDirectChannel.end()) {
   1983         return BAD_VALUE;
   1984     }
   1985 
   1986     auto j = mSensorToChannel.find(sensor_handle);
   1987     if (j == mSensorToChannel.end()) {
   1988         return BAD_VALUE;
   1989     }
   1990 
   1991     j->second.erase(channel_handle);
   1992     if (rate_level != SENSOR_DIRECT_RATE_STOP) {
   1993         j->second.insert(std::make_pair(channel_handle, rate_level));
   1994     }
   1995 
   1996     Mutex::Autolock autoLock2(mLock);
   1997     struct ConfigCmd cmd;
   1998     initConfigCmd(&cmd, sensor_handle);
   1999 
   2000     int ret = TEMP_FAILURE_RETRY(::write(mFd, &cmd, sizeof(cmd)));
   2001 
   2002     if (rate_level == SENSOR_DIRECT_RATE_STOP) {
   2003         ret = NO_ERROR;
   2004     } else {
   2005         ret = (ret == sizeof(cmd)) ? sensor_handle : BAD_VALUE;
   2006     }
   2007     return ret;
   2008 }
   2009 
   2010 bool HubConnection::isDirectReportSupported() const {
   2011     return true;
   2012 }
   2013 #else // DIRECT_REPORT_ENABLED
   2014 // nop functions if feature is turned off
   2015 int HubConnection::addDirectChannel(const struct sensors_direct_mem_t *) {
   2016     return INVALID_OPERATION;
   2017 }
   2018 
   2019 int HubConnection::removeDirectChannel(int) {
   2020     return INVALID_OPERATION;
   2021 }
   2022 
   2023 int HubConnection::configDirectReport(int, int, int) {
   2024     return INVALID_OPERATION;
   2025 }
   2026 
   2027 void HubConnection::sendDirectReportEvent(const sensors_event_t *, size_t) {
   2028 }
   2029 
   2030 void HubConnection::mergeDirectReportRequest(struct ConfigCmd *, int) {
   2031 }
   2032 
   2033 bool HubConnection::isDirectReportSupported() const {
   2034     return false;
   2035 }
   2036 #endif // DIRECT_REPORT_ENABLED
   2037 
   2038 } // namespace android
   2039