Merge "Enable Nanohub INFO and DEBUG logs" into oc-dr1-dev
diff --git a/firmware/os/algos/calibration/gyroscope/gyro_cal.c b/firmware/os/algos/calibration/gyroscope/gyro_cal.c
index 7232950..83c5487 100644
--- a/firmware/os/algos/calibration/gyroscope/gyro_cal.c
+++ b/firmware/os/algos/calibration/gyroscope/gyro_cal.c
@@ -34,7 +34,7 @@
 
 #ifdef GYRO_CAL_DBG_ENABLED
 // The time value used to throttle debug messaging.
-#define GYROCAL_WAIT_TIME_NANOS (300000000)
+#define GYROCAL_WAIT_TIME_NANOS (100000000)
 
 // Unit conversion: nanoseconds to seconds.
 #define NANOS_TO_SEC (1.0e-9f)
@@ -295,8 +295,6 @@
 // Update the gyro calibration with gyro data [rad/sec].
 void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
                        float x, float y, float z, float temperature_celsius) {
-  static float latest_temperature_celsius = 0.0f;
-
   // Make sure that a valid window end-time is set, and start the watchdog
   // timer.
   if (gyro_cal->stillness_win_endtime_nanos <= 0) {
@@ -307,10 +305,8 @@
     gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
   }
 
-  // Update the temperature statistics (only on a temperature change).
-  if (NANO_ABS(temperature_celsius - latest_temperature_celsius) > FLT_MIN) {
-    gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
-  }
+  // Update the temperature statistics.
+  gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
 
 #ifdef GYRO_CAL_DBG_ENABLED
   // Update the gyro sampling rate estimate.
@@ -411,7 +407,7 @@
 
   // Determines if the device is currently still.
   device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
-      !mean_not_stable && !min_max_temp_exceeded ;
+      !mean_not_stable && !min_max_temp_exceeded;
 
   if (device_is_still) {
     // Device is "still" logic:
@@ -429,9 +425,8 @@
 
     // Check to see if current stillness period exceeds the desired limit.
     stillness_duration_exceeded =
-        ((gyro_cal->gyro_stillness_detect.last_sample_time -
-          gyro_cal->start_still_time_nanos) >=
-         gyro_cal->max_still_duration_nanos);
+        (gyro_cal->gyro_stillness_detect.last_sample_time >=
+         gyro_cal->start_still_time_nanos + gyro_cal->max_still_duration_nanos);
 
     // Track the new stillness mean and temperature data.
     gyroStillMeanTracker(gyro_cal, DO_STORE_DATA);
@@ -482,9 +477,8 @@
     // If device was previously still and the total stillness duration is not
     // "too short", then do a calibration with the data accumulated thus far.
     stillness_duration_too_short =
-        ((gyro_cal->gyro_stillness_detect.window_start_time -
-          gyro_cal->start_still_time_nanos) <
-         gyro_cal->min_still_duration_nanos);
+        (gyro_cal->gyro_stillness_detect.window_start_time <
+         gyro_cal->start_still_time_nanos + gyro_cal->min_still_duration_nanos);
 
     if (gyro_cal->prev_still && !stillness_duration_too_short) {
       computeGyroCal(gyro_cal,
@@ -516,11 +510,11 @@
 // Calculates a new gyro bias offset calibration value.
 void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
   // Check to see if new calibration values is within acceptable range.
-  if (!(gyro_cal->gyro_stillness_detect.prev_mean_x < MAX_GYRO_BIAS &&
+  if (!(gyro_cal->gyro_stillness_detect.prev_mean_x <  MAX_GYRO_BIAS &&
         gyro_cal->gyro_stillness_detect.prev_mean_x > -MAX_GYRO_BIAS &&
-        gyro_cal->gyro_stillness_detect.prev_mean_y < MAX_GYRO_BIAS &&
+        gyro_cal->gyro_stillness_detect.prev_mean_y <  MAX_GYRO_BIAS &&
         gyro_cal->gyro_stillness_detect.prev_mean_y > -MAX_GYRO_BIAS &&
-        gyro_cal->gyro_stillness_detect.prev_mean_z < MAX_GYRO_BIAS &&
+        gyro_cal->gyro_stillness_detect.prev_mean_z <  MAX_GYRO_BIAS &&
         gyro_cal->gyro_stillness_detect.prev_mean_z > -MAX_GYRO_BIAS)) {
 #ifdef GYRO_CAL_DBG_ENABLED
     CAL_DEBUG_LOG("[GYRO_CAL:REJECT]",
@@ -582,14 +576,39 @@
     return;
   }
 
-  // Check for the watchdog timeout condition (i.e., the time elapsed since the
-  // last received sample has exceeded the allowed watchdog duration).
+  // Checks for the following watchdog timeout conditions:
+  //    i.  The current timestamp has exceeded the allowed watchdog duration.
+  //    ii. A timestamp was received that has jumped backwards by more than the
+  //    allowed watchdog duration (e.g., timestamp clock roll-over).
   watchdog_timeout =
       (sample_time_nanos > gyro_cal->gyro_watchdog_timeout_duration_nanos +
-                               gyro_cal->gyro_watchdog_start_nanos);
+                               gyro_cal->gyro_watchdog_start_nanos) ||
+      (sample_time_nanos + gyro_cal->gyro_watchdog_timeout_duration_nanos <
+       gyro_cal->gyro_watchdog_start_nanos);
 
   // If a timeout occurred then reset to known good state.
   if (watchdog_timeout) {
+#ifdef GYRO_CAL_DBG_ENABLED
+    gyro_cal->debug_watchdog_count++;
+    if (sample_time_nanos < gyro_cal->gyro_watchdog_start_nanos) {
+      CAL_DEBUG_LOG(
+          "[GYRO_CAL:WATCHDOG]",
+          "Total#, Timestamp | Delta [nsec]: %lu, %llu, -%llu",
+          (unsigned long int)gyro_cal->debug_watchdog_count,
+          (unsigned long long int)sample_time_nanos,
+          (unsigned long long int)(gyro_cal->gyro_watchdog_start_nanos -
+                                   sample_time_nanos));
+    } else {
+      CAL_DEBUG_LOG(
+          "[GYRO_CAL:WATCHDOG]",
+          "Total#, Timestamp | Delta  [nsec]: %lu, %llu, %llu",
+          (unsigned long int)gyro_cal->debug_watchdog_count,
+          (unsigned long long int)sample_time_nanos,
+          (unsigned long long int)(sample_time_nanos -
+                                   gyro_cal->gyro_watchdog_start_nanos));
+    }
+#endif  // GYRO_CAL_DBG_ENABLED
+
     // Reset stillness detectors and restart data capture.
     gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
     gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
@@ -624,12 +643,6 @@
     // Assert watchdog timeout flags.
     gyro_cal->gyro_watchdog_timeout |= watchdog_timeout;
     gyro_cal->gyro_watchdog_start_nanos = 0;
-#ifdef GYRO_CAL_DBG_ENABLED
-    gyro_cal->debug_watchdog_count++;
-    CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]", "Total#, Timestamp [nsec]: %lu, %llu",
-                  (unsigned long int)gyro_cal->debug_watchdog_count,
-                  (unsigned long long int)sample_time_nanos);
-#endif  // GYRO_CAL_DBG_ENABLED
   }
 }
 
@@ -653,7 +666,7 @@
 
       // Initializes the min/max temperatures values.
       temperature_min_max_celsius[0] = FLT_MAX;
-      temperature_min_max_celsius[1] = -1.0f * (FLT_MAX - 1.0f);
+      temperature_min_max_celsius[1] = -FLT_MAX;
       break;
 
     case DO_UPDATE_DATA:
@@ -671,7 +684,7 @@
       break;
 
     case DO_STORE_DATA:
-      // Store the most recent "stillness" mean data to the GyroCal data
+      // Store the most recent temperature statistics data to the GyroCal data
       // structure. This functionality allows previous results to be recalled
       // when the device suddenly becomes "not still".
       if (num_points > 0) {
@@ -718,7 +731,7 @@
       // Resets the min/max window mean values to a default value.
       for (i = 0; i < 3; i++) {
         gyro_winmean_min[i] = FLT_MAX;
-        gyro_winmean_max[i] = -1.0f * (FLT_MAX - 1.0f);
+        gyro_winmean_max[i] = -FLT_MAX;
       }
       break;
 
@@ -1146,7 +1159,8 @@
 
     case GYRO_WAIT_STATE:
       // This helps throttle the print statements.
-      if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
+      if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(
+              timestamp_nanos, wait_timer_nanos, GYROCAL_WAIT_TIME_NANOS)) {
         gyro_cal->debug_state = next_state;
       }
       break;
@@ -1228,10 +1242,11 @@
   //   i.  Within the first 300 seconds of boot: output interval = 5
   //       seconds.
   //   ii. Thereafter: output interval is 60 seconds.
-  bool condition_i =
-      ((timestamp_nanos <= 300000000000) &&
-       (timestamp_nanos > 5000000000 + wait_timer_nanos));  // nsec
-  bool condition_ii = (timestamp_nanos > 60000000000 + wait_timer_nanos);
+  bool condition_i = ((timestamp_nanos <= 300000000000) &&
+                      NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(
+                          timestamp_nanos, wait_timer_nanos, 5000000000));
+  bool condition_ii = NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(
+      timestamp_nanos, wait_timer_nanos, 60000000000);
 
   // This is a state machine that controls the reporting out of tuning data.
   switch (debug_state) {
@@ -1250,7 +1265,8 @@
 
     case GYRO_WAIT_STATE:
       // This helps throttle the print statements.
-      if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
+      if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(
+              timestamp_nanos, wait_timer_nanos, GYROCAL_WAIT_TIME_NANOS)) {
         debug_state = next_state;
       }
       break;
diff --git a/firmware/os/algos/calibration/over_temp/over_temp_cal.c b/firmware/os/algos/calibration/over_temp/over_temp_cal.c
index cef632a..abcb7e3 100644
--- a/firmware/os/algos/calibration/over_temp/over_temp_cal.c
+++ b/firmware/os/algos/calibration/over_temp/over_temp_cal.c
@@ -42,7 +42,7 @@
 #define OTC_DEBUG_VERSION_STRING "[May 15, 2017]"
 
 // The time value used to throttle debug messaging.
-#define OTC_WAIT_TIME_NANOS (300000000)
+#define OTC_WAIT_TIME_NANOS (100000000)
 
 // Sensor axis label definition with index correspondence: 0=X, 1=Y, 2=Z.
 static const char  kDebugAxisLabel[3] = "XYZ";
@@ -660,8 +660,9 @@
   //          (current_timestamp_nanos - modelupdate_timestamp_nanos) <
   //            min_update_interval_nanos
   if (over_temp_cal->num_model_pts >= over_temp_cal->min_num_model_pts &&
-      timestamp_nanos > over_temp_cal->min_update_interval_nanos +
-                            over_temp_cal->modelupdate_timestamp_nanos) {
+      NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(
+          timestamp_nanos, over_temp_cal->modelupdate_timestamp_nanos,
+          over_temp_cal->min_update_interval_nanos)) {
     computeModelUpdate(over_temp_cal, timestamp_nanos);
   }
 
@@ -687,7 +688,8 @@
   static uint64_t wait_timer = 0;
   // Prints the sensor temperature trajectory for debugging purposes.
   // This throttles the print statements.
-  if (timestamp_nanos >= 1000000000 + wait_timer) {
+  if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(timestamp_nanos, wait_timer,
+                                               1000000000)) {
     wait_timer = timestamp_nanos;  // Starts the wait timer.
 
     // Prints out temperature and the current timestamp.
@@ -776,73 +778,63 @@
     removeStaleModelData(over_temp_cal, timestamp_nanos);
   }
 
+  // If there are points in the model data set, then a 'nearest_offset' has been
+  // defined.
+  bool nearest_offset_defined = (over_temp_cal->num_model_pts > 0);
+
   // Uses the most recent offset estimate for offset compensation if it is
   // defined and within a time delta specified by
   // OTC_USE_RECENT_OFFSET_TIME_NANOS.
-  if (over_temp_cal->latest_offset && over_temp_cal->num_model_pts > 0 &&
+  if (over_temp_cal->latest_offset && nearest_offset_defined &&
       timestamp_nanos < over_temp_cal->latest_offset->timestamp_nanos +
                             OTC_USE_RECENT_OFFSET_TIME_NANOS) {
     setCompensatedOffset(over_temp_cal, over_temp_cal->latest_offset->offset,
                          timestamp_nanos);
-    return;
+    return;  // Exits early.
   }
 
-  // Defaults to the current compensated offset vector.
+  // Sets the default compensated offset vector.
   float compensated_offset[3];
-  memcpy(compensated_offset, over_temp_cal->compensated_offset.offset,
-         3 * sizeof(float));
+  if (nearest_offset_defined) {
+    // Uses the nearest-temperature estimate to perform the compensation.
+    memcpy(compensated_offset, over_temp_cal->nearest_offset->offset,
+           3 * sizeof(float));
+  } else {
+    // Uses the current compensated offset value.
+    memcpy(compensated_offset, over_temp_cal->compensated_offset.offset,
+           3 * sizeof(float));
+  }
 
-  // Provides per-axis offset compensation updates.
+  // Provides per-axis checks to complete the offset compensation vector update.
   size_t index;
   for (index = 0; index < 3; index++) {
-    if (over_temp_cal->temp_sensitivity[index] >= OTC_INITIAL_SENSITIVITY) {
-      // Uses the nearest-temperature estimate to perform the compensation if
-      // this axis model is in its initial state. If the 'nearest_offset' is
-      // not defined (i.e., no model points defined), then no update is
-      // performed (i.e., keeps the current value).
-      if (over_temp_cal->num_model_pts > 0) {
+    if (over_temp_cal->temp_sensitivity[index] < OTC_INITIAL_SENSITIVITY) {
+      // If a valid axis model is defined then the default compensation will use
+      // the linear model:
+      //   compensated_offset = (temp_sensitivity * temperature +
+      //   sensor_intercept)
+      compensated_offset[index] =
+          (over_temp_cal->temp_sensitivity[index] * temperature_celsius +
+           over_temp_cal->sensor_intercept[index]);
+
+      if (nearest_offset_defined &&
+          NANO_ABS(temperature_celsius -
+                   over_temp_cal->nearest_offset->offset_temp_celsius) <
+              over_temp_cal->delta_temp_per_bin &&
+          NANO_ABS(compensated_offset[index] -
+                   over_temp_cal->nearest_offset->offset[index]) <
+              over_temp_cal->max_error_limit) {
+        // Uses the nearest-temperature estimate to perform the compensation if
+        // the sensor's temperature is within a small neighborhood of the
+        // 'nearest_offset', and the delta between the nearest-temperature
+        // estimate and the model fit is less than 'max_error_limit'.
         compensated_offset[index] =
             over_temp_cal->nearest_offset->offset[index];
       }
-    } else {
-      if (NANO_ABS(temperature_celsius -
-                   over_temp_cal->nearest_offset->offset_temp_celsius) <
-              over_temp_cal->delta_temp_per_bin) {
-        // Attempts to use the nearest-temperature estimate to perform the
-        // compensation if the sensor's temperature is within a small
-        // neighborhood of the 'nearest_offset'. If the 'nearest_offset' is
-        // not defined (i.e., no model points defined), then no update is
-        // performed (i.e., keeps the current value).
-        if (over_temp_cal->num_model_pts > 0) {
-          // If the delta between the nearest-temperature estimate and the
-          // model fit is greater than 'max_error_limit', then the validity of
-          // the data may be questionable; then this defaults to using the
-          // model fit for compensation.
-          compensated_offset[index] =
-              (over_temp_cal->temp_sensitivity[index] * temperature_celsius +
-               over_temp_cal->sensor_intercept[index]);
-
-          if (NANO_ABS(compensated_offset[index] -
-                       over_temp_cal->nearest_offset->offset[index]) <
-                  over_temp_cal->max_error_limit) {
-            compensated_offset[index] =
-                over_temp_cal->nearest_offset->offset[index];
-          }
-        }
-      } else {
-        // If a valid axis model is defined but outside the temperature
-        // neighborhood of the 'nearest_offset', then compensate using the
-        // linear model:
-        //   compensated_offset = (temp_sensitivity * temperature +
-        //   sensor_intercept)
-        compensated_offset[index] =
-            (over_temp_cal->temp_sensitivity[index] * temperature_celsius +
-             over_temp_cal->sensor_intercept[index]);
-      }
     }
   }
 
-  // Updates the offset compensation vector, and timestamp.
+  // Finalizes the update to the offset compensation vector, and timestamp.
   setCompensatedOffset(over_temp_cal, compensated_offset, timestamp_nanos);
 }
 
@@ -1270,7 +1262,8 @@
 
     case OTC_WAIT_STATE:
       // This helps throttle the print statements.
-      if (timestamp_nanos >= OTC_WAIT_TIME_NANOS + wait_timer) {
+      if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(timestamp_nanos, wait_timer,
+                                                   OTC_WAIT_TIME_NANOS)) {
         over_temp_cal->debug_state = next_state;
       }
       break;
diff --git a/firmware/os/algos/common/math/vec.h b/firmware/os/algos/common/math/vec.h
index 870e697..49f197c 100644
--- a/firmware/os/algos/common/math/vec.h
+++ b/firmware/os/algos/common/math/vec.h
@@ -61,6 +61,15 @@
 
 #define NANO_MIN(a, b) ((a) < (b)) ? (a) : (b)
 
+// Time check helper macro that returns true if:
+//    i.  't1' is equal to or exceeds 't2' plus 't_delta'.
+//    ii. Or, a negative timestamp delta occurred since,
+//        't1' should always >= 't2'. This prevents potential lockout conditions
+//        if the timer count 't1' rolls over or an erroneously large
+//        timestamp is passed through.
+#define NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(t1, t2, t_delta) \
+  (((t1) >= (t2) + (t_delta)) || ((t1) < (t2)))
+
 // 3-DIMENSIONAL VECTOR MATH ///////////////////////////////////////////
 static inline void initVec3(struct Vec3 *v, float x, float y, float z) {
   ASSERT_NOT_NULL(v);
diff --git a/sensorhal/directchannel.cpp b/sensorhal/directchannel.cpp
index d0e719d..8d87782 100644
--- a/sensorhal/directchannel.cpp
+++ b/sensorhal/directchannel.cpp
@@ -79,7 +79,8 @@
 GrallocHalWrapper::GrallocHalWrapper()
         : mError(NO_INIT), mVersion(-1),
           mGrallocModule(nullptr), mAllocDevice(nullptr), mGralloc1Device(nullptr),
-          mPfnRetain(nullptr), mPfnRelease(nullptr), mPfnLock(nullptr), mPfnUnlock(nullptr) {
+          mPfnRetain(nullptr), mPfnRelease(nullptr), mPfnLock(nullptr), mPfnUnlock(nullptr),
+          mUnregisterImplyDelete(false) {
     const hw_module_t *module;
     status_t err = ::hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
     ALOGE_IF(err, "couldn't load %s module (%s)", GRALLOC_HARDWARE_MODULE_ID, strerror(-err));
@@ -106,7 +107,7 @@
             mGrallocModule = (gralloc_module_t *)module;
             mVersion = 0;
             break;
-        case 1:
+        case 1: {
             err = ::gralloc1_open(module, &mGralloc1Device);
             if (err != NO_ERROR) {
                 ALOGE("cannot open gralloc1 device (%s)", strerror(-err));
@@ -135,10 +136,23 @@
                 break;
             }
 
+
+            int32_t caps[GRALLOC1_LAST_CAPABILITY];
+            uint32_t n_cap = GRALLOC1_LAST_CAPABILITY;
+            mGralloc1Device->getCapabilities(mGralloc1Device, &n_cap, caps);
+            for (size_t i = 0; i < n_cap; ++i) {
+                if (caps[i] == GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE) {
+                    mUnregisterImplyDelete = true;
+                }
+            }
+            ALOGI("gralloc hal %ssupport RELEASE_IMPLY_DELETE",
+                  mUnregisterImplyDelete ? "" : "does not ");
+
             // successfully initialized gralloc1
             mGrallocModule = (gralloc_module_t *)module;
             mVersion = 1;
             break;
+        }
         default:
             ALOGE("Unknown version, not supported");
             break;
@@ -280,8 +294,10 @@
             mBase = nullptr;
         }
         GrallocHalWrapper::getInstance().unregisterBuffer(mNativeHandle);
-        ::native_handle_close(mNativeHandle);
-        ::native_handle_delete(mNativeHandle);
+        if (!GrallocHalWrapper::getInstance().unregisterImplyDelete()) {
+            ::native_handle_close(mNativeHandle);
+            ::native_handle_delete(mNativeHandle);
+        }
         mNativeHandle = nullptr;
     }
 }
diff --git a/sensorhal/directchannel.h b/sensorhal/directchannel.h
index 192e35d..4842ffc 100644
--- a/sensorhal/directchannel.h
+++ b/sensorhal/directchannel.h
@@ -58,6 +58,7 @@
     int unregisterBuffer(const native_handle_t *handle);
     int lock(const native_handle_t *handle, int usage, int l, int t, int w, int h, void **vaddr);
     int unlock(const native_handle_t *handle);
+    bool unregisterImplyDelete() { return mUnregisterImplyDelete; }
 private:
     friend class Singleton<GrallocHalWrapper>;
     GrallocHalWrapper();
@@ -76,6 +77,7 @@
     GRALLOC1_PFN_RELEASE mPfnRelease;
     GRALLOC1_PFN_LOCK mPfnLock;
     GRALLOC1_PFN_UNLOCK mPfnUnlock;
+    bool mUnregisterImplyDelete;
 };
 
 class GrallocDirectChannel : public DirectChannelBase {