QS: Only put visible tiles in listening state
- Make it so the QSPanel doesn't listen until expansion starts
- Push listening state through the TileLayout
- Make PagedTileLayout only listen for visible pages
- Push setListening onto background thread
Change-Id: Id7c008c9447f9a5dac69469fef72bc580f423b0c
Fixes: 28962155
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index f07e8fc..cf96457 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -31,6 +31,10 @@
private View mDecorGroup;
private PageListener mPageListener;
+ private int mPosition;
+ private boolean mOffPage;
+ private boolean mListening;
+
public PagedTileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setAdapter(mAdapter);
@@ -48,6 +52,7 @@
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (mPageIndicator == null) return;
+ setCurrentPage(position, positionOffset != 0);
mPageIndicator.setLocation(position + positionOffset);
if (mPageListener != null) {
mPageListener.onPageChanged(positionOffsetPixels == 0 &&
@@ -78,6 +83,52 @@
}
@Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (mListening) {
+ mPages.get(mPosition).setListening(listening);
+ if (mOffPage) {
+ mPages.get(mPosition + 1).setListening(listening);
+ }
+ } else {
+ // Make sure no pages are listening.
+ for (int i = 0; i < mPages.size(); i++) {
+ mPages.get(i).setListening(false);
+ }
+ }
+ }
+
+ /**
+ * Sets individual pages to listening or not. If offPage it will set
+ * the next page after position to listening as well since we are in between
+ * pages.
+ */
+ private void setCurrentPage(int position, boolean offPage) {
+ if (mPosition == position && mOffPage == offPage) return;
+ if (mListening) {
+ if (mPosition != position) {
+ // Clear out the last pages from listening.
+ mPages.get(mPosition).setListening(false);
+ if (mOffPage) {
+ mPages.get(mPosition + 1).setListening(false);
+ }
+ // Set the new pages to listening
+ mPages.get(position).setListening(true);
+ if (offPage) {
+ mPages.get(position + 1).setListening(true);
+ }
+ } else if (mOffPage != offPage) {
+ // Whether we are showing position + 1 has changed.
+ mPages.get(mPosition + 1).setListening(offPage);
+ }
+ }
+ // Save the current state.
+ mPosition = position;
+ mOffPage = offPage;
+ }
+
+ @Override
public boolean hasOverlappingRendering() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index ef75562..8d6e17e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -60,6 +60,7 @@
private QSAnimator mQSAnimator;
private QSCustomizer mQSCustomizer;
private NotificationPanelView mPanelView;
+ private boolean mListening;
public QSContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -209,6 +210,7 @@
public void setExpanded(boolean expanded) {
if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
mQsExpanded = expanded;
+ mQSPanel.setListening(mListening && mQsExpanded);
updateQsState();
}
@@ -227,8 +229,9 @@
public void setListening(boolean listening) {
if (DEBUG) Log.d(TAG, "setListening " + listening);
- mQSPanel.setListening(listening);
+ mListening = listening;
mHeader.setListening(listening);
+ mQSPanel.setListening(mListening && mQsExpanded);
}
public void setQsExpansion(float expansion, float headerTranslation) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 0e8d76a..6945176 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -57,7 +57,7 @@
private int mPanelPaddingBottom;
private int mBrightnessPaddingTop;
private boolean mExpanded;
- private boolean mListening;
+ protected boolean mListening;
private Callback mCallback;
private BrightnessController mBrightnessController;
@@ -102,6 +102,7 @@
protected void setupTileLayout() {
mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
R.layout.qs_paged_tile_layout, this, false);
+ mTileLayout.setListening(mListening);
addView((View) mTileLayout);
findViewById(android.R.id.edit).setOnClickListener(view ->
mHost.startRunnableDismissingKeyguard(() -> showEdit(view)));
@@ -230,8 +231,8 @@
public void setListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
- for (TileRecord r : mRecords) {
- r.tile.setListening(mListening);
+ if (mTileLayout != null) {
+ mTileLayout.setListening(listening);
}
mFooter.setListening(mListening);
if (mListening) {
@@ -343,7 +344,6 @@
}
};
r.tileView.init(click, longClick);
- r.tile.setListening(mListening);
callback.onStateChanged(r.tile.getState());
r.tile.refreshState();
mRecords.add(r);
@@ -533,5 +533,7 @@
void removeTile(TileRecord tile);
int getOffsetTop(TileRecord tile);
boolean updateResources();
+
+ void setListening(boolean listening);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 0cc30a8..8d9f23f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -24,6 +24,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
@@ -63,7 +64,7 @@
* handleUpdateState. Callbacks affecting state should use refreshState to trigger another
* state update pass on tile looper.
*/
-public abstract class QSTile<TState extends State> implements Listenable {
+public abstract class QSTile<TState extends State> {
protected final String TAG = "Tile." + getClass().getSimpleName();
protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG);
@@ -71,6 +72,7 @@
protected final Context mContext;
protected final H mHandler;
protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
+ private final ArraySet<Object> mListeners = new ArraySet<>();
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
protected TState mState = newTileState();
@@ -97,6 +99,24 @@
mHandler = new H(host.getLooper());
}
+ /**
+ * Adds or removes a listening client for the tile. If the tile has one or more
+ * listening client it will go into the listening state.
+ */
+ public void setListening(Object listener, boolean listening) {
+ if (listening) {
+ if (mListeners.add(listener) && mListeners.size() == 1) {
+ if (DEBUG) Log.d(TAG, "setListening " + true);
+ mHandler.obtainMessage(H.SET_LISTENING, 1, 0).sendToTarget();
+ }
+ } else {
+ if (mListeners.remove(listener) && mListeners.size() == 0) {
+ if (DEBUG) Log.d(TAG, "setListening " + false);
+ mHandler.obtainMessage(H.SET_LISTENING, 0, 0).sendToTarget();
+ }
+ }
+ }
+
public String getTileSpec() {
return mTileSpec;
}
@@ -279,6 +299,8 @@
handleRefreshState(null);
}
+ protected abstract void setListening(boolean listening);
+
protected void handleDestroy() {
setListening(false);
mCallbacks.clear();
@@ -312,6 +334,7 @@
private static final int DESTROY = 10;
private static final int CLEAR_STATE = 11;
private static final int REMOVE_CALLBACKS = 12;
+ private static final int SET_LISTENING = 13;
private H(Looper looper) {
super(looper);
@@ -364,6 +387,9 @@
} else if (msg.what == CLEAR_STATE) {
name = "handleClearState";
handleClearState();
+ } else if (msg.what == SET_LISTENING) {
+ name = "setListening";
+ setListening(msg.arg1 != 0);
} else {
throw new IllegalArgumentException("Unknown msg: " + msg.what);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 4accc8b..b28d0f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -55,6 +55,7 @@
removeView((View) mTileLayout);
}
mTileLayout = new HeaderTileLayout(context);
+ mTileLayout.setListening(mListening);
addView((View) mTileLayout, 1 /* Between brightness and footer */);
}
@@ -147,6 +148,7 @@
private final Space mEndSpacer;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+ private boolean mListening;
public HeaderTileLayout(Context context) {
super(context);
@@ -176,6 +178,15 @@
}
@Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ for (TileRecord record : mRecords) {
+ record.tile.setListening(this, mListening);
+ }
+ }
+
+ @Override
public void addTile(TileRecord tile) {
addView(tile.tileView, getChildCount() - 1 /* Leave icon at end */,
generateLayoutParams());
@@ -183,6 +194,7 @@
addView(new Space(mContext), getChildCount() - 1 /* Leave icon at end */,
generateSpaceParams());
mRecords.add(tile);
+ tile.tile.setListening(this, mListening);
}
private LayoutParams generateSpaceParams() {
@@ -208,6 +220,7 @@
// Remove its spacer as well.
removeViewAt(childIndex);
mRecords.remove(tile);
+ tile.tile.setListening(this, false);
}
private int getChildIndex(QSTileBaseView tileView) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index a578e6c..a5a1eaa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -25,6 +25,7 @@
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
private int mCellMarginTop;
+ private boolean mListening;
public TileLayout(Context context) {
this(context, null);
@@ -41,18 +42,32 @@
return getTop();
}
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ for (TileRecord record : mRecords) {
+ record.tile.setListening(this, mListening);
+ }
+ }
+
public void addTile(TileRecord tile) {
mRecords.add(tile);
+ tile.tile.setListening(this, mListening);
addView(tile.tileView);
}
@Override
public void removeTile(TileRecord tile) {
mRecords.remove(tile);
+ tile.tile.setListening(this, false);
removeView(tile.tileView);
}
public void removeAllViews() {
+ for (TileRecord record : mRecords) {
+ record.tile.setListening(this, false);
+ }
mRecords.clear();
super.removeAllViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index fb76918..8ec6a2f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -66,10 +66,10 @@
if (tile == null || !tile.isAvailable()) {
continue;
}
- tile.setListening(true);
+ tile.setListening(this, true);
tile.clearState();
tile.refreshState();
- tile.setListening(false);
+ tile.setListening(this, false);
qsHandler.post(new Runnable() {
@Override
public void run() {