media_perception: Check D-Bus response for nullptr.

Add a check for nullptr at the beginning of the
HandleFalconPtzTransitionResponse callback.
http://google3/third_party/chromiumos_libchrome/dbus/object_proxy.h?l=134
provides that nullptr can be passed to the callback if the method call
(DoPTZTransition) was unsuccessful.

Also copied google3/videoconf/gvc2/rtanalytics/cros_proto/huddly.proto
to proto/huddly.proto.

BUG=b:170953648,chromium:1152909
TEST=Deployed local builds of MPS to endeavour. Without this patch,
camera crashes occasionally produce MPS crashes with the stack trace
ending in dbus::PopArrayOfBytes; with this patch, camera crashes
generally do not produce MPS crashes.

Change-Id: Idc60cb0de7a42f3f092019a544d113339c00ccce
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2558652
Tested-by: Richard Yeh <rcy@google.com>
Tested-by: Luke Sorenson <lasoren@chromium.org>
Commit-Queue: Luke Sorenson <lasoren@chromium.org>
Reviewed-by: Luke Sorenson <lasoren@chromium.org>
Reviewed-by: Toni Baržić <tbarzic@chromium.org>
Reviewed-by: Pablo Ceballos <pceballos@chromium.org>
Reviewed-by: Joe Tessler <jrt@chromium.org>
Auto-Submit: Richard Yeh <rcy@google.com>
diff --git a/media_perception/BUILD.gn b/media_perception/BUILD.gn
index e080e4e..0bf9cac 100644
--- a/media_perception/BUILD.gn
+++ b/media_perception/BUILD.gn
@@ -28,6 +28,7 @@
     "${proto_in_dir}/device_management.proto",
     "${proto_in_dir}/frame_perception.proto",
     "${proto_in_dir}/hotword_detection.proto",
+    "${proto_in_dir}/huddly.proto",
     "${proto_in_dir}/media_perception_mojom.proto",
     "${proto_in_dir}/occupancy_trigger.proto",
     "${proto_in_dir}/perception_interface.proto",
diff --git a/media_perception/output_manager.cc b/media_perception/output_manager.cc
index ffc94f3..00373b8 100644
--- a/media_perception/output_manager.cc
+++ b/media_perception/output_manager.cc
@@ -9,6 +9,7 @@
 
 #include "media_perception/frame_perception.pb.h"
 #include "media_perception/hotword_detection.pb.h"
+#include "media_perception/huddly.pb.h"
 #include "media_perception/occupancy_trigger.pb.h"
 #include "media_perception/presence_perception.pb.h"
 #include "media_perception/proto_mojom_conversion.h"
@@ -403,13 +404,21 @@
 
 void OutputManager::HandleFalconPtzTransitionResponse(
     dbus::Response* response) {
-  dbus::MessageReader reader(response);
-  // Return the response to rtanalytics.
-  const uint8_t* bytes = nullptr;
-  size_t size;
-  reader.PopArrayOfBytes(&bytes, &size);
   std::vector<uint8_t> serialized_response;
-  serialized_response.assign(bytes, bytes + size);
+  if (response == nullptr) {
+    LOG(ERROR) << "HandleFalconPtzTransitionResponse ignoring dbus nullptr.";
+    huddly::IndexedTransitionsResponse itr;
+    itr.set_chosen_starting_index(-1);
+    serialized_response =
+        Serialized<huddly::IndexedTransitionsResponse>(itr).GetBytes();
+  } else {
+    dbus::MessageReader reader(response);
+    // Return the response to rtanalytics.
+    const uint8_t* bytes = nullptr;
+    size_t size;
+    reader.PopArrayOfBytes(&bytes, &size);
+    serialized_response.assign(bytes, bytes + size);
+  }
   rtanalytics_->RespondToFalconPtzTransition(configuration_name_,
                                              serialized_response);
 }
diff --git a/media_perception/proto/huddly.proto b/media_perception/proto/huddly.proto
new file mode 100644
index 0000000..f42efc7
--- /dev/null
+++ b/media_perception/proto/huddly.proto
@@ -0,0 +1,44 @@
+syntax = "proto3";
+
+package huddly;
+
+message CropIndexStatusRequest {}
+
+message CropIndexStatusResponse {
+  int32 crop_index = 1;
+}
+
+message Rect {
+  float x_center = 1;     // (0.125 - 0.875) On max Zoom
+  float y_center = 2;     // (0.125 - 0.875) On max Zoom
+  float zoom_factor = 3;  // (1 - 4)
+}
+
+message IndexedTransitions {
+  // List of Crops.
+  message Transition {
+    message Crop {
+      Rect rect = 1;
+      int32 crop_index = 2;
+    }
+    repeated Crop crops = 1;
+  }
+
+  repeated int32 starting_index = 1;  // (or timestamp)
+  // Transitions are associated with the starting indices above.
+  repeated Transition transition = 2;
+}
+
+message IndexedTransitionsResponse {
+  // Nonnegative crop_index of transition selected by camera to execute, or -1
+  // in the case of an error, where the camera should stop moving and return
+  // the current crop rect.
+  int32 chosen_starting_index = 1;
+  // In the case that there is some error, the camera should return its current
+  // crop.
+  Rect current_position = 2;
+}
+
+message CurrentPtzCrop {
+  Rect current_crop = 1;
+}