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