Merge 1ef40c6f506a3d6f44eb8436870eba7a074e08bb on remote branch

Change-Id: Icf74fd3499c0fd0579254d17523c5a3331ce916f
diff --git a/core/include/chre/core/event_loop_common.h b/core/include/chre/core/event_loop_common.h
index 03765f0..c2f636b 100644
--- a/core/include/chre/core/event_loop_common.h
+++ b/core/include/chre/core/event_loop_common.h
@@ -53,6 +53,7 @@
   SettingChangeEvent,
   GnssLocationReportEvent,
   GnssMeasurementReportEvent,
+  DelayedFatalError,
 };
 
 //! The function signature of a system callback mirrors the CHRE event free
diff --git a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
index 1add617..4f8db72 100644
--- a/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
+++ b/java/test/cross_validation/src/com/google/android/chre/test/crossvalidator/ChreCrossValidatorSensor.java
@@ -37,7 +37,7 @@
 import org.junit.Assert;
 import org.junit.Assume;
 
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -70,8 +70,6 @@
 
     private static final long DEFAULT_SAMPLING_INTERVAL_IN_MS = 20;
 
-    // TODO(b/146052784): May need to account for differences in sampling rate and latency from
-    // AP side vs CHRE side
     private static final long SAMPLING_LATENCY_IN_MS = 0;
 
     private static final long MAX_TIMESTAMP_DIFF_NS = 10000000L;
@@ -256,8 +254,6 @@
         Assert.assertTrue("Did not find any AP datapoints", mApDatapointsArray.length > 0);
         alignApAndChreDatapoints();
         // AP and CHRE datapoints will be same size
-        // TODO(b/146052784): Ensure that CHRE data is the same sampling rate as AP data for
-        // comparison
         for (int i = 0; i < mApDatapointsArray.length; i++) {
             assertSensorDatapointsSimilar(
                     (ApSensorDatapoint) mApDatapointsArray[i],
@@ -400,35 +396,35 @@
     }
 
     /*
-    * Align the AP and CHRE datapoints by finding the first pair that are similar comparing
-    * linearly from there. Also truncate the end if one list has more datapoints than the other
-    * after this. This is needed because AP and CHRE can start sending data and varying times to
-    * this validator and can also stop sending at various times.
+    * Align the AP and CHRE datapoints by finding all the timestamps that match up and discarding
+    * the rest of the datapoints.
     */
     private void alignApAndChreDatapoints() throws AssertionError {
-        int matchAp = 0, matchChre = 0;
-        int shorterDpLength = Math.min(mApDatapointsArray.length, mChreDatapointsArray.length);
-        if (mApDatapointsArray[0].timestamp < mChreDatapointsArray[0].timestamp) {
-            matchChre = 0;
-            matchAp = indexOfFirstClosestDatapoint((SensorDatapoint[]) mApDatapointsArray,
-                                                   mChreDatapointsArray[0]);
-        } else {
-            matchAp = 0;
-            matchChre = indexOfFirstClosestDatapoint((SensorDatapoint[]) mChreDatapointsArray,
-                                                     mApDatapointsArray[0]);
+        ArrayList<ApSensorDatapoint> newApSensorDatapoints = new ArrayList<ApSensorDatapoint>();
+        ArrayList<ChreSensorDatapoint> newChreSensorDatapoints =
+                new ArrayList<ChreSensorDatapoint>();
+        int apI = 0;
+        int chreI = 0;
+        while (apI < mApDatapointsArray.length && chreI < mChreDatapointsArray.length) {
+            ApSensorDatapoint apDp = mApDatapointsArray[apI];
+            ChreSensorDatapoint chreDp = mChreDatapointsArray[chreI];
+            if (datapointTimestampsAreSimilar(apDp, chreDp)) {
+                newApSensorDatapoints.add(apDp);
+                newChreSensorDatapoints.add(chreDp);
+                apI++;
+                chreI++;
+            } else if (apDp.timestamp < chreDp.timestamp) {
+                apI++;
+            } else {
+                chreI++;
+            }
         }
+        // TODO(b/175795665): Assert that an acceptable amount of datapoints pass the alignment
+        // phase.
         Assert.assertTrue("Did not find matching timestamps to align AP and CHRE datapoints.",
-                          (matchAp != -1 && matchChre != -1));
-        // Remove extraneous datapoints before matching datapoints
-        int apStartI = matchAp;
-        int chreStartI = matchChre;
-        int newApLength = mApDatapointsArray.length - apStartI;
-        int newChreLength = mChreDatapointsArray.length - chreStartI;
-        int minLength = Math.min(newApLength, newChreLength);
-        int chreEndI = chreStartI + minLength;
-        int apEndI = apStartI + minLength;
-        mApDatapointsArray = Arrays.copyOfRange(mApDatapointsArray, apStartI, apEndI);
-        mChreDatapointsArray = Arrays.copyOfRange(mChreDatapointsArray, chreStartI, chreEndI);
+                          !(newApSensorDatapoints.isEmpty() || newChreSensorDatapoints.isEmpty()));
+        mApDatapointsArray = newApSensorDatapoints.toArray(new ApSensorDatapoint[0]);
+        mChreDatapointsArray = newChreSensorDatapoints.toArray(new ChreSensorDatapoint[0]);
     }
 
     /**
@@ -461,10 +457,6 @@
                 String.format("AP and CHRE three axis datapoint values differ on index %d", index)
                 + "\nAP data -> " + apDp + "\nCHRE data -> "
                 + chreDp;
-        String timestampsAssertMsg =
-                String.format("AP and CHRE three axis timestamp values differ on index %d", index)
-                + "\nAP data -> " + apDp + "\nCHRE data -> "
-                + chreDp;
 
         // TODO(b/146052784): Log full list of datapoints to file on disk on assertion failure
         // so that there is more insight into the problem then just logging the one pair of
@@ -472,23 +464,6 @@
         Assert.assertTrue(datapointsAssertMsg,
                 datapointValuesAreSimilar(
                 apDp, chreDp, mSensorConfig.errorMargin));
-        Assert.assertTrue(timestampsAssertMsg,
-                datapointTimestampsAreSimilar(apDp, chreDp));
-    }
-
-    /**
-     * @param datapoints Array of dataoints to compare timestamps to laterDp
-     * @param laterDp SensorDatapoint whose timestamp will be compared to the datapoints in array
-     *    to find the first pair that match.
-     */
-    private int indexOfFirstClosestDatapoint(SensorDatapoint[] sensorDatapoints,
-                                             SensorDatapoint laterDp) {
-        for (int i = 0; i < sensorDatapoints.length; i++) {
-            if (datapointTimestampsAreSimilar(sensorDatapoints[i], laterDp)) {
-                return i;
-            }
-        }
-        return -1;
     }
 
     /**
diff --git a/platform/slpi/see/platform_sensor_manager.cc b/platform/slpi/see/platform_sensor_manager.cc
index d798d5c..478f0ee 100644
--- a/platform/slpi/see/platform_sensor_manager.cc
+++ b/platform/slpi/see/platform_sensor_manager.cc
@@ -142,6 +142,17 @@
 
 #endif  // CHRE_SLPI_UIMG_ENABLED
 
+#ifndef CHRE_LOG_ONLY_NO_SENSOR
+/**
+ * Callback function which will run after a delay if a required sensor is not
+ * found.
+ */
+void crashAfterSensorNotFoundCallback(uint16_t /* eventType */,
+                                      void * /* eventData */) {
+  FATAL_ERROR("Missing required sensor(s)");
+}
+#endif
+
 void handleMissingSensor() {
   // Try rebooting if a sensor is missing, which might help recover from a
   // transient failure/race condition at startup. But to avoid endless crashes,
@@ -151,12 +162,13 @@
   // SLPI SSR).
 #ifndef CHRE_LOG_ONLY_NO_SENSOR
   if (SystemTime::getMonotonicTime() < (kDefaultSeeWaitTimeout + Seconds(15))) {
-    FATAL_ERROR("Missing required sensor(s)");
-  } else
-#endif
-  {
-    LOGE("Missing required sensor(s)");
+    Nanoseconds delay(5 * Seconds(60).toRawNanoseconds());  // 5 minutes
+    EventLoopManagerSingleton::get()->setDelayedCallback(
+        SystemCallbackType::DelayedFatalError, nullptr,
+        crashAfterSensorNotFoundCallback, delay);
   }
+#endif
+  LOGE("Missing required sensor(s)");
 }
 
 /**