Merge "Do not use mStaleListener if tile is listening" into tm-dev
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index f78046d..57193e7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -33,7 +33,7 @@
String ACTION = "com.android.systemui.action.PLUGIN_QS";
- int VERSION = 14;
+ int VERSION = 15;
String TAG = "QS";
@@ -50,6 +50,14 @@
void setOverscrolling(boolean overscrolling);
void setExpanded(boolean qsExpanded);
void setListening(boolean listening);
+
+ /**
+ * Set whether QQS/QS is visible or not.
+ *
+ * This is different from setExpanded, as it will be true when QQS is visible. In particular,
+ * it should be false when device is locked and only notifications (in lockscreen) are visible.
+ */
+ void setQsVisible(boolean qsVisible);
boolean isShowingDetail();
void closeDetail();
void animateHeaderSlidingOut();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f87cb29..a92c99e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -72,6 +72,7 @@
private static final boolean DEBUG = false;
private static final String EXTRA_EXPANDED = "expanded";
private static final String EXTRA_LISTENING = "listening";
+ private static final String EXTRA_VISIBLE = "visible";
private final Rect mQsBounds = new Rect();
private final StatusBarStateController mStatusBarStateController;
@@ -148,6 +149,10 @@
private boolean mOverScrolling;
+ // Whether QQS or QS is visible. When in lockscreen, this is true if and only if QQS or QS is
+ // visible;
+ private boolean mQsVisible;
+
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
QSTileHost qsTileHost,
@@ -224,6 +229,7 @@
mQSCustomizerController.init();
mQSCustomizerController.setQs(this);
if (savedInstanceState != null) {
+ setQsVisible(savedInstanceState.getBoolean(EXTRA_VISIBLE));
setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED));
setListening(savedInstanceState.getBoolean(EXTRA_LISTENING));
setEditLocation(view);
@@ -285,6 +291,7 @@
super.onSaveInstanceState(outState);
outState.putBoolean(EXTRA_EXPANDED, mQsExpanded);
outState.putBoolean(EXTRA_LISTENING, mListening);
+ outState.putBoolean(EXTRA_VISIBLE, mQsVisible);
if (mQSCustomizerController != null) {
mQSCustomizerController.saveInstanceState(outState);
}
@@ -303,6 +310,11 @@
return mQsExpanded;
}
+ @VisibleForTesting
+ boolean isQsVisible() {
+ return mQsVisible;
+ }
+
@Override
public View getHeader() {
return mHeader;
@@ -458,7 +470,7 @@
public void setExpanded(boolean expanded) {
if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
mQsExpanded = expanded;
- mQSPanelController.setListening(mListening, mQsExpanded);
+ updateQsPanelControllerListening();
updateQsState();
}
@@ -486,9 +498,20 @@
public void setListening(boolean listening) {
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
- mQSContainerImplController.setListening(listening);
- mQSFooterActionController.setListening(listening);
- mQSPanelController.setListening(mListening, mQsExpanded);
+ mQSContainerImplController.setListening(listening && mQsVisible);
+ mQSFooterActionController.setListening(listening && mQsVisible);
+ updateQsPanelControllerListening();
+ }
+
+ private void updateQsPanelControllerListening() {
+ mQSPanelController.setListening(mListening && mQsVisible, mQsExpanded);
+ }
+
+ @Override
+ public void setQsVisible(boolean visible) {
+ if (DEBUG) Log.d(TAG, "setQsVisible " + visible);
+ mQsVisible = visible;
+ setListening(mListening);
}
@Override
@@ -836,6 +859,7 @@
indentingPw.println("mHeaderAnimating: " + mHeaderAnimating);
indentingPw.println("mStackScrollerOverscrolling: " + mStackScrollerOverscrolling);
indentingPw.println("mListening: " + mListening);
+ indentingPw.println("mQsVisible: " + mQsVisible);
indentingPw.println("mLayoutDirection: " + mLayoutDirection);
indentingPw.println("mLastQSExpansion: " + mLastQSExpansion);
indentingPw.println("mLastPanelFraction: " + mLastPanelFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 851307a..918c6be 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -161,9 +161,6 @@
/** */
public void setListening(boolean listening, boolean expanded) {
setListening(listening && expanded);
- if (mView.isListening()) {
- refreshAllTiles();
- }
// Set the listening as soon as the QS fragment starts listening regardless of the
//expansion, so it will update the current brightness before the slider is visible.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 93f245b..ec61ea6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -308,12 +308,17 @@
}
void setListening(boolean listening) {
+ if (mView.isListening() == listening) return;
mView.setListening(listening);
if (mView.getTileLayout() != null) {
mQSLogger.logAllTilesChangeListening(listening, mView.getDumpableTag(), mCachedSpecs);
mView.getTileLayout().setListening(listening, mUiEventLogger);
}
+
+ if (mView.isListening()) {
+ refreshAllTiles();
+ }
}
boolean switchTileLayout(boolean force) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index c6ebd73..833573d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -104,15 +104,6 @@
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
}
- @Override
- void setListening(boolean listening) {
- super.setListening(listening);
- }
-
- public boolean isListening() {
- return mView.isListening();
- }
-
private void setMaxTiles(int parseNumTiles) {
mView.setMaxTiles(parseNumTiles);
setTiles();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 2c6972a..ec0d081 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -175,9 +175,6 @@
mListening = listening;
mQuickQSPanelController.setListening(listening);
- if (mQuickQSPanelController.isListening()) {
- mQuickQSPanelController.refreshAllTiles();
- }
if (mQuickQSPanelController.switchTileLayout(false)) {
mView.updateResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index a47bd5c..740e12a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -233,7 +233,13 @@
@VisibleForTesting
protected void handleStale() {
- setListening(mStaleListener, true);
+ if (!mListeners.isEmpty()) {
+ // If the tile is already listening (it's been a long time since it refreshed), just
+ // force a refresh. Don't add the staleListener because there's already a listener there
+ refreshState();
+ } else {
+ setListening(mStaleListener, true);
+ }
}
public String getTileSpec() {
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 960678f..2dbbb145 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -2571,6 +2571,7 @@
mQsClipTop = (int) (top - currentTranslation - mQsFrame.getTop());
mQsClipBottom = (int) (bottom - currentTranslation - mQsFrame.getTop());
mQsVisible = qsVisible;
+ mQs.setQsVisible(mQsVisible);
mQs.setFancyClipping(
mQsClipTop,
mQsClipBottom,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index a518b80..664af75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -20,6 +20,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -161,6 +163,7 @@
QSFragment qs = (QSFragment) mFragment;
qs.setListening(true);
qs.setExpanded(true);
+ qs.setQsVisible(true);
processAllMessages();
recreateFragment();
processAllMessages();
@@ -169,6 +172,7 @@
qs = (QSFragment) mFragment;
assertTrue(qs.isListening());
assertTrue(qs.isExpanded());
+ assertTrue(qs.isQsVisible());
}
@Test
@@ -333,6 +337,54 @@
assertThat(mQsFragmentView.getTranslationY()).isEqualTo(0);
}
+ @Test
+ public void setListeningFalse_notVisible() {
+ QSFragment fragment = resumeAndGetFragment();
+ fragment.setQsVisible(false);
+ clearInvocations(mQSContainerImplController, mQSPanelController, mQSFooterActionController);
+
+ fragment.setListening(false);
+ verify(mQSContainerImplController).setListening(false);
+ verify(mQSFooterActionController).setListening(false);
+ verify(mQSPanelController).setListening(eq(false), anyBoolean());
+ }
+
+ @Test
+ public void setListeningTrue_notVisible() {
+ QSFragment fragment = resumeAndGetFragment();
+ fragment.setQsVisible(false);
+ clearInvocations(mQSContainerImplController, mQSPanelController, mQSFooterActionController);
+
+ fragment.setListening(true);
+ verify(mQSContainerImplController).setListening(false);
+ verify(mQSFooterActionController).setListening(false);
+ verify(mQSPanelController).setListening(eq(false), anyBoolean());
+ }
+
+ @Test
+ public void setListeningFalse_visible() {
+ QSFragment fragment = resumeAndGetFragment();
+ fragment.setQsVisible(true);
+ clearInvocations(mQSContainerImplController, mQSPanelController, mQSFooterActionController);
+
+ fragment.setListening(false);
+ verify(mQSContainerImplController).setListening(false);
+ verify(mQSFooterActionController).setListening(false);
+ verify(mQSPanelController).setListening(eq(false), anyBoolean());
+ }
+
+ @Test
+ public void setListeningTrue_visible() {
+ QSFragment fragment = resumeAndGetFragment();
+ fragment.setQsVisible(true);
+ clearInvocations(mQSContainerImplController, mQSPanelController, mQSFooterActionController);
+
+ fragment.setListening(true);
+ verify(mQSContainerImplController).setListening(true);
+ verify(mQSFooterActionController).setListening(true);
+ verify(mQSPanelController).setListening(eq(true), anyBoolean());
+ }
+
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 4dbf3d8..c127a6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -137,6 +137,10 @@
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
when(mQSPanel.getResources()).thenReturn(mResources);
when(mResources.getConfiguration()).thenReturn(mConfiguration);
+ doAnswer(invocation -> {
+ when(mQSPanel.isListening()).thenReturn(invocation.getArgument(0));
+ return null;
+ }).when(mQSPanel).setListening(anyBoolean());
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 69d3f8b..c0944ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -21,6 +21,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
@@ -62,6 +63,9 @@
whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController)
whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources)
whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false)
+ whenever(qsPanel.setListening(anyBoolean())).then {
+ whenever(qsPanel.isListening).thenReturn(it.getArgument(0))
+ }
controller = QSPanelController(
qsPanel,
@@ -100,7 +104,6 @@
controller.setTiles()
whenever(tile.isListening()).thenReturn(false)
whenever(otherTile.isListening()).thenReturn(true)
- whenever(qsPanel.isListening).thenReturn(true)
controller.setListening(true, true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index c31a971..5336ef0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -379,6 +379,34 @@
assertFalse(mTile.isListening());
}
+ @Test
+ public void testStaleTriggeredWhileListening() throws Exception {
+ Object o = new Object();
+ mTile.clearRefreshes();
+
+ mTile.setListening(o, true); // +1 refresh
+ mTestableLooper.processAllMessages();
+
+ mTestableLooper.runWithLooper(() -> mTile.handleStale()); // +1 refresh
+ mTestableLooper.processAllMessages();
+
+ mTile.setListening(o, false);
+ mTestableLooper.processAllMessages();
+ assertFalse(mTile.isListening());
+ assertThat(mTile.mRefreshes).isEqualTo(2);
+ }
+
+ @Test
+ public void testStaleTriggeredWhileNotListening() throws Exception {
+ mTile.clearRefreshes();
+
+ mTestableLooper.runWithLooper(() -> mTile.handleStale()); // +1 refresh
+ mTestableLooper.processAllMessages();
+
+ assertFalse(mTile.isListening());
+ assertThat(mTile.mRefreshes).isEqualTo(1);
+ }
+
private void assertEvent(UiEventLogger.UiEventEnum eventType,
UiEventLoggerFake.FakeUiEvent fakeEvent) {
assertEquals(eventType.getId(), fakeEvent.eventId);
@@ -418,9 +446,9 @@
return mInvalid;
}
}
-
private static class TileImpl extends QSTileImpl<QSTile.BooleanState> {
boolean mClicked;
+ int mRefreshes = 0;
protected TileImpl(
QSHost host,
@@ -453,6 +481,11 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
+ mRefreshes++;
+ }
+
+ void clearRefreshes() {
+ mRefreshes = 0;
}
@Override