Do not pass in anon callback.

The anon callback gets deferenced after the first few calls. Make sure
that it is a class field. Also update the documentation to reflect this.

There are no known bugs due to this, but proactively fixing this to
avoid unintended behavior.

Bug: 267821080
Test: add logs to see if the callbacks are called continuously.
onBiometricRunningStateChanged is called pretty much every time we go to
LS and leave LS.

Change-Id: If7fb2450f9025b85a30a10612966561c020ec865
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 739cd3fb..9023001 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -3620,7 +3620,9 @@
      * Register to receive notifications about general keyguard information
      * (see {@link KeyguardUpdateMonitorCallback}.
      *
-     * @param callback The callback to register
+     * @param callback The callback to register. Stay away from passing anonymous instances
+     *                 as they will likely be dereferenced. Ensure that the callback is a class
+     *                 field to persist it.
      */
     public void registerCallback(KeyguardUpdateMonitorCallback callback) {
         Assert.isMainThread();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index c709fd1..6d8a849 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -122,21 +122,24 @@
     val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
     val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
 
-    init {
-        keyguardUpdateMonitor.registerCallback(
-            object : KeyguardUpdateMonitorCallback() {
-                override fun onBiometricRunningStateChanged(
-                    running: Boolean,
-                    biometricSourceType: BiometricSourceType?
-                ) {
-                    updateSideFpsVisibility()
-                }
+    /**
+     * This callback needs to be a class field so it does not get garbage collected.
+     */
+    val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
+        override fun onBiometricRunningStateChanged(
+            running: Boolean,
+            biometricSourceType: BiometricSourceType?
+        ) {
+            updateSideFpsVisibility()
+        }
 
-                override fun onStrongAuthStateChanged(userId: Int) {
-                    updateSideFpsVisibility()
-                }
-            }
-        )
+        override fun onStrongAuthStateChanged(userId: Int) {
+            updateSideFpsVisibility()
+        }
+    }
+
+    init {
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
     }
 
     // TODO(b/243685699): Move isScrimmed logic to data layer.