From e5107a36b0547135791bfe2b692898994ef0887d Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Tue, 31 May 2016 15:40:58 -0400 Subject: [PATCH] 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 --- .../android/systemui/qs/PagedTileLayout.java | 51 +++++++++++++++++++ .../com/android/systemui/qs/QSContainer.java | 5 +- .../src/com/android/systemui/qs/QSPanel.java | 10 ++-- .../src/com/android/systemui/qs/QSTile.java | 28 +++++++++- .../com/android/systemui/qs/QuickQSPanel.java | 13 +++++ .../com/android/systemui/qs/TileLayout.java | 15 ++++++ .../qs/customize/TileQueryHelper.java | 4 +- 7 files changed, 118 insertions(+), 8 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index f07e8fccd894f..cf96457ce09c6 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 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { 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 class PagedTileLayout extends ViewPager implements QSTileLayout { 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 && @@ -77,6 +82,52 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { super.setCurrentItem(item, smoothScroll); } + @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 ef7556267e0cd..8d6e17e2622b8 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 @@ public class QSContainer extends FrameLayout { 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 class QSContainer extends FrameLayout { public void setExpanded(boolean expanded) { if (DEBUG) Log.d(TAG, "setExpanded " + expanded); mQsExpanded = expanded; + mQSPanel.setListening(mListening && mQsExpanded); updateQsState(); } @@ -227,8 +229,9 @@ public class QSContainer extends FrameLayout { 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 0e8d76ac50bd5..6945176be7d38 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 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { 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 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { 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 class QSPanel extends LinearLayout implements Tunable, Callback { 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 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { } }; r.tileView.init(click, longClick); - r.tile.setListening(mListening); callback.onStateChanged(r.tile.getState()); r.tile.refreshState(); mRecords.add(r); @@ -533,5 +533,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { 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 0cc30a8642eae..8d9f23fb9242a 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.graphics.drawable.Drawable; 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 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; * handleUpdateState. Callbacks affecting state should use refreshState to trigger another * state update pass on tile looper. */ -public abstract class QSTile implements Listenable { +public abstract class QSTile { protected final String TAG = "Tile." + getClass().getSimpleName(); protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG); @@ -71,6 +72,7 @@ public abstract class QSTile implements Listenable { protected final Context mContext; protected final H mHandler; protected final Handler mUiHandler = new Handler(Looper.getMainLooper()); + private final ArraySet mListeners = new ArraySet<>(); private final ArrayList mCallbacks = new ArrayList<>(); protected TState mState = newTileState(); @@ -97,6 +99,24 @@ public abstract class QSTile implements Listenable { 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 @@ public abstract class QSTile implements Listenable { handleRefreshState(null); } + protected abstract void setListening(boolean listening); + protected void handleDestroy() { setListening(false); mCallbacks.clear(); @@ -312,6 +334,7 @@ public abstract class QSTile implements Listenable { 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 @@ public abstract class QSTile implements Listenable { } 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 4accc8b7d1ef9..b28d0f200e2a1 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 @@ public class QuickQSPanel extends QSPanel { removeView((View) mTileLayout); } mTileLayout = new HeaderTileLayout(context); + mTileLayout.setListening(mListening); addView((View) mTileLayout, 1 /* Between brightness and footer */); } @@ -147,6 +148,7 @@ public class QuickQSPanel extends QSPanel { private final Space mEndSpacer; protected final ArrayList mRecords = new ArrayList<>(); + private boolean mListening; public HeaderTileLayout(Context context) { super(context); @@ -175,6 +177,15 @@ public class QuickQSPanel extends QSPanel { mEndSpacer.setLayoutParams(params); } + @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 */, @@ -183,6 +194,7 @@ public class QuickQSPanel extends QSPanel { 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 @@ public class QuickQSPanel extends QSPanel { // 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 a578e6c9cb9e5..a5a1eaaf6662c 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 @@ public class TileLayout extends ViewGroup implements QSTileLayout { protected final ArrayList mRecords = new ArrayList<>(); private int mCellMarginTop; + private boolean mListening; public TileLayout(Context context) { this(context, null); @@ -41,18 +42,32 @@ public class TileLayout extends ViewGroup implements QSTileLayout { 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 fb76918c644de..8ec6a2f66e1ae 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 @@ public class TileQueryHelper { 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() {