From 7eace292e2ee7c2864106dfda7b2b81d7d729bf5 Mon Sep 17 00:00:00 2001 From: Sergey Nikolaienkov Date: Mon, 7 Sep 2020 15:31:44 +0000 Subject: [PATCH 1/3] Clean up unused Views in AudioRecordingDisclosureBar Bug: 166459250 Test: make, flash Test: atest CtsSystemUiTestCases:MicIndicatorTest Change-Id: I249cc29597d3c2891c23ccb2ed979bd46d5e4a78 --- .../drawable/tv_rect_dark_left_rounded.xml | 26 ------ .../drawable/tv_rect_dark_right_rounded.xml | 26 ------ .../layout/tv_audio_recording_indicator.xml | 81 +++---------------- packages/SystemUI/res/values/colors_tv.xml | 2 - .../AudioRecordingDisclosureBar.java | 33 +------- 5 files changed, 11 insertions(+), 157 deletions(-) delete mode 100644 packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml delete mode 100644 packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml diff --git a/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml b/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml deleted file mode 100644 index 9b48a70d9439b..0000000000000 --- a/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml b/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml deleted file mode 100644 index 03348756231b4..0000000000000 --- a/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml index f9336a5403763..b62018d7cb9e8 100644 --- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml +++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml @@ -22,80 +22,17 @@ android:padding="12dp"> + android:layout_width="34dp" + android:layout_height="24dp" + android:layout_gravity="center" + android:background="@drawable/tv_rect_shadow_rounded"> - - - - - - - - - - - - - - - - - - - - - - + - - diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml index cb49918e4e3ff..1177bb5757c2b 100644 --- a/packages/SystemUI/res/values/colors_tv.xml +++ b/packages/SystemUI/res/values/colors_tv.xml @@ -22,8 +22,6 @@ #7FEEEEEE #7F000000 - - #FF3C4043 #CC000000 #33FFFFFF diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java index a29db4d98329e..c1fad89179917 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java @@ -36,7 +36,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver; import android.view.WindowManager; -import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.statusbar.tv.TvStatusBar; @@ -89,12 +88,6 @@ public class AudioRecordingDisclosureBar implements private boolean mIsEnabled; private View mIndicatorView; - private View mIconTextsContainer; - private View mIconContainerBg; - private View mIcon; - private View mBgEnd; - private View mTextsContainers; - private TextView mTextView; private boolean mIsLtr; @State private int mState = STATE_STOPPED; @@ -221,21 +214,6 @@ public class AudioRecordingDisclosureBar implements mIndicatorView = LayoutInflater.from(mContext).inflate( R.layout.tv_audio_recording_indicator, null); - mIconTextsContainer = mIndicatorView.findViewById(R.id.icon_texts_container); - mIconContainerBg = mIconTextsContainer.findViewById(R.id.icon_container_bg); - mIcon = mIconTextsContainer.findViewById(R.id.icon_mic); - mTextsContainers = mIconTextsContainer.findViewById(R.id.texts_container); - mTextView = mTextsContainers.findViewById(R.id.text); - mBgEnd = mIndicatorView.findViewById(R.id.bg_end); - - mTextsContainers.setVisibility(View.GONE); - mIconContainerBg.setVisibility(View.GONE); - mTextView.setVisibility(View.GONE); - mBgEnd.setVisibility(View.GONE); - mTextsContainers = null; - mIconContainerBg = null; - mTextView = null; - mBgEnd = null; // Initially change the visibility to INVISIBLE, wait until and receives the size and // then animate it moving from "off" the screen correctly @@ -305,12 +283,11 @@ public class AudioRecordingDisclosureBar implements private void hide() { if (DEBUG) Log.d(TAG, "Hide indicator"); - final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth() - - (int) mIconTextsContainer.getTranslationX()); + final int targetOffset = (mIsLtr ? 1 : -1) * mIndicatorView.getWidth(); final AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(mIndicatorView, View.TRANSLATION_X, targetOffset), - ObjectAnimator.ofFloat(mIcon, View.ALPHA, 0f)); + ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f)); set.setDuration(ANIMATION_DURATION); set.addListener( new AnimatorListenerAdapter() { @@ -363,12 +340,6 @@ public class AudioRecordingDisclosureBar implements windowManager.removeView(mIndicatorView); mIndicatorView = null; - mIconTextsContainer = null; - mIconContainerBg = null; - mIcon = null; - mTextsContainers = null; - mTextView = null; - mBgEnd = null; } private static List splitByComma(String string) { From 521f95e20eb2cd546482ccf3c8e9af1cf0bcb9f9 Mon Sep 17 00:00:00 2001 From: Sergey Nikolaienkov Date: Mon, 7 Sep 2020 16:09:38 +0000 Subject: [PATCH 2/3] Update AudioRecordingDisclosureBar animations Currently the Mic icon slide from the right following the previous notification pattern, as we changed it to a small one, we would want the Microphone to Fade In and Fade Out. Bug: 166459250 Test: make, flash Test: atest CtsSystemUiTestCases:MicIndicatorTest Change-Id: Ib628688110cf08b38929973153fbff5a3ca2d683 --- .../AudioRecordingDisclosureBar.java | 57 ++++++------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java index c1fad89179917..a2ea05f3abdf3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java @@ -21,7 +21,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.IntDef; import android.annotation.UiThread; @@ -82,13 +81,12 @@ public class AudioRecordingDisclosureBar implements private static final int STATE_SHOWN = 2; private static final int STATE_DISAPPEARING = 3; - private static final int ANIMATION_DURATION = 600; + private static final int ANIMATION_DURATION_MS = 200; private final Context mContext; private boolean mIsEnabled; private View mIndicatorView; - private boolean mIsLtr; @State private int mState = STATE_STOPPED; @@ -207,17 +205,15 @@ public class AudioRecordingDisclosureBar implements if (mState != STATE_NOT_SHOWN) return; if (DEBUG) Log.d(TAG, "Showing indicator"); - mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection() - == View.LAYOUT_DIRECTION_LTR; - // Inflate the indicator view mIndicatorView = LayoutInflater.from(mContext).inflate( R.layout.tv_audio_recording_indicator, null); - // Initially change the visibility to INVISIBLE, wait until and receives the size and - // then animate it moving from "off" the screen correctly - mIndicatorView.setVisibility(View.INVISIBLE); + // 1. Set alpha to 0. + // 2. Wait until the window is shown and the view is laid out. + // 3. Start a "fade in" (alpha) animation. + mIndicatorView.setAlpha(0f); mIndicatorView .getViewTreeObserver() .addOnGlobalLayoutListener( @@ -232,44 +228,29 @@ public class AudioRecordingDisclosureBar implements mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener( this); - // Now that the width of the indicator has been assigned, we can - // move it in from off the screen. - final int initialOffset = - (mIsLtr ? 1 : -1) * mIndicatorView.getWidth(); - final AnimatorSet set = new AnimatorSet(); - set.setDuration(ANIMATION_DURATION); - set.playTogether( - ObjectAnimator.ofFloat(mIndicatorView, - View.TRANSLATION_X, initialOffset, 0), - ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f, - 1f)); - set.addListener( + final ObjectAnimator anim = + ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 1f) + .setDuration(ANIMATION_DURATION_MS); + anim.addListener( new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation, - boolean isReverse) { - if (mState == STATE_STOPPED) return; - - // Indicator is INVISIBLE at the moment, change it. - mIndicatorView.setVisibility(View.VISIBLE); - } - @Override public void onAnimationEnd(Animator animation) { onAppeared(); } }); - set.start(); + anim.start(); } }); + final boolean isLtr = mContext.getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_LTR; final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( WRAP_CONTENT, WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); - layoutParams.gravity = Gravity.TOP | (mIsLtr ? Gravity.RIGHT : Gravity.LEFT); + layoutParams.gravity = Gravity.TOP | (isLtr ? Gravity.RIGHT : Gravity.LEFT); layoutParams.setTitle(LAYOUT_PARAMS_TITLE); layoutParams.packageName = mContext.getPackageName(); final WindowManager windowManager = (WindowManager) mContext.getSystemService( @@ -283,20 +264,16 @@ public class AudioRecordingDisclosureBar implements private void hide() { if (DEBUG) Log.d(TAG, "Hide indicator"); - final int targetOffset = (mIsLtr ? 1 : -1) * mIndicatorView.getWidth(); - final AnimatorSet set = new AnimatorSet(); - set.playTogether( - ObjectAnimator.ofFloat(mIndicatorView, View.TRANSLATION_X, targetOffset), - ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f)); - set.setDuration(ANIMATION_DURATION); - set.addListener( + final ObjectAnimator anim = ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f) + .setDuration(ANIMATION_DURATION_MS); + anim.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { onHidden(); } }); - set.start(); + anim.start(); mState = STATE_DISAPPEARING; } From 1dbc58650490bfafa9389a1bfae138fabaf2975f Mon Sep 17 00:00:00 2001 From: Sergey Nikolaienkov Date: Mon, 7 Sep 2020 16:50:39 +0000 Subject: [PATCH 3/3] Make AudioRecordingDisclosureBar animations interruptable Bug: 166578426 Test: make, flash Test: atest CtsSystemUiTestCases:MicIndicatorTest Change-Id: Ie4a21aac28ded6e62447e7924eae52dff2eebb6f --- .../AudioRecordingDisclosureBar.java | 149 ++++++++++-------- 1 file changed, 85 insertions(+), 64 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java index a2ea05f3abdf3..7aeca64ba9e87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java @@ -87,6 +87,8 @@ public class AudioRecordingDisclosureBar implements private boolean mIsEnabled; private View mIndicatorView; + private boolean mViewAndWindowAdded; + private ObjectAnimator mAnimator; @State private int mState = STATE_STOPPED; @@ -181,7 +183,7 @@ public class AudioRecordingDisclosureBar implements } if (active) { - showIfNotShown(); + showIfNeeded(); } else { hideIndicatorIfNeeded(); } @@ -189,26 +191,42 @@ public class AudioRecordingDisclosureBar implements @UiThread private void hideIndicatorIfNeeded() { - // If not STATE_APPEARING, will check whether the indicator should be hidden when the - // indicator comes to the STATE_SHOWN. - // If STATE_DISAPPEARING or STATE_SHOWN - nothing else for us to do here. - if (mState != STATE_SHOWN) return; + // If STOPPED, NOT_SHOWN or DISAPPEARING - nothing else for us to do here. + if (mState != STATE_SHOWN && mState != STATE_APPEARING) return; - // If is in the STATE_SHOWN and there are no active recorders - hide. - if (!hasActiveRecorders()) { - hide(); + if (hasActiveRecorders()) { + return; + } + + if (mViewAndWindowAdded) { + mState = STATE_DISAPPEARING; + animateDisappearance(); + } else { + // Appearing animation has not started yet, as we were still waiting for the View to be + // laid out. + mState = STATE_NOT_SHOWN; + removeIndicatorView(); } } @UiThread - private void showIfNotShown() { - if (mState != STATE_NOT_SHOWN) return; + private void showIfNeeded() { + // If STOPPED, SHOWN or APPEARING - nothing else for us to do here. + if (mState != STATE_NOT_SHOWN && mState != STATE_DISAPPEARING) return; + if (DEBUG) Log.d(TAG, "Showing indicator"); + final int prevState = mState; + mState = STATE_APPEARING; + + if (prevState == STATE_DISAPPEARING) { + animateAppearance(); + return; + } + // Inflate the indicator view mIndicatorView = LayoutInflater.from(mContext).inflate( - R.layout.tv_audio_recording_indicator, - null); + R.layout.tv_audio_recording_indicator, null); // 1. Set alpha to 0. // 2. Wait until the window is shown and the view is laid out. @@ -220,25 +238,16 @@ public class AudioRecordingDisclosureBar implements new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - if (mState == STATE_STOPPED) { - return; - } + // State could have changed to NOT_SHOWN (if all the recorders are + // already gone) to STOPPED (if the indicator was disabled) + if (mState != STATE_APPEARING) return; + mViewAndWindowAdded = true; // Remove the observer mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener( this); - final ObjectAnimator anim = - ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 1f) - .setDuration(ANIMATION_DURATION_MS); - anim.addListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - onAppeared(); - } - }); - anim.start(); + animateAppearance(); } }); @@ -256,49 +265,58 @@ public class AudioRecordingDisclosureBar implements final WindowManager windowManager = (WindowManager) mContext.getSystemService( Context.WINDOW_SERVICE); windowManager.addView(mIndicatorView, layoutParams); - - mState = STATE_APPEARING; } - @UiThread - private void hide() { - if (DEBUG) Log.d(TAG, "Hide indicator"); - final ObjectAnimator anim = ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f) - .setDuration(ANIMATION_DURATION_MS); - anim.addListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - onHidden(); + private void animateAppearance() { + animateAlphaTo(1f); + } + + private void animateDisappearance() { + animateAlphaTo(0f); + } + + private void animateAlphaTo(final float endValue) { + if (mAnimator == null) { + if (DEBUG) Log.d(TAG, "set up animator"); + + mAnimator = new ObjectAnimator(); + mAnimator.setTarget(mIndicatorView); + mAnimator.setProperty(View.ALPHA); + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation, boolean isReverse) { + if (DEBUG) Log.d(TAG, "onAnimationStart"); + } + + @Override + public void onAnimationCancel(Animator animation) { + if (DEBUG) Log.d(TAG, "onAnimationCancel"); + } + + @Override + public void onAnimationEnd(Animator animation) { + if (DEBUG) Log.d(TAG, "onAnimationEnd"); + + if (mState == STATE_APPEARING) { + mState = STATE_SHOWN; + } else if (mState == STATE_DISAPPEARING) { + removeIndicatorView(); + mState = STATE_NOT_SHOWN; } - }); - anim.start(); - - mState = STATE_DISAPPEARING; - } - - - @UiThread - private void onAppeared() { - if (mState == STATE_STOPPED) return; - - mState = STATE_SHOWN; - - hideIndicatorIfNeeded(); - } - - @UiThread - private void onHidden() { - if (mState == STATE_STOPPED) return; - - removeIndicatorView(); - mState = STATE_NOT_SHOWN; - - if (hasActiveRecorders()) { - // Got new recorders, show again. - showIfNotShown(); + } + }); + } else if (mAnimator.isRunning()) { + if (DEBUG) Log.d(TAG, "cancel running animation"); + mAnimator.cancel(); } + + final float currentValue = mIndicatorView.getAlpha(); + if (DEBUG) Log.d(TAG, "animate alpha to " + endValue + " from " + currentValue); + + mAnimator.setDuration((int) (Math.abs(currentValue - endValue) * ANIMATION_DURATION_MS)); + mAnimator.setFloatValues(endValue); + mAnimator.start(); } private boolean hasActiveRecorders() { @@ -317,6 +335,9 @@ public class AudioRecordingDisclosureBar implements windowManager.removeView(mIndicatorView); mIndicatorView = null; + mAnimator = null; + + mViewAndWindowAdded = false; } private static List splitByComma(String string) {