Use ScopedLocalRef in InputEvent jni function

This CL updates some jni functions that manipulate Key and Motion events
to use ScopedLocalRef instead of plain jobject for better life-cycle
tracking.

Test: presubmit
Bug: 324375527
Change-Id: I154b0606d3c0912f0df7a890faf7246b575863f5
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index a883144..f1b93db 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -371,7 +371,7 @@
                 }
             }
 
-            jobject inputEventObj;
+            ScopedLocalRef<jobject> inputEventObj(env);
             switch (inputEvent->getType()) {
                 case InputEventType::KEY:
                     if (kDebugDispatchCycle) {
@@ -447,20 +447,19 @@
 
             default:
                 assert(false); // InputConsumer should prevent this from ever happening
-                inputEventObj = nullptr;
             }
 
-            if (inputEventObj) {
+            if (inputEventObj.get()) {
                 if (kDebugDispatchCycle) {
                     ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName().c_str());
                 }
                 env->CallVoidMethod(receiverObj.get(),
-                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
+                                    gInputEventReceiverClassInfo.dispatchInputEvent, seq,
+                                    inputEventObj.get());
                 if (env->ExceptionCheck()) {
                     ALOGE("Exception dispatching input event.");
                     skipCallbacks = true;
                 }
-                env->DeleteLocalRef(inputEventObj);
             } else {
                 ALOGW("channel '%s' ~ Failed to obtain event object.",
                         getInputChannelName().c_str());
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index 3325e89..2b19ddf 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -219,10 +219,10 @@
         result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL);
         if (result) {
             for (size_t i = 0; i < events.size(); i++) {
-                jobject keyEventObj = android_view_KeyEvent_obtainAsCopy(env, events.itemAt(i));
-                if (!keyEventObj) break; // threw OOM exception
-                env->SetObjectArrayElement(result, jsize(i), keyEventObj);
-                env->DeleteLocalRef(keyEventObj);
+                ScopedLocalRef<jobject> keyEventObj =
+                        android_view_KeyEvent_obtainAsCopy(env, events.itemAt(i));
+                if (!keyEventObj.get()) break; // threw OOM exception
+                env->SetObjectArrayElement(result, jsize(i), keyEventObj.get());
             }
         }
     }
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index 908ab5e..ca8752f 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -94,21 +94,23 @@
 
 // ----------------------------------------------------------------------------
 
-jobject android_view_KeyEvent_obtainAsCopy(JNIEnv* env, const KeyEvent& event) {
+ScopedLocalRef<jobject> android_view_KeyEvent_obtainAsCopy(JNIEnv* env, const KeyEvent& event) {
     ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event.getHmac());
-    jobject eventObj =
-            env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
-                                        event.getId(), event.getDownTime(), event.getEventTime(),
-                                        event.getAction(), event.getKeyCode(),
-                                        event.getRepeatCount(), event.getMetaState(),
-                                        event.getDeviceId(), event.getScanCode(), event.getFlags(),
-                                        event.getSource(), event.getDisplayId(), hmac.get(),
-                                        nullptr);
+    ScopedLocalRef<jobject>
+            eventObj(env,
+                     env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
+                                                 gKeyEventClassInfo.obtain, event.getId(),
+                                                 event.getDownTime(), event.getEventTime(),
+                                                 event.getAction(), event.getKeyCode(),
+                                                 event.getRepeatCount(), event.getMetaState(),
+                                                 event.getDeviceId(), event.getScanCode(),
+                                                 event.getFlags(), event.getSource(),
+                                                 event.getDisplayId(), hmac.get(), nullptr));
     if (env->ExceptionCheck()) {
         ALOGE("An exception occurred while obtaining a key event.");
         LOGE_EX(env);
         env->ExceptionClear();
-        return NULL;
+        return ScopedLocalRef<jobject>(env);
     }
     return eventObj;
 }
diff --git a/core/jni/android_view_KeyEvent.h b/core/jni/android_view_KeyEvent.h
index eab7c97..838f013 100644
--- a/core/jni/android_view_KeyEvent.h
+++ b/core/jni/android_view_KeyEvent.h
@@ -17,17 +17,20 @@
 #ifndef _ANDROID_VIEW_KEYEVENT_H
 #define _ANDROID_VIEW_KEYEVENT_H
 
-#include "jni.h"
+#include <nativehelper/scoped_local_ref.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
 
+#include "jni.h"
+
 namespace android {
 
 class KeyEvent;
 
 /* Obtains an instance of a DVM KeyEvent object as a copy of a native KeyEvent instance.
  * Returns NULL on error. */
-extern jobject android_view_KeyEvent_obtainAsCopy(JNIEnv* env, const KeyEvent& event);
+extern ScopedLocalRef<jobject> android_view_KeyEvent_obtainAsCopy(JNIEnv* env,
+                                                                  const KeyEvent& event);
 
 /* Copies the contents of a DVM KeyEvent object to a native KeyEvent instance.
  * Returns non-zero on error. */
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 33fbdb8..285dee3 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -77,25 +77,28 @@
             env->GetLongField(eventObj, gMotionEventClassInfo.mNativePtr));
 }
 
-static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
-        MotionEvent* event) {
-    env->SetLongField(eventObj, gMotionEventClassInfo.mNativePtr,
-            reinterpret_cast<jlong>(event));
+static void android_view_MotionEvent_setNativePtr(JNIEnv* env, ScopedLocalRef<jobject>& eventObj,
+                                                  MotionEvent* event) {
+    env->SetLongField(eventObj.get(), gMotionEventClassInfo.mNativePtr,
+                      reinterpret_cast<jlong>(event));
 }
 
-jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent& event) {
+ScopedLocalRef<jobject> android_view_MotionEvent_obtainAsCopy(JNIEnv* env,
+                                                              const MotionEvent& event) {
     std::unique_ptr<MotionEvent> destEvent = std::make_unique<MotionEvent>();
     destEvent->copyFrom(&event, true);
     return android_view_MotionEvent_obtainFromNative(env, std::move(destEvent));
 }
 
-jobject android_view_MotionEvent_obtainFromNative(JNIEnv* env, std::unique_ptr<MotionEvent> event) {
+ScopedLocalRef<jobject> android_view_MotionEvent_obtainFromNative(
+        JNIEnv* env, std::unique_ptr<MotionEvent> event) {
     if (event == nullptr) {
-        return nullptr;
+        return ScopedLocalRef<jobject>(env);
     }
-    jobject eventObj =
-            env->CallStaticObjectMethod(gMotionEventClassInfo.clazz, gMotionEventClassInfo.obtain);
-    if (env->ExceptionCheck() || !eventObj) {
+    ScopedLocalRef<jobject> eventObj(env,
+                                     env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
+                                                                 gMotionEventClassInfo.obtain));
+    if (env->ExceptionCheck() || !eventObj.get()) {
         LOGE_EX(env);
         LOG_ALWAYS_FATAL("An exception occurred while obtaining a Java motion event.");
     }
diff --git a/core/jni/android_view_MotionEvent.h b/core/jni/android_view_MotionEvent.h
index e812136..b1bf1c4 100644
--- a/core/jni/android_view_MotionEvent.h
+++ b/core/jni/android_view_MotionEvent.h
@@ -17,21 +17,24 @@
 #ifndef _ANDROID_VIEW_MOTIONEVENT_H
 #define _ANDROID_VIEW_MOTIONEVENT_H
 
-#include "jni.h"
+#include <nativehelper/scoped_local_ref.h>
 #include <utils/Errors.h>
 
+#include "jni.h"
+
 namespace android {
 
 class MotionEvent;
 
 /* Obtains an instance of a DVM MotionEvent object as a copy of a native MotionEvent instance.
  * Returns NULL on error. */
-extern jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent& event);
+extern ScopedLocalRef<jobject> android_view_MotionEvent_obtainAsCopy(JNIEnv* env,
+                                                                     const MotionEvent& event);
 
 /* Obtains an instance of a Java MotionEvent object, taking over the ownership of the provided
  * native MotionEvent instance. Crashes on error. */
-extern jobject android_view_MotionEvent_obtainFromNative(JNIEnv* env,
-                                                         std::unique_ptr<MotionEvent> event);
+extern ScopedLocalRef<jobject> android_view_MotionEvent_obtainFromNative(
+        JNIEnv* env, std::unique_ptr<MotionEvent> event);
 
 /* Gets the underlying native MotionEvent instance within a DVM MotionEvent object.
  * Returns NULL if the event is NULL or if it is uninitialized. */
diff --git a/core/jni/android_view_MotionPredictor.cpp b/core/jni/android_view_MotionPredictor.cpp
index de3e81c..0707e99 100644
--- a/core/jni/android_view_MotionPredictor.cpp
+++ b/core/jni/android_view_MotionPredictor.cpp
@@ -61,7 +61,8 @@
     MotionPredictor* predictor = reinterpret_cast<MotionPredictor*>(ptr);
     return android_view_MotionEvent_obtainFromNative(env,
                                                      predictor->predict(static_cast<nsecs_t>(
-                                                             predictionTimeNanos)));
+                                                             predictionTimeNanos)))
+            .release();
 }
 
 static jboolean android_view_MotionPredictor_nativeIsPredictionAvailable(JNIEnv* env, jclass clazz,
diff --git a/native/android/input.cpp b/native/android/input.cpp
index 4708e69..53699bc 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -321,11 +321,13 @@
         case AINPUT_EVENT_TYPE_MOTION:
             return android::android_view_MotionEvent_obtainAsCopy(env,
                                                                   static_cast<const MotionEvent&>(
-                                                                          *aInputEvent));
+                                                                          *aInputEvent))
+                    .release();
         case AINPUT_EVENT_TYPE_KEY:
             return android::android_view_KeyEvent_obtainAsCopy(env,
                                                                static_cast<const KeyEvent&>(
-                                                                       *aInputEvent));
+                                                                       *aInputEvent))
+                    .release();
         default:
             LOG_ALWAYS_FATAL("Unexpected event type %d in AInputEvent_toJava.", eventType);
     }
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 93c0c62..2150eb3 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1509,15 +1509,14 @@
     ScopedLocalRef<jobject> inputEventObj(env);
     switch (inputEvent.getType()) {
         case InputEventType::KEY:
-            inputEventObj.reset(
+            inputEventObj =
                     android_view_KeyEvent_obtainAsCopy(env,
-                                                       static_cast<const KeyEvent&>(inputEvent)));
+                                                       static_cast<const KeyEvent&>(inputEvent));
             break;
         case InputEventType::MOTION:
-            inputEventObj.reset(
-                    android_view_MotionEvent_obtainAsCopy(env,
-                                                          static_cast<const MotionEvent&>(
-                                                                  inputEvent)));
+            inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
+                                                                  static_cast<const MotionEvent&>(
+                                                                          inputEvent));
             break;
         default:
             return true; // dispatch the event normally
@@ -1559,7 +1558,7 @@
 
     const nsecs_t when = keyEvent.getEventTime();
     JNIEnv* env = jniEnv();
-    ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_obtainAsCopy(env, keyEvent));
+    ScopedLocalRef<jobject> keyEventObj = android_view_KeyEvent_obtainAsCopy(env, keyEvent);
     if (!keyEventObj.get()) {
         ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
         return;
@@ -1639,7 +1638,7 @@
 
     // Token may be null
     ScopedLocalRef<jobject> tokenObj(env, javaObjectForIBinder(env, token));
-    ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_obtainAsCopy(env, keyEvent));
+    ScopedLocalRef<jobject> keyEventObj = android_view_KeyEvent_obtainAsCopy(env, keyEvent);
     if (!keyEventObj.get()) {
         ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         return 0;
@@ -1670,7 +1669,7 @@
 
     // Note: tokenObj may be null.
     ScopedLocalRef<jobject> tokenObj(env, javaObjectForIBinder(env, token));
-    ScopedLocalRef<jobject> keyEventObj(env, android_view_KeyEvent_obtainAsCopy(env, keyEvent));
+    ScopedLocalRef<jobject> keyEventObj = android_view_KeyEvent_obtainAsCopy(env, keyEvent);
     if (!keyEventObj.get()) {
         ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
         return {};