CameraITS: skip checking events if a sensor does not exist

The ITS test_sensor_events and test_unified_timestamps tests check for
accelerometer, compass and gyro events if camera reports real-time
timestamp support. However, some devices may not have certain sensors.
Skip the checking if the corresponding sensor does not exist.

Test: Run ITS on a board without a compass
Bug: 76122643
Bug: 119296003
Change-Id: I9a689a47c92b65bd986a4d8e0c5e4024c1f63409
Merged-In: I9a689a47c92b65bd986a4d8e0c5e4024c1f63409
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 26af162..49bafc4 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -309,6 +309,20 @@
         if data['tag'] != 'vibrationStarted':
             raise its.error.Error('Invalid command response')
 
+    def get_sensors(self):
+        """Get all sensors on the device.
+
+        Returns:
+            A Python dictionary that returns keys and booleans for each sensor.
+        """
+        cmd = {}
+        cmd["cmdName"] = "checkSensorExistence"
+        self.sock.send(json.dumps(cmd) + "\n")
+        data,_ = self.__read_response_from_socket()
+        if data['tag'] != 'sensorExistence':
+            raise its.error.Error('Invalid command response')
+        return data['objValue']
+
     def start_sensor_events(self):
         """Start collecting sensor events on the device.
 
diff --git a/apps/CameraITS/tests/scene0/test_sensor_events.py b/apps/CameraITS/tests/scene0/test_sensor_events.py
index 5973de2..d3226b3 100644
--- a/apps/CameraITS/tests/scene0/test_sensor_events.py
+++ b/apps/CameraITS/tests/scene0/test_sensor_events.py
@@ -28,14 +28,16 @@
         # Only run test if the appropriate caps are claimed.
         its.caps.skip_unless(its.caps.sensor_fusion(props))
 
+        sensors = cam.get_sensors()
         cam.start_sensor_events()
         time.sleep(1)
         events = cam.get_sensor_events()
         print "Events over 1s: %d gyro, %d accel, %d mag"%(
                 len(events["gyro"]), len(events["accel"]), len(events["mag"]))
-        assert(len(events["gyro"]) > 0)
-        assert(len(events["accel"]) > 0)
-        assert(len(events["mag"]) > 0)
+        for key, existing in sensors.iteritems():
+            if existing:
+                e_msg = 'Sensor %s has no events!' % key
+                assert len(events[key]) > 0, e_msg
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CameraITS/tests/scene0/test_unified_timestamps.py b/apps/CameraITS/tests/scene0/test_unified_timestamps.py
index 019e6c5..89587f7 100644
--- a/apps/CameraITS/tests/scene0/test_unified_timestamps.py
+++ b/apps/CameraITS/tests/scene0/test_unified_timestamps.py
@@ -34,31 +34,31 @@
 
         # Get the timestamps of motion events.
         print "Reading sensor measurements"
+        sensors = cam.get_sensors()
         cam.start_sensor_events()
         time.sleep(0.5)
         events = cam.get_sensor_events()
-        assert(len(events["gyro"]) > 0)
-        assert(len(events["accel"]) > 0)
-        assert(len(events["mag"]) > 0)
-        ts_gyro0 = events["gyro"][0]["time"]
-        ts_gyro1 = events["gyro"][-1]["time"]
-        ts_accel0 = events["accel"][0]["time"]
-        ts_accel1 = events["accel"][-1]["time"]
-        ts_mag0 = events["mag"][0]["time"]
-        ts_mag1 = events["mag"][-1]["time"]
+        ts_sensor_first = {}
+        ts_sensor_last = {}
+        for sensor, existing in sensors.iteritems():
+            if existing:
+                assert(len(events[sensor]) > 0)
+                ts_sensor_first[sensor] = events[sensor][0]["time"]
+                ts_sensor_last[sensor] = events[sensor][-1]["time"]
 
         # Get the timestamp of another image.
         cap = cam.do_capture(req, fmt)
         ts_image1 = cap['metadata']['android.sensor.timestamp']
 
         print "Image timestamps:", ts_image0, ts_image1
-        print "Gyro timestamps:", ts_gyro0, ts_gyro1
-        print "Accel timestamps:", ts_accel0, ts_accel1
-        print "Mag timestamps:", ts_mag0, ts_mag1
 
         # The motion timestamps must be between the two image timestamps.
-        assert ts_image0 < min(ts_gyro0, ts_accel0, ts_mag0) < ts_image1
-        assert ts_image0 < max(ts_gyro1, ts_accel1, ts_mag1) < ts_image1
+        for sensor, existing in sensors.iteritems():
+            if existing:
+                print "%s timestamps: %d %d" % (sensor, ts_sensor_first[sensor],
+                                                ts_sensor_last[sensor])
+                assert ts_image0 < ts_sensor_first[sensor] < ts_image1
+                assert ts_image0 < ts_sensor_last[sensor] < ts_image1
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 697ad93..b8529b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -610,6 +610,8 @@
                     doGetProps();
                 } else if ("startSensorEvents".equals(cmdObj.getString("cmdName"))) {
                     doStartSensorEvents();
+                } else if ("checkSensorExistence".equals(cmdObj.getString("cmdName"))) {
+                    doCheckSensorExistence();
                 } else if ("getSensorEvents".equals(cmdObj.getString("cmdName"))) {
                     doGetSensorEvents();
                 } else if ("do3A".equals(cmdObj.getString("cmdName"))) {
@@ -813,6 +815,18 @@
         mSocketRunnableObj.sendResponse("sensorEventsStarted", "");
     }
 
+    private void doCheckSensorExistence() throws ItsException {
+        try {
+            JSONObject obj = new JSONObject();
+            obj.put("accel", mAccelSensor != null);
+            obj.put("mag", mMagSensor != null);
+            obj.put("gyro", mGyroSensor != null);
+            mSocketRunnableObj.sendResponse("sensorExistence", null, obj, null);
+        } catch (org.json.JSONException e) {
+            throw new ItsException("JSON error: ", e);
+        }
+    }
+
     private void doGetSensorEvents() throws ItsException {
         synchronized(mEventLock) {
             mSocketRunnableObj.sendResponse(mEvents);