Merge "Protect against receiving partial key event sequences." into main
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 38ab590..71066ac 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -433,7 +433,8 @@
                         mTrackingConfirmKey = event.getKeyCode();
                     }
                     case KeyEvent.ACTION_UP -> {
-                        if (mTrackingConfirmKey != event.getKeyCode()) {
+                        if (mTrackingConfirmKey == null
+                                || mTrackingConfirmKey != event.getKeyCode()) {
                             return true;
                         }
 
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
index 1322545..b98af6b 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
@@ -37,6 +37,7 @@
 import android.service.dreams.Flags;
 import android.service.dreams.IDreamOverlayCallback;
 import android.testing.TestableLooper;
+import android.view.KeyEvent;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -181,4 +182,15 @@
         environment.advance(TestDreamEnvironment.DREAM_STATE_WOKEN);
         verify(environment.getDreamOverlayClient()).onWakeRequested();
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_HANDLES_CONFIRM_KEYS)
+    public void testPartialKeyHandling() throws Exception {
+        TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .build();
+        environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED);
+
+        // Ensure service does not crash from only receiving up event.
+        environment.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE));
+    }
 }
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
index ef85ba5..3d03bf2 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
@@ -46,6 +46,7 @@
 import android.service.dreams.IDreamOverlayClient;
 import android.service.dreams.IDreamService;
 import android.testing.TestableLooper;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowInsetsController;
@@ -390,6 +391,13 @@
         }
     }
 
+    /**
+     * Sends a key event to the dream.
+     */
+    public void dispatchKeyEvent(KeyEvent event) {
+        mService.dispatchKeyEvent(event);
+    }
+
     private void wakeDream() throws RemoteException {
         mService.wakeUp();
     }