Change how PagedTileLayout is measured

The change makes PagedTileLayout only use excess space from QSPanel
after other views have been measured and the padding has been accounted
for (see LinearLayout#measureVertical).

PagedTileLayout caches the last height to be measured so as to minimize
the number of times the number of rows is recalculated (and prevent
loops).

Also, fixed the calculation in TileLayout#updateMaxRows to match the
height calculation in TileLayout#onMeasure.

Test: manual, stress testing with multiple pages, adding and removing
tiles, starting and disconnecting VPN, changing display size
Bug:122714773

Change-Id: I5c85f03cfc79e341244d213fd92307821db80889
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index d6e0306..ddefdf6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -128,6 +128,24 @@
         addView(mDivider);
     }
 
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // We want all the logic of LinearLayout#onMeasure, and for it to assign the excess space
+        // not used by the other children to PagedTileLayout. However, in this case, LinearLayout
+        // assumes that PagedTileLayout would use all the excess space. This is not the case as
+        // PagedTileLayout height is quantized (because it shows a certain number of rows).
+        // Therefore, after everything is measured, we need to make sure that we add up the correct
+        // total height
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int height = getPaddingBottom() + getPaddingTop();
+        int numChildren = getChildCount();
+        for (int i = 0; i < numChildren; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE) height += child.getMeasuredHeight();
+        }
+        setMeasuredDimension(getMeasuredWidth(), height);
+    }
+
     public View getDivider() {
         return mDivider;
     }