Stop existing CursorHandler when a new one is created

1. Add error handling in CursorHandler when read fails.
2. Stop the existing CursorHandler if a new one is created.

Bug: 352477738
Test: suspend&resume and check if cursor is still moving
Change-Id: Ib4ebd1bf53730508ec78a8b657bc7cbdf04f32e9
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index 7a69c07..c2b1fa8 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -83,7 +83,7 @@
     private static final boolean DEBUG = true;
     private ExecutorService mExecutorService;
     private VirtualMachine mVirtualMachine;
-    private ParcelFileDescriptor mCursorStream;
+    private CursorHandler mCursorHandler;
     private ClipboardManager mClipboardManager;
     private static final int RECORD_AUDIO_PERMISSION_REQUEST_CODE = 101;
 
@@ -414,9 +414,11 @@
                                 try {
                                     ParcelFileDescriptor[] pfds =
                                             ParcelFileDescriptor.createSocketPair();
-                                    mExecutorService.execute(
-                                            new CursorHandler(cursorSurfaceView, pfds[0]));
-                                    mCursorStream = pfds[0];
+                                    if (mCursorHandler != null) {
+                                        mCursorHandler.interrupt();
+                                    }
+                                    mCursorHandler = new CursorHandler(cursorSurfaceView, pfds[0]);
+                                    mCursorHandler.start();
                                     runWithDisplayService(
                                             (service) -> service.setCursorStream(pfds[1]));
                                 } catch (Exception e) {
@@ -646,7 +648,7 @@
         }
     }
 
-    static class CursorHandler implements Runnable {
+    static class CursorHandler extends Thread {
         private final SurfaceView mSurfaceView;
         private final ParcelFileDescriptor mStream;
 
@@ -662,6 +664,10 @@
                 ByteBuffer byteBuffer = ByteBuffer.allocate(8 /* (x: u32, y: u32) */);
                 byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
                 while (true) {
+                    if (Thread.interrupted()) {
+                        Log.d(TAG, "interrupted: exiting CursorHandler");
+                        return;
+                    }
                     byteBuffer.clear();
                     int bytes =
                             IoBridge.read(
@@ -669,6 +675,10 @@
                                     byteBuffer.array(),
                                     0,
                                     byteBuffer.array().length);
+                    if (bytes == -1) {
+                        Log.e(TAG, "cannot read from cursor stream, stop the handler");
+                        return;
+                    }
                     float x = (float) (byteBuffer.getInt() & 0xFFFFFFFF);
                     float y = (float) (byteBuffer.getInt() & 0xFFFFFFFF);
                     mSurfaceView.post(