Play control bar overflow animation on the correct target

Fixes: 166685971
Test: manual
Change-Id: I952bf61b5fb63baffb84defb896b87826c8ce5ba
diff --git a/car-apps-common/src/com/android/car/apps/common/ControlBar.java b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
index 88d4dae..4ed3d45 100644
--- a/car-apps-common/src/com/android/car/apps/common/ControlBar.java
+++ b/car-apps-common/src/com/android/car/apps/common/ControlBar.java
@@ -16,6 +16,8 @@
 
 package com.android.car.apps.common;
 
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -29,6 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
@@ -90,6 +93,8 @@
     private boolean mExpandEnabled;
     // Callback for the expand/collapse button
     private ExpandCollapseCallback mExpandCollapseCallback;
+    // The root of the transition animation.
+    private ViewGroup mTransitionRoot;
 
     // Default number of columns, if unspecified
     private static final int DEFAULT_COLUMNS = 3;
@@ -310,12 +315,34 @@
                 .addTransition(new Fade())
                 .setDuration(animationDuration)
                 .setInterpolator(new FastOutSlowInInterpolator());
-        TransitionManager.beginDelayedTransition(this, set);
+        maybeInitTransitionRoot();
+        TransitionManager.beginDelayedTransition(mTransitionRoot, set);
         for (int i = 0; i < mNumExtraRowsInUse; i++) {
             mRowsContainer.getChildAt(i).setVisibility(mIsExpanded ? View.VISIBLE : View.GONE);
         }
     }
 
+    private void maybeInitTransitionRoot() {
+        if (mTransitionRoot != null) {
+            return;
+        }
+        // During the control bar expanding/collapsing animation, the height of the control bar
+        // changes gradually. If the height of its ancestor is WRAP_CONTENT, the height of its
+        // ancestor will not change during the animation, causing janky animation. To fix it the
+        // animation should be played on the highest ancestor that wraps the control bar vertically.
+        mTransitionRoot = this;
+        ViewParent viewParent = getParent();
+        while (viewParent != null && viewParent instanceof ViewGroup) {
+            ViewGroup parent = (ViewGroup) viewParent;
+            if (parent.getLayoutParams().height == WRAP_CONTENT) {
+                mTransitionRoot = parent;
+                viewParent = parent.getParent();
+            } else {
+                break;
+            }
+        }
+    }
+
     /**
      * Returns the view assigned to the given row and column, after layout.
      *