From 70424ac23e7dd226735c590c085b1f609c7231d1 Mon Sep 17 00:00:00 2001 From: Darrell Shi Date: Fri, 20 Aug 2021 23:01:10 +0000 Subject: [PATCH] Fix input monitor issue. This CL fixes an issue of the communal mode where unlocking the device doesn't properly dispose the touch event listener, and it keeps triggering the callback in personal mode. The issue is fixed by handling the InputEventReceiver and disposing it when no longer needed. Change-Id: I0008ceb3edc9dfdbcbfa09c1f68c11e87d2e1f7f Test: atest IdleHostViewControllerTest#testInputEventReceiverLifecycle Bug: 197365101 --- .../systemui/idle/IdleHostViewController.java | 12 ++++++++--- .../idle/IdleHostViewControllerTest.java | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/idle/IdleHostViewController.java b/packages/SystemUI/src/com/android/systemui/idle/IdleHostViewController.java index 97d32c3db2f1e..192c4184a6eb8 100644 --- a/packages/SystemUI/src/com/android/systemui/idle/IdleHostViewController.java +++ b/packages/SystemUI/src/com/android/systemui/idle/IdleHostViewController.java @@ -39,6 +39,7 @@ import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.ViewController; @@ -139,6 +140,9 @@ public class IdleHostViewController extends ViewController impleme // Monitor for tracking touches for activity. private InputMonitorCompat mInputMonitor; + // Input receiver of touch activities. + private InputChannelCompat.InputEventReceiver mInputEventReceiver; + // Intent filter for receiving dream broadcasts. private IntentFilter mDreamIntentFilter; @@ -335,7 +339,7 @@ public class IdleHostViewController extends ViewController impleme } private void enableIdleMonitoring(boolean enable) { - if (enable && mInputMonitor == null) { + if (enable && mInputMonitor == null && mInputEventReceiver == null) { if (DEBUG) { Log.d(TAG, "enable idle monitoring"); } @@ -345,7 +349,7 @@ public class IdleHostViewController extends ViewController impleme // Monitor - any input should reset timer mInputMonitor = mInputMonitorFactory.getInputMonitor(INPUT_MONITOR_IDENTIFIER); - mInputMonitor.getInputReceiver(mLooper, mChoreographer, + mInputEventReceiver = mInputMonitor.getInputReceiver(mLooper, mChoreographer, v -> { if (DEBUG) { Log.d(TAG, "touch detected, resetting timeout"); @@ -358,7 +362,7 @@ public class IdleHostViewController extends ViewController impleme mCancelEnableIdling = mDelayableExecutor.executeDelayed( mEnableIdlingCallback, mIdleTimeout); }); - } else if (!enable && mInputMonitor != null) { + } else if (!enable && mInputMonitor != null && mInputEventReceiver != null) { if (DEBUG) { Log.d(TAG, "disable idle monitoring"); } @@ -368,7 +372,9 @@ public class IdleHostViewController extends ViewController impleme mCancelEnableIdling = null; } + mInputEventReceiver.dispose(); mInputMonitor.dispose(); + mInputEventReceiver = null; mInputMonitor = null; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/idle/IdleHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/idle/IdleHostViewControllerTest.java index 664072f5967da..a685e20a3c858 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/idle/IdleHostViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/idle/IdleHostViewControllerTest.java @@ -42,6 +42,7 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -76,6 +77,7 @@ public class IdleHostViewControllerTest extends SysuiTestCase { @Mock private Sensor mSensor; @Mock private DreamHelper mDreamHelper; @Mock private InputMonitorCompat mInputMonitor; + @Mock private InputChannelCompat.InputEventReceiver mInputEventReceiver; private final long mTimestamp = Instant.now().toEpochMilli(); private KeyguardStateController.Callback mKeyguardStateCallback; @@ -91,6 +93,7 @@ public class IdleHostViewControllerTest extends SysuiTestCase { when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(mSensor); when(mInputMonitorFactory.getInputMonitor("IdleHostViewController")) .thenReturn(mInputMonitor); + when(mInputMonitor.getInputReceiver(any(), any(), any())).thenReturn(mInputEventReceiver); mController = new IdleHostViewController(mContext, mBroadcastDispatcher, mPowerManager, mSensorManager, mIdleHostView, @@ -231,4 +234,21 @@ public class IdleHostViewControllerTest extends SysuiTestCase { // Verifies it goes to sleep. verify(mPowerManager).goToSleep(anyLong(), anyInt(), anyInt()); } + + @Test + public void testInputEventReceiverLifecycle() { + // Keyguard showing. + when(mKeyguardStateController.isShowing()).thenReturn(true); + mKeyguardStateCallback.onKeyguardShowingChanged(); + + // Should register input event receiver. + verify(mInputMonitor).getInputReceiver(any(), any(), any()); + + // Keyguard dismissed. + when(mKeyguardStateController.isShowing()).thenReturn(false); + mKeyguardStateCallback.onKeyguardShowingChanged(); + + // Should dispose input event receiver. + verify(mInputEventReceiver).dispose(); + } }