diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java index ba6373c5bd20c..b84d9ce147d62 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalHostViewController.java @@ -38,6 +38,8 @@ import com.google.common.util.concurrent.ListenableFuture; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -55,7 +57,8 @@ public class CommunalHostViewController extends ViewController private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final KeyguardStateController mKeyguardStateController; private final StatusBarStateController mStatusBarStateController; - private WeakReference mLastSource; + private WeakReference mCurrentSource; + private Optional mLastRequest = Optional.empty(); private int mState; private float mQsExpansion; private float mShadeExpansion; @@ -78,6 +81,37 @@ public class CommunalHostViewController extends ViewController private ViewController mCommunalViewController; + private static class ShowRequest { + private boolean mShouldShow; + private WeakReference mSource; + + ShowRequest(boolean shouldShow, WeakReference source) { + mShouldShow = shouldShow; + mSource = source; + } + + CommunalSource getSource() { + return mSource != null ? mSource.get() : null; + } + + boolean shouldShow() { + return mShouldShow; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ShowRequest)) return false; + ShowRequest that = (ShowRequest) o; + return mShouldShow == that.mShouldShow && Objects.equals(getSource(), that.getSource()); + } + + @Override + public int hashCode() { + return Objects.hash(mShouldShow, mSource); + } + } + private KeyguardUpdateMonitorCallback mKeyguardUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -253,18 +287,26 @@ public class CommunalHostViewController extends ViewController } private void showSource() { + final ShowRequest request = new ShowRequest( + (mState & SHOW_COMMUNAL_VIEW_REQUIRED_STATES) == SHOW_COMMUNAL_VIEW_REQUIRED_STATES + && (mState & SHOW_COMMUNAL_VIEW_INVALID_STATES) == 0 + && mCurrentSource != null, + mCurrentSource); + + if (mLastRequest.isPresent() && Objects.equals(mLastRequest.get(), request)) { + return; + } + + mLastRequest = Optional.of(request); + // Make sure all necessary states are present for showing communal and all invalid states // are absent mMainExecutor.execute(() -> { - final CommunalSource currentSource = mLastSource != null ? mLastSource.get() : null; - if (DEBUG) { - Log.d(TAG, "showSource. currentSource:" + currentSource); + Log.d(TAG, "showSource. currentSource:" + request.getSource()); } - if ((mState & SHOW_COMMUNAL_VIEW_REQUIRED_STATES) == SHOW_COMMUNAL_VIEW_REQUIRED_STATES - && (mState & SHOW_COMMUNAL_VIEW_INVALID_STATES) == 0 - && currentSource != null) { + if (request.shouldShow()) { mView.removeAllViews(); // Make view visible. @@ -273,7 +315,7 @@ public class CommunalHostViewController extends ViewController final Context context = mView.getContext(); final ListenableFuture listenableFuture = - currentSource.requestCommunalView(context); + request.getSource().requestCommunalView(context); if (listenableFuture == null) { Log.e(TAG, "could not request communal view"); @@ -308,7 +350,7 @@ public class CommunalHostViewController extends ViewController * @param source The new {@link CommunalSource}, {@code null} if not set. */ public void show(WeakReference source) { - mLastSource = source; + mCurrentSource = source; showSource(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 09eb5c4bea6f6..4ab6e92ca1be3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -4583,8 +4583,6 @@ public class NotificationPanelViewController extends PanelViewController { mStatusBarStateController.removeCallback(mStatusBarStateListener); mConfigurationController.removeCallback(mConfigurationListener); mCommunalSourceMonitor.removeCallback(mCommunalSourceMonitorCallback); - // Clear source when detached. - setCommunalSource(null /*source*/); mFalsingManager.removeTapListener(mFalsingTapListener); mCommunalStateController.removeCallback(mCommunalStateCallback); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewControllerTest.java index 3b750e7c1c2d4..ea00c6f7fb104 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalHostViewControllerTest.java @@ -16,7 +16,9 @@ package com.android.systemui.communal; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -226,4 +228,18 @@ public class CommunalHostViewControllerTest extends SysuiTestCase { verify(mChildView).setAlpha(alpha); verify(mCommunalView).setAlpha(alpha); } + + @Test + public void testMultipleShowRequestSuppression() { + // Ensure first request invokes source. + mController.show(new WeakReference<>(mCommunalSource)); + mFakeExecutor.runAllReady(); + verify(mCommunalSource).requestCommunalView(any()); + clearInvocations(mCommunalSource); + + // Ensure subsequent identical request is suppressed + mController.show(new WeakReference<>(mCommunalSource)); + mFakeExecutor.runAllReady(); + verify(mCommunalSource, never()).requestCommunalView(any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index 38341b83446ab..f6e06cc6a59b9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -874,8 +874,6 @@ public class NotificationPanelViewTest extends SysuiTestCase { clearInvocations(mCommunalHostViewController); givenViewDetached(); verify(mCommunalSourceMonitor).removeCallback(any()); - verify(mCommunalHostViewController).show(sourceCapture.capture()); - assertThat(sourceCapture.getValue()).isEqualTo(null); } @Test