USBForward: heartbeat mechanism

Change-Id: I0ff1dd380e4086d3f380f6f337f08a44371c87d2
diff --git a/guest/usbforward/protocol.h b/guest/usbforward/protocol.h
index 45dc05e..c55c3b6 100644
--- a/guest/usbforward/protocol.h
+++ b/guest/usbforward/protocol.h
@@ -67,6 +67,15 @@
   //   - int32_t(actual length)
   //   - int32_t[actual length] bytes
   CmdDataTransfer,
+
+  // Heartbeat is used to detect whether device is alive.
+  // This is a trivial request/response mechanism.
+  // Response status indicates whether server is ready.
+  // Request format:
+  // - RequestHeader{}
+  // Response format:
+  // - ResponseHeader{}
+  CmdHeartbeat,
 };
 
 // Status represents command execution result, using USB/IP compatible values.
@@ -141,4 +150,4 @@
   uint32_t timeout;
 } __attribute__((packed));
 
-}  // namespace usb_forward
\ No newline at end of file
+}  // namespace usb_forward
diff --git a/guest/usbforward/usb_server.cpp b/guest/usbforward/usb_server.cpp
index 3bc05b4..5720571 100644
--- a/guest/usbforward/usb_server.cpp
+++ b/guest/usbforward/usb_server.cpp
@@ -153,6 +153,14 @@
   fd_->Write(&rsp, sizeof(rsp));
 }
 
+void USBServer::HandleHeartbeat(uint32_t tag) {
+  auto handle = GetDevice();
+
+  avd::LockGuard<avd::Mutex> lock(write_mutex_);
+  ResponseHeader rsp{handle ? StatusSuccess : StatusFailure, tag};
+  fd_->Write(&rsp, sizeof(rsp));
+}
+
 void USBServer::HandleControlTransfer(uint32_t tag) {
   ControlTransfer req;
   // If disconnected prematurely, don't send response.
@@ -334,6 +342,11 @@
           HandleDataTransfer(req.tag);
           break;
 
+        case CmdHeartbeat:
+          ALOGV("Processing Heartbeat command, tag=%d", req.tag);
+          HandleHeartbeat(req.tag);
+          break;
+
         default:
           ALOGE("Discarding unknown command %08x, tag=%d", req.command,
                 req.tag);
@@ -342,4 +355,4 @@
   }
 }
 
-}  // namespace usb_forward
\ No newline at end of file
+}  // namespace usb_forward
diff --git a/guest/usbforward/usb_server.h b/guest/usbforward/usb_server.h
index 397ad1a..843436c 100644
--- a/guest/usbforward/usb_server.h
+++ b/guest/usbforward/usb_server.h
@@ -59,6 +59,9 @@
   // Handle CmdDataTransfer request.
   void HandleDataTransfer(uint32_t tag);
 
+  // Handle CmdHeartbeat request.
+  void HandleHeartbeat(uint32_t tag);
+
   // OnAsyncDataTransferComplete handles end of asynchronous data transfer cycle
   // and sends response back to caller.
   void OnTransferComplete(uint32_t tag, bool is_data_in, bool is_success,
@@ -77,4 +80,4 @@
   USBServer& operator=(const USBServer& other) = delete;
 };
 
-}  // namespace usb_forward
\ No newline at end of file
+}  // namespace usb_forward