Switch volume animation to Scene.

animateLayoutChanges is too janky.

Bug: 30070005
Change-Id: I88bb94c2de18a8ebc14f0f0aed48877a8b328d8a
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 4cd635e..f3a7acc 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -26,11 +26,20 @@
         android:id="@+id/volume_dialog_content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingTop="@dimen/volume_dialog_collapsed_padding_top"
-        android:animateLayoutChanges="true" >
+        android:orientation="vertical" >
 
-        <!-- volume rows added and removed here! :-) -->
+        <LinearLayout
+                android:id="@+id/volume_dialog_rows"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingEnd="@dimen/volume_button_size"
+                android:orientation="vertical" >
+            <View android:id="@+id/spacer"
+                  android:layout_width="match_parent"
+                  android:layout_height="@dimen/volume_dialog_expanded_spacer"
+                  android:visibility="gone"/>
+            <!-- volume rows added and removed here! :-) -->
+        </LinearLayout>
 
         <include layout="@layout/volume_zen_footer" />
 
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 95019b8..7328d05 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -19,11 +19,8 @@
     android:layout_height="@dimen/volume_row_height"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:id="@+id/volume_dialog_row"
-    android:paddingEnd="@dimen/volume_dialog_padding_end"
     android:orientation="vertical"
-    android:paddingBottom="@dimen/volume_row_padding_bottom"
-    android:animateLayoutChanges="true">
+    android:paddingBottom="@dimen/volume_row_padding_bottom" >
 
     <TextView
         android:id="@+id/volume_row_header"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ae4f3cf..f60bdd1 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -538,8 +538,7 @@
 
     <!-- Volume dialog root view bottom margin, at rest -->
     <dimen name="volume_dialog_margin_bottom">4dp</dimen>
-    <dimen name="volume_dialog_collapsed_padding_top">8dp</dimen>
-    <dimen name="volume_dialog_expanded_padding_top">22dp</dimen>
+    <dimen name="volume_dialog_expanded_spacer">14dp</dimen>
     <dimen name="volume_dialog_padding_end">40dp</dimen>
 
     <dimen name="volume_row_padding_bottom">9.4dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 2094c08..37ea66a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -17,9 +17,7 @@
 package com.android.systemui.volume;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.app.Dialog;
@@ -43,9 +41,11 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Settings.Global;
+import android.transition.AutoTransition;
+import android.transition.Transition;
+import android.transition.TransitionManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -63,12 +63,12 @@
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageButton;
-import android.widget.LinearLayout;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
 import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.tuner.TunerService;
@@ -102,8 +102,10 @@
     private final H mHandler = new H();
     private final VolumeDialogController mController;
 
+    private Window mWindow;
     private CustomDialog mDialog;
     private ViewGroup mDialogView;
+    private ViewGroup mDialogRowsView;
     private ViewGroup mDialogContentView;
     private ImageButton mExpandButton;
     private final List<VolumeRow> mRows = new ArrayList<>();
@@ -114,7 +116,6 @@
     private final AccessibilityManager mAccessibilityMgr;
     private int mExpandButtonAnimationDuration;
     private ZenFooter mZenFooter;
-    private LayoutTransition mLayoutTransition;
     private final Object mSafetyWarningLock = new Object();
     private final Accessibility mAccessibility = new Accessibility();
     private final ColorStateList mActiveSliderTint;
@@ -152,7 +153,8 @@
         mZenModeController = zenModeController;
         mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mAccessibilityMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        mAccessibilityMgr =
+                (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
 
@@ -172,15 +174,13 @@
         mDialog = new CustomDialog(mContext);
 
         mSpTexts = new SpTexts(mContext);
-        mLayoutTransition = new LayoutTransition();
-        mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
         mHovering = false;
         mShowing = false;
-        final Window window = mDialog.getWindow();
-        window.requestFeature(Window.FEATURE_NO_TITLE);
-        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
-        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+        mWindow = mDialog.getWindow();
+        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+        mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
@@ -188,7 +188,7 @@
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
         mDialog.setCanceledOnTouchOutside(true);
         final Resources res = mContext.getResources();
-        final WindowManager.LayoutParams lp = window.getAttributes();
+        final WindowManager.LayoutParams lp = mWindow.getAttributes();
         lp.type = mWindowType;
         lp.format = PixelFormat.TRANSLUCENT;
         lp.setTitle(VolumeDialog.class.getSimpleName());
@@ -196,9 +196,8 @@
         lp.y = res.getDimensionPixelSize(R.dimen.volume_offset_top);
         lp.gravity = Gravity.TOP;
         lp.windowAnimations = -1;
-        window.setAttributes(lp);
-        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
-
+        mWindow.setAttributes(lp);
+        mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
 
         mDialog.setContentView(R.layout.volume_dialog);
         mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
@@ -213,13 +212,13 @@
             }
         });
         mDialogContentView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog_content);
+        mDialogRowsView = (ViewGroup) mDialogContentView.findViewById(R.id.volume_dialog_rows);
         mExpanded = false;
         mExpandButton = (ImageButton) mDialogView.findViewById(R.id.volume_expand_button);
         mExpandButton.setOnClickListener(mClickExpand);
         updateWindowWidthH();
         updateExpandButtonH();
 
-        mDialogContentView.setLayoutTransition(mLayoutTransition);
         mMotion = new VolumeDialogMotion(mDialog, mDialogView, mDialogContentView, mExpandButton,
                 new VolumeDialogMotion.Callback() {
                     @Override
@@ -310,10 +309,7 @@
     private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) {
         VolumeRow row = new VolumeRow();
         initRow(row, stream, iconRes, iconMuteRes, important);
-        if (!mRows.isEmpty()) {
-            addSpacer(row);
-        }
-        mDialogContentView.addView(row.view, mDialogContentView.getChildCount() - 2);
+        mDialogRowsView.addView(row.view);
         mRows.add(row);
     }
 
@@ -322,23 +318,10 @@
         for (int i = 0; i < N; i++) {
             final VolumeRow row = mRows.get(i);
             initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important);
-            if (i > 0) {
-                addSpacer(row);
-            }
-            mDialogContentView.addView(row.view, mDialogContentView.getChildCount() - 2);
+            mDialogRowsView.addView(row.view);
         }
     }
 
-    private void addSpacer(VolumeRow row) {
-        final View v = new View(mContext);
-        v.setId(android.R.id.background);
-        final int h = mContext.getResources()
-                .getDimensionPixelSize(R.dimen.volume_slider_interspacing);
-        final LinearLayout.LayoutParams lp =
-                new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, h);
-        mDialogContentView.addView(v, mDialogContentView.getChildCount() - 2, lp);
-        row.space = v;
-    }
 
     private boolean isAttached() {
         return mDialogContentView != null && mDialogContentView.isAttachedToWindow();
@@ -392,12 +375,15 @@
         row.iconMuteRes = iconMuteRes;
         row.important = important;
         row.view = mDialog.getLayoutInflater().inflate(R.layout.volume_dialog_row, null);
+        row.view.setId(row.stream);
         row.view.setTag(row);
         row.header = (TextView) row.view.findViewById(R.id.volume_row_header);
+        row.header.setId(20 * row.stream);
         mSpTexts.add(row.header);
         row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider);
         row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
         row.anim = null;
+        row.cachedShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS;
 
         // forward events above the slider into the slider
         row.view.setOnTouchListener(new OnTouchListener() {
@@ -509,7 +495,7 @@
         mMotion.startDismiss(new Runnable() {
             @Override
             public void run() {
-                setExpandedH(false);
+                updateExpandedH(false);
             }
         });
         if (mAccessibilityMgr.isEnabled()) {
@@ -555,23 +541,65 @@
         mHandler.sendEmptyMessageDelayed(H.UPDATE_BOTTOM_MARGIN, getConservativeCollapseDuration());
     }
 
-    private void setExpandedH(boolean expanded) {
+    private void updateExpandedH(final boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
         mExpandButtonAnimationRunning = isAttached();
-        if (D.BUG) Log.d(TAG, "setExpandedH " + expanded);
-        if (!mExpanded && mExpandButtonAnimationRunning) {
-            prepareForCollapse();
+        if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
+        updateExpandButtonH();
+        updateFooterH();
+        final VolumeRow activeRow = getActiveRow();
+        mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
+        AutoTransition transition = new AutoTransition();
+        transition.setDuration(mExpandButtonAnimationDuration);
+        transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        transition.addListener(new Transition.TransitionListener() {
+            @Override
+            public void onTransitionStart(Transition transition) {
+            }
+
+            @Override
+            public void onTransitionEnd(Transition transition) {
+                mWindow.setLayout(
+                        mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+            }
+
+            @Override
+            public void onTransitionCancel(Transition transition) {
+                mWindow.setLayout(
+                        mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT);
+            }
+
+            @Override
+            public void onTransitionPause(Transition transition) {
+            }
+
+            @Override
+            public void onTransitionResume(Transition transition) {
+            }
+        });
+        TransitionManager.endTransitions(mDialogView);
+        TransitionManager.beginDelayedTransition(mDialogView, transition);
+        updateRowsH(activeRow);
+        rescheduleTimeoutH();
+    }
+
+    private void updateExpandButtonH() {
+        if (D.BUG) Log.d(TAG, "updateExpandButtonH");
+        mExpandButton.setClickable(!mExpandButtonAnimationRunning);
+        if (!(mExpandButtonAnimationRunning && isAttached())) {
+            final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
+                    : R.drawable.ic_volume_expand_animation;
+            if (hasTouchFeature()) {
+                mExpandButton.setImageResource(res);
+            } else {
+                // if there is no touch feature, show the volume ringer instead
+                mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
+                mExpandButton.setBackgroundResource(0);  // remove gray background emphasis
+            }
+            mExpandButton.setContentDescription(mContext.getString(mExpanded ?
+                    R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
         }
-        final Resources res = mContext.getResources();
-        int paddingTop = mExpanded
-                ? res.getDimensionPixelSize(R.dimen.volume_dialog_expanded_padding_top)
-                : res.getDimensionPixelSize(R.dimen.volume_dialog_collapsed_padding_top);
-        mDialogContentView.setPaddingRelative(mDialogContentView.getPaddingStart(),
-                paddingTop,
-                mDialogContentView.getPaddingEnd(),
-                mDialogContentView.getPaddingBottom());
-        updateRowsH();
         if (mExpandButtonAnimationRunning) {
             final Drawable d = mExpandButton.getDrawable();
             if (d instanceof AnimatedVectorDrawable) {
@@ -590,60 +618,41 @@
                 }, mExpandButtonAnimationDuration);
             }
         }
-        rescheduleTimeoutH();
     }
 
-    private void updateExpandButtonH() {
-        if (D.BUG) Log.d(TAG, "updateExpandButtonH");
-        mExpandButton.setClickable(!mExpandButtonAnimationRunning);
-        if (mExpandButtonAnimationRunning && isAttached()) return;
-        final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
-                : R.drawable.ic_volume_expand_animation;
-        if (hasTouchFeature()) {
-            mExpandButton.setImageResource(res);
-        } else {
-            // if there is no touch feature, show the volume ringer instead
-            mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
-            mExpandButton.setBackgroundResource(0);  // remove gray background emphasis
-        }
-        mExpandButton.setContentDescription(mContext.getString(mExpanded ?
-                R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
-    }
-
-    private boolean isVisibleH(VolumeRow row, boolean isActive) {
+    private boolean shouldBeVisibleH(VolumeRow row, boolean isActive) {
         return mExpanded && row.view.getVisibility() == View.VISIBLE
                 || (mExpanded && (row.important || isActive))
                 || !mExpanded && isActive;
     }
 
-    private void updateRowsH() {
+    private void updateRowsH(final VolumeRow activeRow) {
         if (D.BUG) Log.d(TAG, "updateRowsH");
-        final VolumeRow activeRow = getActiveRow();
-        updateFooterH();
-        updateExpandButtonH();
         if (!mShowing) {
             trimObsoleteH();
         }
+        Util.setVisOrGone(mDialogRowsView.findViewById(R.id.spacer), mExpanded);
         // apply changes to all rows
-        for (VolumeRow row : mRows) {
+        for (final VolumeRow row : mRows) {
             final boolean isActive = row == activeRow;
-            final boolean visible = isVisibleH(row, isActive);
-            Util.setVisOrGone(row.view, visible);
-            Util.setVisOrGone(row.space, visible && mExpanded);
-            updateVolumeRowHeaderVisibleH(row);
-            updateVolumeRowSliderTintH(row, isActive);
+            final boolean shouldBeVisible = shouldBeVisibleH(row, isActive);
+            Util.setVisOrGone(row.view, shouldBeVisible);
+            if (row.view.isShown()) {
+                updateVolumeRowHeaderVisibleH(row);
+                updateVolumeRowSliderTintH(row, isActive);
+            }
         }
+
     }
 
     private void trimObsoleteH() {
         if (D.BUG) Log.d(TAG, "trimObsoleteH");
-        for (int i = mRows.size() -1; i >= 0; i--) {
+        for (int i = mRows.size() - 1; i >= 0; i--) {
             final VolumeRow row = mRows.get(i);
             if (row.ss == null || !row.ss.dynamic) continue;
             if (!mDynamic.get(row.stream)) {
                 mRows.remove(i);
-                mDialogContentView.removeView(row.view);
-                mDialogContentView.removeView(row.space);
+                mDialogRowsView.removeView(row.view);
             }
         }
     }
@@ -670,7 +679,7 @@
 
         if (mActiveStream != state.activeStream) {
             mActiveStream = state.activeStream;
-            updateRowsH();
+            updateRowsH(getActiveRow());
             rescheduleTimeoutH();
         }
         for (VolumeRow row : mRows) {
@@ -731,9 +740,6 @@
                 && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
         final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
         final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
-        final boolean isZenPriority = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        final boolean isRingZenNone = (isRingStream || isSystemStream) && isZenNone;
-        final boolean isRingLimited = isRingStream && isZenPriority;
         final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
                 : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)
                 : false;
@@ -1023,7 +1029,7 @@
             if (mExpandButtonAnimationRunning) return;
             final boolean newExpand = !mExpanded;
             Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
-            setExpandedH(newExpand);
+            updateExpandedH(newExpand);
         }
     };
 
@@ -1220,7 +1226,6 @@
 
     private static class VolumeRow {
         private View view;
-        private View space;
         private TextView header;
         private ImageButton icon;
         private SeekBar slider;