Handle gRPC canellation case

there was a crash when onNext() is called 'after' shutdown service in
the guest is shut down. it happens really rarely, but for stability, add
cancellation status check, and callback for the status.

Fix: 398765174
Test: keep calling onNext() and check if there is no exception
Change-Id: I4d023647a1c69cc2f6b029fb05724bf98b99f35d
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
index 887ae02..e035ad4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
@@ -28,6 +28,7 @@
 import com.android.virtualization.terminal.proto.ReportVmActivePortsResponse
 import com.android.virtualization.terminal.proto.ShutdownQueueOpeningRequest
 import com.android.virtualization.terminal.proto.ShutdownRequestItem
+import io.grpc.stub.ServerCallStreamObserver
 import io.grpc.stub.StreamObserver
 
 internal class DebianServiceImpl(context: Context) : DebianServiceImplBase() {
@@ -79,8 +80,15 @@
         request: ShutdownQueueOpeningRequest?,
         responseObserver: StreamObserver<ShutdownRequestItem?>,
     ) {
+        val serverCallStreamObserver = responseObserver as ServerCallStreamObserver<ShutdownRequestItem?>
+        serverCallStreamObserver.setOnCancelHandler {
+            shutdownRunnable = null
+        }
         Log.d(TAG, "openShutdownRequestQueue")
         shutdownRunnable = Runnable {
+            if (serverCallStreamObserver.isCancelled()) {
+                return@Runnable
+            }
             responseObserver.onNext(ShutdownRequestItem.newBuilder().build())
             responseObserver.onCompleted()
             shutdownRunnable = null