OSDN Git Service

QS: Only put visible tiles in listening state
authorJason Monk <jmonk@google.com>
Tue, 31 May 2016 19:40:58 +0000 (15:40 -0400)
committerJason Monk <jmonk@google.com>
Tue, 31 May 2016 19:49:35 +0000 (15:49 -0400)
 - 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

packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
packages/SystemUI/src/com/android/systemui/qs/QSTile.java
packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java

index f07e8fc..cf96457 100644 (file)
@@ -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 &&
@@ -78,6 +83,52 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
     }
 
     @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;
     }
index ef75562..8d6e17e 100644 (file)
@@ -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) {
index 0e8d76a..6945176 100644 (file)
@@ -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);
     }
 }
index 0cc30a8..8d9f23f 100644 (file)
@@ -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<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 @@ public abstract class QSTile<TState extends State> implements Listenable {
     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 @@ public abstract class QSTile<TState extends State> 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<TState extends State> 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<TState extends State> 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<TState extends State> 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);
                 }
index 4accc8b..b28d0f2 100644 (file)
@@ -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<TileRecord> mRecords = new ArrayList<>();
+        private boolean mListening;
 
         public HeaderTileLayout(Context context) {
             super(context);
@@ -176,6 +178,15 @@ public class QuickQSPanel extends QSPanel {
         }
 
         @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 @@ 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) {
index a578e6c..a5a1eaa 100644 (file)
@@ -25,6 +25,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
 
     protected final ArrayList<TileRecord> 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();
     }
index fb76918..8ec6a2f 100644 (file)
@@ -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() {