Merge "Fix clipping coordinates on RTL" into tm-dev
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9de132f..41724ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -151,15 +151,17 @@
         mHorizontalContentContainer.setClipChildren(true);
         mHorizontalContentContainer.setClipToPadding(false);
         // Don't clip on the top, that way, secondary pages tiles can animate up
+        // Clipping coordinates should be relative to this view, not absolute (parent coordinates)
         mHorizontalContentContainer.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    if (left != oldLeft || right != oldRight || bottom != oldBottom) {
-                        mClippingRect.left = left;
-                        mClippingRect.right = right;
-                        mClippingRect.bottom = bottom;
+                    if ((right - left) != (oldRight - oldLeft)
+                            || ((bottom - top) != (oldBottom - oldTop))) {
+                        mClippingRect.right = right - left;
+                        mClippingRect.bottom = bottom - top;
                         mHorizontalContentContainer.setClipBounds(mClippingRect);
                     }
                 });
+        mClippingRect.left = 0;
         mClippingRect.top = -1000;
         mHorizontalContentContainer.setClipBounds(mClippingRect);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index e237a5c..60cfd72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -13,18 +13,24 @@
  */
 package com.android.systemui.qs
 
+import android.graphics.Rect
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.testing.TestableLooper.RunWithLooper
+import android.testing.ViewUtils
 import android.view.View
-import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.FrameLayout
 import android.widget.LinearLayout
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSIconViewImpl
+import com.android.systemui.qs.tileimpl.QSTileViewImpl
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -36,37 +42,40 @@
 @RunWithLooper
 @SmallTest
 class QSPanelTest : SysuiTestCase() {
-    private lateinit var mTestableLooper: TestableLooper
-    private lateinit var mQsPanel: QSPanel
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var qsPanel: QSPanel
 
-    private lateinit var mParentView: ViewGroup
-
-    private lateinit var mFooter: View
+    private lateinit var footer: View
 
     @Before
     @Throws(Exception::class)
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        mTestableLooper = TestableLooper.get(this)
+        testableLooper = TestableLooper.get(this)
 
-        mTestableLooper.runWithLooper {
-            mQsPanel = QSPanel(mContext, null)
-            mQsPanel.initialize()
+        testableLooper.runWithLooper {
+            qsPanel = QSPanel(context, null)
+            qsPanel.mUsingMediaPlayer = true
+
+            qsPanel.initialize()
             // QSPanel inflates a footer inside of it, mocking it here
-            mFooter = LinearLayout(mContext).apply { id = R.id.qs_footer }
-            mQsPanel.addView(mFooter)
-            mQsPanel.onFinishInflate()
+            footer = LinearLayout(context).apply { id = R.id.qs_footer }
+            qsPanel.addView(footer, MATCH_PARENT, 100)
+            qsPanel.onFinishInflate()
             // Provides a parent with non-zero size for QSPanel
-            mParentView = FrameLayout(mContext).apply {
-                addView(mQsPanel)
-            }
+            ViewUtils.attachView(qsPanel)
         }
     }
 
+    @After
+    fun tearDown() {
+        ViewUtils.detachView(qsPanel)
+    }
+
     @Test
     fun testHasCollapseAccessibilityAction() {
-        val info = AccessibilityNodeInfo(mQsPanel)
-        mQsPanel.onInitializeAccessibilityNodeInfo(info)
+        val info = AccessibilityNodeInfo(qsPanel)
+        qsPanel.onInitializeAccessibilityNodeInfo(info)
 
         assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isNotEqualTo(0)
         assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isEqualTo(0)
@@ -75,9 +84,79 @@
     @Test
     fun testCollapseActionCallsRunnable() {
         val mockRunnable = mock(Runnable::class.java)
-        mQsPanel.setCollapseExpandAction(mockRunnable)
+        qsPanel.setCollapseExpandAction(mockRunnable)
 
-        mQsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
+        qsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
         verify(mockRunnable).run()
     }
+
+    @Test
+    fun testTilesFooterVisibleRTLLandscapeMedia() {
+        qsPanel.layoutDirection = View.LAYOUT_DIRECTION_RTL
+        // We need at least a tile so the layout has a height
+        qsPanel.tileLayout?.addTile(
+                QSPanelControllerBase.TileRecord(
+                    mock(QSTile::class.java),
+                    QSTileViewImpl(context, QSIconViewImpl(context))
+                )
+            )
+
+        val mediaView = FrameLayout(context)
+        mediaView.addView(View(context), MATCH_PARENT, 800)
+
+        qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+        qsPanel.measure(
+            /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+            /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+        )
+        qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+        val tiles = qsPanel.tileLayout as View
+        // Tiles are effectively to the right of media
+        assertThat(mediaView isLeftOf tiles)
+        assertThat(tiles.isVisibleToUser).isTrue()
+
+        assertThat(mediaView isLeftOf footer)
+        assertThat(footer.isVisibleToUser).isTrue()
+    }
+
+    @Test
+    fun testTilesFooterVisibleLandscapeMedia() {
+        qsPanel.layoutDirection = View.LAYOUT_DIRECTION_LTR
+        // We need at least a tile so the layout has a height
+        qsPanel.tileLayout?.addTile(
+            QSPanelControllerBase.TileRecord(
+                mock(QSTile::class.java),
+                QSTileViewImpl(context, QSIconViewImpl(context))
+            )
+        )
+
+        val mediaView = FrameLayout(context)
+        mediaView.addView(View(context), MATCH_PARENT, 800)
+
+        qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
+        qsPanel.measure(
+            /* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
+            /* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
+        )
+        qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
+
+        val tiles = qsPanel.tileLayout as View
+        // Tiles are effectively to the left of media
+        assertThat(tiles isLeftOf mediaView)
+        assertThat(tiles.isVisibleToUser).isTrue()
+
+        assertThat(footer isLeftOf mediaView)
+        assertThat(footer.isVisibleToUser).isTrue()
+    }
+
+    private infix fun View.isLeftOf(other: View): Boolean {
+        val rect = Rect()
+        getBoundsOnScreen(rect)
+        val thisRight = rect.right
+
+        other.getBoundsOnScreen(rect)
+
+        return thisRight <= rect.left
+    }
 }