diff options
Diffstat (limited to 'packages')
40 files changed, 674 insertions, 192 deletions
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml index 01d9ab3..e9cdfcd 100644 --- a/packages/Keyguard/res/values/dimens.xml +++ b/packages/Keyguard/res/values/dimens.xml @@ -162,5 +162,5 @@ <dimen name="big_font_size">120dp</dimen> <!-- The y translation to apply at the start in appear animations. --> - <dimen name="appear_y_translation_start">24dp</dimen> + <dimen name="appear_y_translation_start">32dp</dimen> </resources> diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java b/packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java new file mode 100644 index 0000000..0d30ea6 --- /dev/null +++ b/packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.keyguard; + +import android.animation.Animator; +import android.view.animation.Interpolator; + +/** + * An interface which can create animations when starting an appear animation with + * {@link com.android.keyguard.AppearAnimationUtils} + */ +public interface AppearAnimationCreator<T> { + void createAnimation(T animatedObject, long delay, long duration, + float startTranslationY, Interpolator interpolator, Runnable finishListener); +} diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java index ea896d5..6bb1f2c 100644 --- a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java +++ b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java @@ -16,84 +16,124 @@ package com.android.keyguard; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.TimeInterpolator; import android.content.Context; import android.view.View; -import android.view.ViewPropertyAnimator; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; /** * A class to make nice appear transitions for views in a tabular layout. */ -public class AppearAnimationUtils { +public class AppearAnimationUtils implements AppearAnimationCreator<View> { public static final long APPEAR_DURATION = 220; private final Interpolator mLinearOutSlowIn; private final float mStartTranslation; + private final AppearAnimationProperties mProperties = new AppearAnimationProperties(); + private final float mDelayScale; public AppearAnimationUtils(Context ctx) { + this(ctx, 1.0f, 1.0f); + } + + public AppearAnimationUtils(Context ctx, float delayScaleFactor, + float translationScaleFactor) { mLinearOutSlowIn = AnimationUtils.loadInterpolator( ctx, android.R.interpolator.linear_out_slow_in); - mStartTranslation = - ctx.getResources().getDimensionPixelOffset(R.dimen.appear_y_translation_start); + mStartTranslation = ctx.getResources().getDimensionPixelOffset( + R.dimen.appear_y_translation_start) * translationScaleFactor; + mDelayScale = delayScaleFactor; } - public void startAppearAnimation(View[][] views, final Runnable finishListener) { - long maxDelay = 0; - ViewPropertyAnimator maxDelayAnimator = null; - for (int row = 0; row < views.length; row++) { - View[] columns = views[row]; + public void startAppearAnimation(View[][] objects, final Runnable finishListener) { + startAppearAnimation(objects, finishListener, this); + } + + public <T> void startAppearAnimation(T[][] objects, final Runnable finishListener, + AppearAnimationCreator<T> creator) { + AppearAnimationProperties properties = getDelays(objects); + startAnimations(properties, objects, finishListener, creator); + } + + private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects, + final Runnable finishListener, AppearAnimationCreator creator) {; + if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) { + finishListener.run(); + return; + } + for (int row = 0; row < properties.delays.length; row++) { + long[] columns = properties.delays[row]; for (int col = 0; col < columns.length; col++) { - long delay = calculateDelay(row, col); - ViewPropertyAnimator animator = startAppearAnimation(columns[col], delay); - if (animator != null && delay > maxDelay) { - maxDelay = delay; - maxDelayAnimator = animator; + long delay = columns[col]; + Runnable endRunnable = null; + if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) { + endRunnable = finishListener; } + creator.createAnimation(objects[row][col], delay, APPEAR_DURATION, + mStartTranslation, mLinearOutSlowIn, endRunnable); } } - if (maxDelayAnimator != null) { - maxDelayAnimator.setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - finishListener.run(); - } - }); - } else { - finishListener.run(); - } + } - private ViewPropertyAnimator startAppearAnimation(View view, long delay) { - if (view == null) return null; - view.setAlpha(0f); - view.setTranslationY(mStartTranslation); - view.animate() - .alpha(1f) - .translationY(0) - .setInterpolator(mLinearOutSlowIn) - .setDuration(APPEAR_DURATION) - .setStartDelay(delay) - .setListener(null); - if (view.hasOverlappingRendering()) { - view.animate().withLayer(); + private <T> AppearAnimationProperties getDelays(T[][] items) { + long maxDelay = 0; + mProperties.maxDelayColIndex = -1; + mProperties.maxDelayRowIndex = -1; + mProperties.delays = new long[items.length][]; + for (int row = 0; row < items.length; row++) { + T[] columns = items[row]; + mProperties.delays[row] = new long[columns.length]; + for (int col = 0; col < columns.length; col++) { + long delay = calculateDelay(row, col); + mProperties.delays[row][col] = delay; + if (items[row][col] != null && delay > maxDelay) { + maxDelay = delay; + mProperties.maxDelayColIndex = col; + mProperties.maxDelayRowIndex = row; + } + } } - return view.animate(); + return mProperties; } private long calculateDelay(int row, int col) { - return (long) (row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20); + return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale); } - public TimeInterpolator getInterpolator() { + public Interpolator getInterpolator() { return mLinearOutSlowIn; } public float getStartTranslation() { return mStartTranslation; } + + @Override + public void createAnimation(View view, long delay, long duration, float startTranslationY, + Interpolator interpolator, Runnable endRunnable) { + if (view != null) { + view.setAlpha(0f); + view.setTranslationY(startTranslationY); + view.animate() + .alpha(1f) + .translationY(0) + .setInterpolator(interpolator) + .setDuration(duration) + .setStartDelay(delay); + if (view.hasOverlappingRendering()) { + view.animate().withLayer(); + } + if (endRunnable != null) { + view.animate().withEndAction(endRunnable); + } + } + } + + public class AppearAnimationProperties { + public long[][] delays; + public int maxDelayRowIndex; + public int maxDelayColIndex; + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java index 5853ff9..e6de72f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java @@ -21,6 +21,9 @@ import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -28,10 +31,13 @@ import android.os.Bundle; import android.os.CountDownTimer; import android.os.SystemClock; import android.os.UserHandle; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Interpolator; import android.widget.Button; import android.widget.LinearLayout; @@ -41,7 +47,8 @@ import com.android.internal.widget.LockPatternView; import java.io.IOException; import java.util.List; -public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView { +public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView, + AppearAnimationCreator<LockPatternView.CellState> { private static final String TAG = "SecurityPatternView"; private static final boolean DEBUG = KeyguardConstants.DEBUG; @@ -59,6 +66,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final AppearAnimationUtils mAppearAnimationUtils; private CountDownTimer mCountdownTimer = null; private LockPatternUtils mLockPatternUtils; @@ -87,6 +95,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit private SecurityMessageDisplay mSecurityMessageDisplay; private View mEcaView; private Drawable mBouncerFrame; + private ViewGroup mKeyguardBouncerFrame; + private KeyguardMessageArea mHelpMessage; enum FooterMode { Normal, @@ -101,6 +111,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit public KeyguardPatternView(Context context, AttributeSet attrs) { super(context, attrs); mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); + mAppearAnimationUtils = new AppearAnimationUtils(context, 1.5f /* delayScale */, + 2.0f /* transitionScale */); } public void setKeyguardCallback(KeyguardSecurityCallback callback) { @@ -148,6 +160,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit if (bouncerFrameView != null) { mBouncerFrame = bouncerFrameView.getBackground(); } + + mKeyguardBouncerFrame = (ViewGroup) findViewById(R.id.keyguard_bouncer_frame); + mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area); } private void updateFooter(FooterMode mode) { @@ -403,8 +418,69 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit @Override public void startAppearAnimation() { - // TODO: Fancy animation. - setAlpha(0); - animate().alpha(1).withLayer().setDuration(200); + enableClipping(false); + mAppearAnimationUtils.startAppearAnimation( + mLockPatternView.getCellStates(), + new Runnable() { + @Override + public void run() { + enableClipping(true); + } + }, + this); + if (!TextUtils.isEmpty(mHelpMessage.getText())) { + mAppearAnimationUtils.createAnimation(mHelpMessage, 0, + AppearAnimationUtils.APPEAR_DURATION, + mAppearAnimationUtils.getStartTranslation(), + mAppearAnimationUtils.getInterpolator(), + null /* finishRunnable */); + } + } + + private void enableClipping(boolean enable) { + setClipChildren(enable); + mKeyguardBouncerFrame.setClipToPadding(enable); + mKeyguardBouncerFrame.setClipChildren(enable); + } + + @Override + public void createAnimation(final LockPatternView.CellState animatedCell, long delay, + long duration, float startTranslationY, Interpolator interpolator, + final Runnable finishListener) { + animatedCell.scale = 0.0f; + animatedCell.translateY = startTranslationY; + ValueAnimator animator = ValueAnimator.ofFloat(startTranslationY, 0.0f); + animator.setInterpolator(interpolator); + animator.setDuration(duration); + animator.setStartDelay(delay); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float animatedFraction = animation.getAnimatedFraction(); + animatedCell.scale = animatedFraction; + animatedCell.translateY = (float) animation.getAnimatedValue(); + mLockPatternView.invalidate(); + } + }); + if (finishListener != null) { + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finishListener.run(); + } + }); + + // Also animate the Emergency call + mAppearAnimationUtils.createAnimation(mEcaView, delay, duration, startTranslationY, + interpolator, null); + + // And the forgot pattern button + if (mForgotPatternButton.getVisibility() == View.VISIBLE) { + mAppearAnimationUtils.createAnimation(mForgotPatternButton, delay, duration, + startTranslationY, interpolator, null); + } + } + animator.start(); + mLockPatternView.invalidate(); } } diff --git a/packages/SystemUI/res/drawable/ic_qs_close.xml b/packages/SystemUI/res/drawable/ic_qs_back.xml index dd43e6c..52039f5 100644 --- a/packages/SystemUI/res/drawable/ic_qs_close.xml +++ b/packages/SystemUI/res/drawable/ic_qs_back.xml @@ -24,5 +24,5 @@ Copyright (C) 2014 The Android Open Source Project <path android:fill="#FFFFFFFF" - android:pathData="M19.0,6.4l-1.3999996,-1.4000001 -5.6000004,5.6000004 -5.6,-5.6000004 -1.4000001,1.4000001 5.6000004,5.6 -5.6000004,5.6000004 1.4000001,1.3999996 5.6,-5.6000004 5.6000004,5.6000004 1.3999996,-1.3999996 -5.6000004,-5.6000004z"/> + android:pathData="M20.0,11.0L7.8,11.0l5.6,-5.6L12.0,4.0l-8.0,8.0l8.0,8.0l1.4,-1.4L7.8,13.0L20.0,13.0L20.0,11.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_zen_off.xml b/packages/SystemUI/res/drawable/ic_qs_zen_off.xml index 73886ec..88a2c3a 100644 --- a/packages/SystemUI/res/drawable/ic_qs_zen_off.xml +++ b/packages/SystemUI/res/drawable/ic_qs_zen_off.xml @@ -23,8 +23,6 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"/> <path - android:fill="#00000000" - android:stroke="#CCCCCC" - android:strokeWidth="1.0" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" /> + android:fill="#4DFFFFFF" + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_zen_on.xml b/packages/SystemUI/res/drawable/ic_qs_zen_on.xml index 8dff318..0e933cf 100644 --- a/packages/SystemUI/res/drawable/ic_qs_zen_on.xml +++ b/packages/SystemUI/res/drawable/ic_qs_zen_on.xml @@ -24,5 +24,5 @@ Copyright (C) 2014 The Android Open Source Project <path android:fill="#FFFFFFFF" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" /> + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_vol_zen_off.xml b/packages/SystemUI/res/drawable/ic_vol_zen_off.xml index ea5ab70..51be1a8 100644 --- a/packages/SystemUI/res/drawable/ic_vol_zen_off.xml +++ b/packages/SystemUI/res/drawable/ic_vol_zen_off.xml @@ -23,8 +23,6 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"/> <path - android:fill="#00000000" - android:stroke="#CCCCCC" - android:strokeWidth="1.0" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" /> + android:fill="#4DFFFFFF" + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_vol_zen_on.xml b/packages/SystemUI/res/drawable/ic_vol_zen_on.xml index 44024f3..c8c217d 100644 --- a/packages/SystemUI/res/drawable/ic_vol_zen_on.xml +++ b/packages/SystemUI/res/drawable/ic_vol_zen_on.xml @@ -24,5 +24,5 @@ Copyright (C) 2014 The Android Open Source Project <path android:fill="#FFFFFFFF" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" /> + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml index afab88f..8b104d1 100644 --- a/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml +++ b/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml @@ -24,5 +24,5 @@ Copyright (C) 2014 The Android Open Source Project <path android:fill="#FFFFFFFF" - android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" /> + android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z"/> </vector> diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index e73b431..e1c460c 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -26,7 +26,7 @@ android:layout_alignParentStart="true" android:contentDescription="@string/accessibility_quick_settings_close" android:padding="@dimen/qs_panel_padding" - android:src="@drawable/ic_qs_close" /> + android:src="@drawable/ic_qs_back" /> <TextView android:id="@android:id/title" diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml index 6268628..ac6450b 100644 --- a/packages/SystemUI/res/layout/recents_empty.xml +++ b/packages/SystemUI/res/layout/recents_empty.xml @@ -19,8 +19,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" - android:textSize="40sp" + android:textSize="20sp" android:textColor="#ffffffff" + android:textStyle="italic" android:text="@string/recents_empty_message" - android:fontFamily="sans-serif-thin" + android:fontFamily="sans-serif-light" android:visibility="gone" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml index 7de421c..85d2f16 100644 --- a/packages/SystemUI/res/layout/recents_task_view.xml +++ b/packages/SystemUI/res/layout/recents_task_view.xml @@ -25,36 +25,37 @@ <com.android.systemui.recents.views.TaskBarView android:id="@+id/task_view_bar" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="56dp" android:layout_gravity="top|center_horizontal" android:background="@color/recents_task_bar_default_background_color"> <ImageView android:id="@+id/application_icon" android:layout_width="@dimen/recents_task_view_application_icon_size" android:layout_height="@dimen/recents_task_view_application_icon_size" - android:layout_gravity="center_vertical|start" - android:padding="8dp" /> + android:layout_marginStart="16dp" + android:layout_gravity="center_vertical|start" /> <TextView android:id="@+id/activity_description" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center_vertical|left" - android:layout_marginStart="@dimen/recents_task_view_application_icon_size" - android:layout_marginEnd="@dimen/recents_task_view_application_icon_size" - android:textSize="22sp" + android:layout_gravity="center_vertical|start" + android:layout_marginStart="64dp" + android:layout_marginEnd="64dp" + android:textSize="16sp" android:textColor="#ffffffff" android:text="@string/recents_empty_message" - android:fontFamily="sans-serif-light" + android:fontFamily="sans-serif-medium" android:singleLine="true" android:maxLines="2" android:ellipsize="marquee" android:fadingEdge="horizontal" /> <ImageView android:id="@+id/dismiss_task" - android:layout_width="@dimen/recents_task_view_application_icon_size" - android:layout_height="@dimen/recents_task_view_application_icon_size" + android:layout_width="48dp" + android:layout_height="48dp" + android:layout_marginEnd="4dp" android:layout_gravity="center_vertical|end" - android:padding="23dp" + android:padding="18dp" android:src="@drawable/recents_dismiss_light" /> </com.android.systemui.recents.views.TaskBarView> </com.android.systemui.recents.views.TaskView> diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml index 8b34400..6d63bb0 100644 --- a/packages/SystemUI/res/layout/zen_mode_condition.xml +++ b/packages/SystemUI/res/layout/zen_mode_condition.xml @@ -16,11 +16,14 @@ --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="wrap_content" > + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/zen_mode_condition_detail_button_padding" + android:layout_marginRight="@dimen/zen_mode_condition_detail_button_padding" > <RadioButton android:id="@android:id/checkbox" - android:layout_width="32dp" + android:layout_width="40dp" + android:layout_marginStart="2dp" android:layout_height="@dimen/zen_mode_condition_height" android:layout_alignParentStart="true" android:gravity="center" /> diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml index 0936cc2..0a8f852 100644 --- a/packages/SystemUI/res/layout/zen_mode_panel.xml +++ b/packages/SystemUI/res/layout/zen_mode_panel.xml @@ -21,9 +21,7 @@ android:layout_height="wrap_content" android:background="@color/system_primary_color" android:orientation="vertical" - android:paddingTop="@dimen/qs_panel_padding" - android:paddingLeft="@dimen/qs_panel_padding" - android:paddingRight="@dimen/qs_panel_padding" > + android:paddingTop="@dimen/qs_panel_padding" > <TextView android:id="@android:id/title" @@ -31,8 +29,10 @@ android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_marginBottom="8dp" + android:layout_marginStart="@dimen/qs_panel_padding" + android:layout_marginEnd="@dimen/qs_panel_padding" android:text="@string/zen_mode_title" - android:textAppearance="@style/TextAppearance.QS.DetailHeader" /> + android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" /> <LinearLayout android:id="@android:id/content" @@ -46,6 +46,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" + android:layout_marginEnd="4dp" android:layout_gravity="end" android:text="@string/quick_settings_more_settings" android:textAppearance="@style/TextAppearance.QS.DetailButton" /> diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml index 39ce0a2..42c4392 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -38,6 +38,9 @@ <dimen name="status_bar_recents_app_icon_left_margin">8dp</dimen> <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen> + <!-- The side padding for the task stack as a percentage of the width. --> + <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.2229</item> + <!-- Width of the zen mode interstitial dialog. --> <dimen name="zen_mode_dialog_width">384dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml index b510fef..326f602 100644 --- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml @@ -19,6 +19,9 @@ <!-- Recent Applications parameters --> <dimen name="status_bar_recents_app_label_width">190dip</dimen> + <!-- The side padding for the task stack as a percentage of the width. --> + <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.25</item> + <fraction name="keyguard_clock_y_fraction_max">37%</fraction> <fraction name="keyguard_clock_y_fraction_min">14%</fraction> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 5750faa..313e2e8 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -46,6 +46,9 @@ <!-- On tablets this is just the close_handle_height --> <dimen name="peek_height">@dimen/close_handle_height</dimen> + <!-- The side padding for the task stack as a percentage of the width. --> + <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.075</item> + <!-- Width of the zen mode interstitial dialog. --> <dimen name="zen_mode_dialog_width">384dp</dimen> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 4e37dbb..757d4ad 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -67,11 +67,13 @@ <!-- The recents task bar light text color to be drawn on top of dark backgrounds. --> <color name="recents_task_bar_light_text_color">#ffeeeeee</color> <!-- The recents task bar dark text color to be drawn on top of light backgrounds. --> - <color name="recents_task_bar_dark_text_color">#ff222222</color> + <color name="recents_task_bar_dark_text_color">#ff333333</color> <!-- The recents task bar light dismiss icon color to be drawn on top of dark backgrounds. --> <color name="recents_task_bar_light_dismiss_color">#ffeeeeee</color> <!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. --> <color name="recents_task_bar_dark_dismiss_color">#ff333333</color> + <!-- The recents task bar highlight color. --> + <color name="recents_task_bar_highlight_color">#28ffffff</color> <color name="keyguard_affordance">#ffffffff</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 6405ae6..0184df2 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -113,9 +113,9 @@ <!-- The min animation duration for animating views that are newly visible. --> <integer name="recents_filter_animate_new_views_min_duration">125</integer> <!-- The min animation duration for animating the task bar in. --> - <integer name="recents_animate_task_bar_enter_duration">225</integer> + <integer name="recents_animate_task_bar_enter_duration">300</integer> <!-- The min animation duration for animating the task bar out. --> - <integer name="recents_animate_task_bar_exit_duration">175</integer> + <integer name="recents_animate_task_bar_exit_duration">150</integer> <!-- The animation duration for animating in the info pane. --> <integer name="recents_animate_task_view_info_pane_duration">150</integer> <!-- The animation duration for animating the removal of a task view. --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 610b376..3646ade 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -212,7 +212,7 @@ <dimen name="glowpadview_inner_radius">15dip</dimen> <!-- The size of the application icon in the recents task view. --> - <dimen name="recents_task_view_application_icon_size">60dp</dimen> + <dimen name="recents_task_view_application_icon_size">32dp</dimen> <!-- The size of the activity icon in the recents task view. --> <dimen name="recents_task_view_activity_icon_size">60dp</dimen> @@ -221,20 +221,32 @@ <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen> <!-- The min translation in the Z index for the last task. --> - <dimen name="recents_task_view_z_min">3dp</dimen> + <dimen name="recents_task_view_z_min">5dp</dimen> <!-- The translation in the Z index for each task above the last task. --> - <dimen name="recents_task_view_z_increment">5dp</dimen> + <dimen name="recents_task_view_z_increment">10dp</dimen> + + <!-- The amount of bottom inset in the shadow outline. --> + <dimen name="recents_task_view_shadow_outline_bottom_inset">5dp</dimen> <!-- The amount to translate when animating the removal of a task. --> <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen> + <!-- The amount of highlight to make on each task view. --> + <dimen name="recents_task_view_highlight">1dp</dimen> + <!-- The amount of space a user has to scroll to dismiss any info panes. --> <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen> <!-- The height of the search bar space. --> <dimen name="recents_search_bar_space_height">64dp</dimen> + <!-- The side padding for the task stack as a percentage of the width. --> + <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.04444</item> + + <!-- The top offset for the task stack. --> + <dimen name="recents_stack_top_padding">16dp</dimen> + <!-- Used to calculate the translation animation duration, the expected amount of movement in dps over one second of time. --> <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen> @@ -302,4 +314,7 @@ <!-- Volume panel dialog width --> <dimen name="volume_panel_width">300dp</dimen> + + <!-- Volume panel z depth --> + <dimen name="volume_panel_z">3dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ef3956e..59f1efd 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -522,7 +522,7 @@ <string name="quick_settings_notifications_label">Notifications</string> <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] --> - <string name="recents_empty_message">RECENTS</string> + <string name="recents_empty_message">No recent apps</string> <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] --> <string name="recents_app_info_button_label">Application Info</string> <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 626fc0d..c8cf05d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -47,8 +47,10 @@ public class QSPanel extends ViewGroup { private int mCellHeight; private int mLargeCellWidth; private int mLargeCellHeight; + private boolean mExpanded; private TileRecord mDetailRecord; + private Callback mCallback; public QSPanel(Context context) { this(context, null); @@ -59,6 +61,7 @@ public class QSPanel extends ViewGroup { mContext = context; mDetail = new FrameLayout(mContext); + mDetail.setBackgroundColor(mContext.getResources().getColor(R.color.system_primary_color)); mDetail.setVisibility(GONE); mDetail.setClickable(true); addView(mDetail); @@ -66,6 +69,10 @@ public class QSPanel extends ViewGroup { updateResources(); } + public void setCallback(Callback callback) { + mCallback = callback; + } + public void updateResources() { final Resources res = mContext.getResources(); final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns)); @@ -84,12 +91,14 @@ public class QSPanel extends ViewGroup { } public void setExpanded(boolean expanded) { - if (!expanded) { + if (mExpanded == expanded) return; + mExpanded = expanded; + if (!mExpanded) { showDetail(false /*show*/, mDetailRecord); } for (TileRecord r : mRecords) { - r.tile.setListening(expanded); - if (expanded) { + r.tile.setListening(mExpanded); + if (mExpanded) { r.tile.refreshState(); } } @@ -156,6 +165,7 @@ public class QSPanel extends ViewGroup { if (mDetailRecord == null) return; listener = mTeardownDetailWhenDone; } + fireShowingDetail(show); int x = r.tileView.getLeft() + r.tileView.getWidth() / 2; int y = r.tileView.getTop() + r.tileView.getHeight() / 2; mClipper.animateCircularClip(x, y, show, listener); @@ -195,7 +205,7 @@ public class QSPanel extends ViewGroup { mDetail.measure(exactly(width), unspecified()); if (mDetail.getVisibility() == VISIBLE && mDetail.getChildCount() > 0) { final int dmh = mDetail.getMeasuredHeight(); - if (dmh > 0) h = dmh; + if (dmh > 0) h = Math.max(h, dmh); } setMeasuredDimension(width, h); } @@ -222,7 +232,8 @@ public class QSPanel extends ViewGroup { left + record.tileView.getMeasuredWidth(), top + record.tileView.getMeasuredHeight()); } - mDetail.layout(0, 0, mDetail.getMeasuredWidth(), mDetail.getMeasuredHeight()); + final int dh = Math.max(mDetail.getMeasuredHeight(), getMeasuredHeight()); + mDetail.layout(0, 0, mDetail.getMeasuredWidth(), dh); } private int getRowTop(int row) { @@ -239,6 +250,12 @@ public class QSPanel extends ViewGroup { return cols; } + private void fireShowingDetail(boolean showingDetail) { + if (mCallback != null) { + mCallback.onShowingDetail(showingDetail); + } + } + private class H extends Handler { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; @@ -265,4 +282,8 @@ public class QSPanel extends ViewGroup { mDetailRecord = null; }; }; + + public interface Callback { + void onShowingDetail(boolean showingDetail); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index ffd64d4..ca9bb94 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -35,6 +35,7 @@ import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.os.SystemClock; import android.os.UserHandle; import android.util.DisplayMetrics; import android.view.Display; @@ -49,7 +50,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** A proxy implementation for the recents component */ -public class AlternateRecentsComponent { +public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener { /** A handler for messages from the recents implementation */ class RecentsMessageHandler extends Handler { @@ -62,12 +63,15 @@ public class AlternateRecentsComponent { Bundle replyData = msg.getData().getParcelable(KEY_CONFIGURATION_DATA); mSingleCountFirstTaskRect = replyData.getParcelable(KEY_SINGLE_TASK_STACK_RECT); mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight); + mTwoCountFirstTaskRect = replyData.getParcelable(KEY_TWO_TASK_STACK_RECT); + mTwoCountFirstTaskRect.offset(0, (int) statusBarHeight); mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT); mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight); if (Console.Enabled) { Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|RecentsMessageHandler|handleMessage]", "singleTaskRect: " + mSingleCountFirstTaskRect + + " twoTaskRect: " + mTwoCountFirstTaskRect + " multipleTaskRect: " + mMultipleCountFirstTaskRect); } @@ -123,6 +127,7 @@ public class AlternateRecentsComponent { final public static int MSG_SHOW_RECENTS = 4; final public static int MSG_HIDE_RECENTS = 5; final public static int MSG_TOGGLE_RECENTS = 6; + final public static int MSG_START_ENTER_ANIMATION = 7; final public static String EXTRA_ANIMATING_WITH_THUMBNAIL = "recents.animatingWithThumbnail"; final public static String EXTRA_FROM_ALT_TAB = "recents.triggeredFromAltTab"; @@ -130,6 +135,7 @@ public class AlternateRecentsComponent { final public static String KEY_WINDOW_RECT = "recents.windowRect"; final public static String KEY_SYSTEM_INSETS = "recents.systemInsets"; final public static String KEY_SINGLE_TASK_STACK_RECT = "recents.singleCountTaskRect"; + final public static String KEY_TWO_TASK_STACK_RECT = "recents.twoCountTaskRect"; final public static String KEY_MULTIPLE_TASK_STACK_RECT = "recents.multipleCountTaskRect"; @@ -155,6 +161,7 @@ public class AlternateRecentsComponent { boolean mTriggeredFromAltTab; Rect mSingleCountFirstTaskRect = new Rect(); + Rect mTwoCountFirstTaskRect = new Rect(); Rect mMultipleCountFirstTaskRect = new Rect(); long mLastToggleTime; @@ -261,8 +268,10 @@ public class AlternateRecentsComponent { /** Returns whether we have valid task rects to animate to. */ boolean hasValidTaskRects() { return mSingleCountFirstTaskRect != null && mSingleCountFirstTaskRect.width() > 0 && - mSingleCountFirstTaskRect.height() > 0 && mMultipleCountFirstTaskRect != null && - mMultipleCountFirstTaskRect.width() > 0 && mMultipleCountFirstTaskRect.height() > 0; + mSingleCountFirstTaskRect.height() > 0 && mTwoCountFirstTaskRect != null && + mTwoCountFirstTaskRect.width() > 0 && mTwoCountFirstTaskRect.height() > 0 && + mMultipleCountFirstTaskRect != null && mMultipleCountFirstTaskRect.width() > 0 && + mMultipleCountFirstTaskRect.height() > 0; } /** Updates each of the task animation rects. */ @@ -303,8 +312,8 @@ public class AlternateRecentsComponent { return null; } - /** Returns whether there is are multiple recents tasks */ - boolean hasMultipleRecentsTask(List<ActivityManager.RecentTaskInfo> tasks) { + /** Returns the proper rect to use for the animation, given the number of tasks. */ + Rect getAnimationTaskRect(List<ActivityManager.RecentTaskInfo> tasks) { // NOTE: Currently there's no method to get the number of non-home tasks, so we have to // compute this ourselves SystemServicesProxy ssp = mSystemServicesProxy; @@ -318,7 +327,13 @@ public class AlternateRecentsComponent { continue; } } - return (tasks.size() > 1); + if (tasks.size() <= 1) { + return mSingleCountFirstTaskRect; + } else if (tasks.size() <= 2) { + return mTwoCountFirstTaskRect; + } else { + return mMultipleCountFirstTaskRect; + } } /** Converts from the device rotation to the degree */ @@ -392,7 +407,7 @@ public class AlternateRecentsComponent { } return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail, - taskRect.left, taskRect.top, null); + taskRect.left, taskRect.top, this); } /** Returns whether the recents is currently running */ @@ -472,9 +487,8 @@ public class AlternateRecentsComponent { // which can differ depending on the number of items in the list. SystemServicesProxy ssp = mSystemServicesProxy; List<ActivityManager.RecentTaskInfo> recentTasks = - ssp.getRecentTasks(2, UserHandle.CURRENT.getIdentifier()); - Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect : - mSingleCountFirstTaskRect; + ssp.getRecentTasks(3, UserHandle.CURRENT.getIdentifier()); + Rect taskRect = getAnimationTaskRect(recentTasks); boolean useThumbnailTransition = !isTopTaskHome && hasValidTaskRects(); @@ -517,4 +531,18 @@ public class AlternateRecentsComponent { mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); } } + + + /**** OnAnimationStartedListener Implementation ****/ + + @Override + public void onAnimationStarted() { + // Notify recents to start the enter animation + try { + Message msg = Message.obtain(null, MSG_START_ENTER_ANIMATION, 0, 0); + mService.send(msg); + } catch (RemoteException re) { + re.printStackTrace(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index 57957a8..76e88a5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -36,7 +36,7 @@ public class Constants { // Enables the search bar layout public static final boolean EnableSearchLayout = true; // Enables the dynamic shadows behind each task - public static final boolean EnableShadows = false; + public static final boolean EnableShadows = true; // This disables the bitmap and icon caches public static final boolean DisableBackgroundCache = false; // For debugging, this enables us to create mock recents tasks @@ -101,8 +101,6 @@ public class Constants { public static final int TaskStackOverscrollRange = 150; public static final int FilterStartDelay = 25; - // The padding will be applied to the smallest dimension, and then applied to all sides - public static final float StackPaddingPct = 0.1f; // The overlap height relative to the task height public static final float StackOverlapPct = 0.65f; // The height of the peek space relative to the stack height @@ -113,4 +111,4 @@ public class Constants { public static final int StackPeekNumCards = 3; } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index befe8b4..df387c1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -98,6 +98,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // If there are no filtered stacks, dismiss recents and launch the first task dismissRecentsIfVisible(); } + } else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) { + // Try and start the enter animation + mRecentsView.startOnEnterAnimation(); } } }; @@ -345,6 +348,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView IntentFilter filter = new IntentFilter(); filter.addAction(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY); filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY); + filter.addAction(RecentsService.ACTION_START_ENTER_ANIMATION); registerReceiver(mServiceBroadcastReceiver, filter); // Register the broadcast receiver to handle messages when the screen is turned off diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 03f7e36..6391685 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -46,26 +46,37 @@ public class RecentsConfiguration { public float animationPxMovementPerSecond; - public Interpolator defaultBezierInterpolator; + public Interpolator fastOutSlowInInterpolator; + public Interpolator fastOutLinearInInterpolator; + public Interpolator linearOutSlowInInterpolator; public int filteringCurrentViewsMinAnimDuration; public int filteringNewViewsMinAnimDuration; - public int taskBarEnterAnimDuration; - public int taskBarExitAnimDuration; + public int taskStackScrollDismissInfoPaneDistance; public int taskStackMaxDim; + public float taskStackWidthPaddingPct; + public int taskStackTopPaddingPx; + public int taskViewInfoPaneAnimDuration; public int taskViewRemoveAnimDuration; public int taskViewRemoveAnimTranslationXPx; public int taskViewTranslationZMinPx; public int taskViewTranslationZIncrementPx; + public int taskViewShadowOutlineBottomInsetPx; public int taskViewRoundedCornerRadiusPx; + public int taskViewHighlightPx; + public int searchBarSpaceHeightPx; public int taskBarViewDefaultBackgroundColor; public int taskBarViewDefaultTextColor; public int taskBarViewLightTextColor; public int taskBarViewDarkTextColor; + public int taskBarViewHighlightColor; + + public int taskBarEnterAnimDuration; + public int taskBarExitAnimDuration; public boolean launchedFromAltTab; public boolean launchedWithThumbnailAnimation; @@ -112,13 +123,16 @@ public class RecentsConfiguration { res.getInteger(R.integer.recents_filter_animate_current_views_min_duration); filteringNewViewsMinAnimDuration = res.getInteger(R.integer.recents_filter_animate_new_views_min_duration); - taskBarEnterAnimDuration = - res.getInteger(R.integer.recents_animate_task_bar_enter_duration); - taskBarExitAnimDuration = - res.getInteger(R.integer.recents_animate_task_bar_exit_duration); + taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize( R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance); taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim); + + TypedValue widthPaddingPctValue = new TypedValue(); + res.getValue(R.dimen.recents_stack_width_padding_percentage, widthPaddingPctValue, true); + taskStackWidthPaddingPct = widthPaddingPctValue.getFloat(); + taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding); + taskViewInfoPaneAnimDuration = res.getInteger(R.integer.recents_animate_task_view_info_pane_duration); taskViewRemoveAnimDuration = @@ -127,9 +141,13 @@ public class RecentsConfiguration { res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x); taskViewRoundedCornerRadiusPx = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); + taskViewHighlightPx = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight); taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min); taskViewTranslationZIncrementPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment); + taskViewShadowOutlineBottomInsetPx = + res.getDimensionPixelSize(R.dimen.recents_task_view_shadow_outline_bottom_inset); + searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height); taskBarViewDefaultBackgroundColor = @@ -140,9 +158,20 @@ public class RecentsConfiguration { res.getColor(R.color.recents_task_bar_light_text_color); taskBarViewDarkTextColor = res.getColor(R.color.recents_task_bar_dark_text_color); + taskBarViewHighlightColor = + res.getColor(R.color.recents_task_bar_highlight_color); - defaultBezierInterpolator = AnimationUtils.loadInterpolator(context, + taskBarEnterAnimDuration = + res.getInteger(R.integer.recents_animate_task_bar_enter_duration); + taskBarExitAnimDuration = + res.getInteger(R.integer.recents_animate_task_bar_exit_duration); + + fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); + fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.fast_out_linear_in); + linearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.linear_out_slow_in); // Check if the developer options are enabled ContentResolver cr = context.getContentResolver(); @@ -167,6 +196,13 @@ public class RecentsConfiguration { appWidgetId).apply(); } + /** Called when the configuration has changed, and we want to reset any configuration specific + * members. */ + public void updateOnConfigurationChange() { + launchedFromAltTab = false; + launchedWithThumbnailAnimation = false; + } + /** Returns whether the search bar app widget exists */ public boolean hasSearchBarAppWidget() { return searchBarAppWidgetId >= 0; diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java index 4bdbb20..0c2c11d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java @@ -55,7 +55,8 @@ class SystemUIMessageHandler extends Handler { if (msg.what == AlternateRecentsComponent.MSG_UPDATE_FOR_CONFIGURATION) { RecentsTaskLoader.initialize(context); - RecentsConfiguration.reinitialize(context); + RecentsConfiguration config = RecentsConfiguration.reinitialize(context); + config.updateOnConfigurationChange(); try { Bundle data = msg.getData(); @@ -73,7 +74,6 @@ class SystemUIMessageHandler extends Handler { // Get the task stack and search bar bounds Rect taskStackBounds = new Rect(); - RecentsConfiguration config = RecentsConfiguration.getInstance(); config.getTaskStackBounds(windowRect.width(), windowRect.height(), taskStackBounds); // Calculate the target task rect for when there is one task. @@ -83,20 +83,29 @@ class SystemUIMessageHandler extends Handler { stack.addTask(new Task()); tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() - systemInsets.top - systemInsets.bottom, 0, 0); - tsv.boundScroll(); + tsv.setStackScrollToInitialState(); transform = tsv.getStackTransform(0, tsv.getStackScroll()); transform.rect.offset(taskStackBounds.left, taskStackBounds.top); replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT, new Rect(transform.rect)); - // Also calculate the target task rect when there are multiple tasks. + // Also calculate the target task rect when there are two tasks. stack.addTask(new Task()); tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() - systemInsets.top - systemInsets.bottom, 0, 0); - tsv.setStackScrollRaw(Integer.MAX_VALUE); - tsv.boundScroll(); + tsv.setStackScrollToInitialState(); transform = tsv.getStackTransform(1, tsv.getStackScroll()); transform.rect.offset(taskStackBounds.left, taskStackBounds.top); + replyData.putParcelable(AlternateRecentsComponent.KEY_TWO_TASK_STACK_RECT, + new Rect(transform.rect)); + + // Also calculate the target task rect when there are two tasks. + stack.addTask(new Task()); + tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() - + systemInsets.top - systemInsets.bottom, 0, 0); + tsv.setStackScrollToInitialState(); + transform = tsv.getStackTransform(2, tsv.getStackScroll()); + transform.rect.offset(taskStackBounds.left, taskStackBounds.top); replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT, new Rect(transform.rect)); @@ -127,6 +136,11 @@ class SystemUIMessageHandler extends Handler { Constants.Log.App.TimeRecentsStartupKey, "receivedToggleRecents"); Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask, Constants.Log.App.TimeRecentsLaunchKey, "receivedToggleRecents"); + } else if (msg.what == AlternateRecentsComponent.MSG_START_ENTER_ANIMATION) { + // Send a broadcast to start the enter animation + Intent intent = new Intent(RecentsService.ACTION_START_ENTER_ANIMATION); + intent.setPackage(context.getPackageName()); + context.sendBroadcast(intent); } } } @@ -135,6 +149,7 @@ class SystemUIMessageHandler extends Handler { public class RecentsService extends Service { final static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity"; final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity"; + final static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation"; final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab"; Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this)); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index cad9ce5..6005275 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -158,6 +158,18 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV return false; } + /** Requests all task stacks to start their enter-recents animation */ + public void startOnEnterAnimation() { + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child instanceof TaskStackView) { + TaskStackView stackView = (TaskStackView) child; + stackView.startOnEnterAnimation(); + } + } + } + /** Adds the search bar */ public void setSearchBar(View searchBar) { // Create the search bar (and hide it if we have no recent tasks) diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java index 3ee0545..cae6bd7 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java @@ -278,6 +278,7 @@ public class SwipeHelper { if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) { view.setAlpha(getAlphaForOffset(view)); } + mCallback.onSwipeChanged(mCurrView, view.getTranslationX()); } }); anim.addListener(new AnimatorListenerAdapter() { @@ -313,6 +314,7 @@ public class SwipeHelper { if (mCurrView != null) { float delta = getPos(ev) - mInitialTouchPos; setSwipeAmount(delta); + mCallback.onSwipeChanged(mCurrView, delta); } break; case MotionEvent.ACTION_UP: @@ -393,6 +395,8 @@ public class SwipeHelper { void onBeginDrag(View v); + void onSwipeChanged(View v, float delta); + void onChildDismissed(View v); void onSnapBackCompleted(View v); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java index 07caa1b..c10ddd1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java @@ -16,9 +16,12 @@ package com.android.systemui.recents.views; -import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.FrameLayout; @@ -42,6 +45,8 @@ class TaskBarView extends FrameLayout { Drawable mLightDismissDrawable; Drawable mDarkDismissDrawable; + static Paint sHighlightPaint; + public TaskBarView(Context context) { this(context, null); } @@ -56,9 +61,23 @@ class TaskBarView extends FrameLayout { public TaskBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + setWillNotDraw(false); + + // Load the dismiss resources Resources res = context.getResources(); mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light); mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark); + + // Configure the highlight paint + if (sHighlightPaint == null) { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + sHighlightPaint = new Paint(); + sHighlightPaint.setStyle(Paint.Style.STROKE); + sHighlightPaint.setStrokeWidth(config.taskViewHighlightPx); + sHighlightPaint.setColor(config.taskBarViewHighlightColor); + sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); + sHighlightPaint.setAntiAlias(true); + } } @Override @@ -69,6 +88,17 @@ class TaskBarView extends FrameLayout { mDismissButton = (ImageView) findViewById(R.id.dismiss_task); } + @Override + protected void onDraw(Canvas canvas) { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + + // Draw the highlight at the top edge (but put the bottom edge just out of view) + float offset = config.taskViewHighlightPx / 2f; + float radius = config.taskViewRoundedCornerRadiusPx; + canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset, + getMeasuredHeight() + radius, radius, radius, sHighlightPaint); + } + /** Synchronizes this bar view's properties with the task's transform */ void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform, TaskViewTransform toTransform, int duration) { @@ -81,7 +111,7 @@ class TaskBarView extends FrameLayout { .alpha(toTransform.dismissAlpha) .setStartDelay(0) .setDuration(duration) - .setInterpolator(config.defaultBezierInterpolator) + .setInterpolator(config.fastOutSlowInInterpolator) .withLayer() .start(); } else { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 2b08b19..053f122 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -23,7 +23,6 @@ import android.animation.ValueAnimator; import android.app.Activity; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.Region; @@ -88,6 +87,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int mStackViewsAnimationDuration; boolean mStackViewsDirty = true; boolean mAwaitingFirstLayout = true; + boolean mStartEnterAnimationRequestedAfterLayout; int[] mTmpVisibleRange = new int[2]; Rect mTmpRect = new Rect(); Rect mTmpRect2 = new Rect(); @@ -172,7 +172,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Set the alphas - transform.dismissAlpha = Math.max(-1f, Math.min(0f, t)) + 1f; + transform.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f; // Update the rect and visibility transform.rect.set(mTaskRect); @@ -300,6 +300,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public void setStackScrollRaw(int value) { mStackScroll = value; } + /** Sets the current stack scroll to the initial state when you first enter recents */ + public void setStackScrollToInitialState() { + if (mStack.getTaskCount() > 2) { + int initialScroll = mMaxScroll - mTaskRect.height() / 2; + setStackScroll(initialScroll); + } else { + setStackScroll(mMaxScroll); + } + } /** * Returns the scroll to such that the task transform at that index will have t=0. (If the scroll @@ -344,7 +353,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll); mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll - curScroll, 250)); - mScrollAnimator.setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator); + mScrollAnimator.setInterpolator(RecentsConfiguration.getInstance().fastOutSlowInInterpolator); mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { @@ -636,6 +645,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Note: We let the stack view be the full height because we want the cards to go under the // navigation bar if possible. However, the stack rects which we use to calculate // max scroll, etc. need to take the nav bar into account + RecentsConfiguration config = RecentsConfiguration.getInstance(); // Compute the stack rects mRect.set(0, 0, width, height); @@ -643,23 +653,21 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mStackRect.left += insetLeft; mStackRect.bottom -= insetBottom; - int smallestDimension = Math.min(width, height); - int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f); + int widthPadding = (int) (config.taskStackWidthPaddingPct * mStackRect.width()); + int heightPadding = config.taskStackTopPaddingPx; if (Constants.DebugFlags.App.EnableSearchLayout) { - mStackRect.top += padding; - mStackRect.left += padding; - mStackRect.right -= padding; - mStackRect.bottom -= padding; + mStackRect.top += heightPadding; + mStackRect.left += widthPadding; + mStackRect.right -= widthPadding; + mStackRect.bottom -= heightPadding; } else { - mStackRect.inset(padding, padding); + mStackRect.inset(widthPadding, heightPadding); } mStackRectSansPeek.set(mStackRect); mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height(); // Compute the task rect - int minHeight = (int) (mStackRect.height() - - (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height())); - int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height())); + int size = mStackRect.width(); int left = mStackRect.left + (mStackRect.width() - size) / 2; mTaskRect.set(left, mStackRectSansPeek.top, left + size, mStackRectSansPeek.top + size); @@ -700,22 +708,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // If this is the first layout, then scroll to the front of the stack and synchronize the // stack views immediately if (mAwaitingFirstLayout) { - setStackScroll(mMaxScroll); + setStackScrollToInitialState(); requestSynchronizeStackViewsWithModel(); synchronizeStackViewsWithModel(); - - // Update the focused task index to be the next item to the top task - if (config.launchedFromAltTab) { - focusTask(Math.max(0, mStack.getTaskCount() - 2), false); - } - - // Animate the task bar of the first task view - if (config.launchedWithThumbnailAnimation) { - TaskView tv = (TaskView) getChildAt(getChildCount() - 1); - if (tv != null) { - tv.animateOnEnterRecents(); - } - } } // Measure each of the children @@ -758,7 +753,47 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } if (mAwaitingFirstLayout) { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + + // Update the focused task index to be the next item to the top task + if (config.launchedFromAltTab) { + focusTask(Math.max(0, mStack.getTaskCount() - 2), false); + } + + // Prepare the first view for its enter animation + if (config.launchedWithThumbnailAnimation) { + TaskView tv = (TaskView) getChildAt(getChildCount() - 1); + if (tv != null) { + tv.prepareAnimateOnEnterRecents(); + } + } + + // Mark that we have completely the first layout mAwaitingFirstLayout = false; + + // If the enter animation started already and we haven't completed a layout yet, do the + // enter animation now + if (mStartEnterAnimationRequestedAfterLayout) { + startOnEnterAnimation(); + } + } + } + + /** Requests this task stacks to start it's enter-recents animation */ + public void startOnEnterAnimation() { + RecentsConfiguration config = RecentsConfiguration.getInstance(); + if (!config.launchedWithThumbnailAnimation) return; + + // If we are still waiting to layout, then just defer until then + if (mAwaitingFirstLayout) { + mStartEnterAnimationRequestedAfterLayout = true; + return; + } + + // Animate the task bar of the first task view + TaskView tv = (TaskView) getChildAt(getChildCount() - 1); + if (tv != null) { + tv.animateOnEnterRecents(); } } @@ -1529,6 +1564,11 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } @Override + public void onSwipeChanged(View v, float delta) { + // Do nothing + } + + @Override public void onChildDismissed(View v) { TaskView tv = (TaskView) v; mSv.onTaskDismissed(tv); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 8575661..ffa181d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -21,7 +21,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Outline; -import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; @@ -113,7 +112,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On // Update the outline Outline o = new Outline(); - o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), radius); + o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - + config.taskViewShadowOutlineBottomInsetPx, radius); setOutline(o); } @@ -167,7 +167,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On .scaleY(toTransform.scale) .alpha(toTransform.alpha) .setDuration(duration) - .setInterpolator(config.defaultBezierInterpolator) + .setInterpolator(config.fastOutSlowInInterpolator) .withLayer() .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override @@ -221,14 +221,21 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On fromTransform.alpha = 0f; } + /** Prepares this task view for the enter-recents animations. This is called earlier in the + * first layout because the actual animation into recents may take a long time. */ + public void prepareAnimateOnEnterRecents() { + mBarView.setVisibility(View.INVISIBLE); + } + /** Animates this task view as it enters recents */ public void animateOnEnterRecents() { RecentsConfiguration config = RecentsConfiguration.getInstance(); - mBarView.setAlpha(0f); + mBarView.setVisibility(View.VISIBLE); + mBarView.setTranslationY(-mBarView.getMeasuredHeight()); mBarView.animate() - .alpha(1f) - .setStartDelay(300) - .setInterpolator(config.defaultBezierInterpolator) + .translationY(0) + .setStartDelay(200) + .setInterpolator(config.fastOutSlowInInterpolator) .setDuration(config.taskBarEnterAnimDuration) .withLayer() .start(); @@ -238,9 +245,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On public void animateOnLeavingRecents(final Runnable r) { RecentsConfiguration config = RecentsConfiguration.getInstance(); mBarView.animate() - .alpha(0f) + .translationY(-mBarView.getMeasuredHeight()) .setStartDelay(0) - .setInterpolator(config.defaultBezierInterpolator) + .setInterpolator(config.fastOutLinearInInterpolator) .setDuration(config.taskBarExitAnimDuration) .withLayer() .withEndAction(new Runnable() { @@ -261,7 +268,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On animate().translationX(config.taskViewRemoveAnimTranslationXPx) .alpha(0f) .setStartDelay(0) - .setInterpolator(config.defaultBezierInterpolator) + .setInterpolator(config.fastOutSlowInInterpolator) .setDuration(config.taskViewRemoveAnimDuration) .withLayer() .withEndAction(new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index fbe76f9..06cc476 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -83,6 +83,7 @@ import com.android.systemui.statusbar.phone.KeyguardTouchDelegate; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Locale; @@ -117,6 +118,9 @@ public abstract class BaseStatusBar extends SystemUI implements public static final int EXPANDED_LEAVE_ALONE = -10000; public static final int EXPANDED_FULL_OPEN = -10001; + /** If true, delays dismissing the Keyguard until the ActivityManager calls back. */ + protected static final boolean DELAY_DISMISS_TO_ACTIVITY_LAUNCH = false; + protected CommandQueue mCommandQueue; protected IStatusBarService mBarService; protected H mHandler = createHandler(); @@ -182,6 +186,7 @@ public abstract class BaseStatusBar extends SystemUI implements */ protected int mState; protected boolean mBouncerShowing; + protected boolean mShowLockscreenNotifications; protected NotificationOverflowContainer mKeyguardIconOverflowContainer; @@ -201,6 +206,9 @@ public abstract class BaseStatusBar extends SystemUI implements final int mode = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF); setZenMode(mode); + final boolean show = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1) != 0; + setShowLockscreenNotifications(show); } }; @@ -224,7 +232,7 @@ public abstract class BaseStatusBar extends SystemUI implements } final boolean isActivity = pendingIntent.isActivity(); if (isActivity) { - startNotificationActivity(new OnDismissAction() { + dismissKeyguardThenExecute(new OnDismissAction() { @Override public boolean onDismiss() { try { @@ -246,7 +254,8 @@ public abstract class BaseStatusBar extends SystemUI implements animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); visibilityChanged(false); } - return handled; // Wait for activity start. + // Wait for activity start. + return handled && DELAY_DISMISS_TO_ACTIVITY_LAUNCH; } }); return true; @@ -328,8 +337,7 @@ public abstract class BaseStatusBar extends SystemUI implements mHandler.post(new Runnable() { @Override public void run() { - mNotificationData.updateRanking(currentRanking); - updateNotifications(); + updateRankingInternal(currentRanking); } }); } @@ -362,6 +370,9 @@ public abstract class BaseStatusBar extends SystemUI implements mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false, mSettingsObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS), false, + mSettingsObserver); mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS), @@ -472,7 +483,7 @@ public abstract class BaseStatusBar extends SystemUI implements * Takes the necessary steps to prepare the status bar for starting an activity, then starts it. * @param action A dismiss action that is called if it's safe to start the activity. */ - protected void startNotificationActivity(OnDismissAction action) { + protected void dismissKeyguardThenExecute(OnDismissAction action) { action.onDismiss(); } @@ -1042,7 +1053,7 @@ public abstract class BaseStatusBar extends SystemUI implements } public void onClick(final View v) { - startNotificationActivity(new OnDismissAction() { + dismissKeyguardThenExecute(new OnDismissAction() { public boolean onDismiss() { try { // The intent we are sending is for the application, which @@ -1062,7 +1073,7 @@ public abstract class BaseStatusBar extends SystemUI implements v.getLocationOnScreen(pos); Intent overlay = new Intent(); overlay.setSourceBounds(new Rect(pos[0], pos[1], - pos[0]+v.getWidth(), pos[1]+v.getHeight())); + pos[0] + v.getWidth(), pos[1] + v.getHeight())); try { mIntent.send(mContext, 0, overlay); sent = true; @@ -1087,7 +1098,7 @@ public abstract class BaseStatusBar extends SystemUI implements visibilityChanged(false); boolean waitForActivityLaunch = sent && mIntent.isActivity(); - return waitForActivityLaunch; + return waitForActivityLaunch && DELAY_DISMISS_TO_ACTIVITY_LAUNCH; } }); } @@ -1247,6 +1258,10 @@ public abstract class BaseStatusBar extends SystemUI implements updateNotifications(); } + protected void setShowLockscreenNotifications(boolean show) { + mShowLockscreenNotifications = show; + } + protected abstract void haltTicker(); protected abstract void setAreThereNotifications(); protected abstract void updateNotifications(); @@ -1264,6 +1279,8 @@ public abstract class BaseStatusBar extends SystemUI implements public abstract void addNotificationInternal(StatusBarNotification notification, Ranking ranking); + protected abstract void updateRankingInternal(Ranking ranking); + @Override public void removeNotification(String key) { if (!USE_NOTIFICATION_LISTENER) { @@ -1271,7 +1288,7 @@ public abstract class BaseStatusBar extends SystemUI implements } } - protected abstract void removeNotificationInternal(String key, Ranking ranking); + public abstract void removeNotificationInternal(String key, Ranking ranking); public void updateNotification(StatusBarNotification notification) { if (!USE_NOTIFICATION_LISTENER) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java index 24da5c2..de27119 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java @@ -20,8 +20,10 @@ import android.app.Notification; import android.content.Context; import android.os.Process; import android.provider.Settings; +import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; +import android.util.ArraySet; import android.view.View; import com.android.systemui.R; @@ -30,12 +32,13 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; public class InterceptedNotifications { private static final String TAG = "InterceptedNotifications"; - private static final String EXTRA_INTERCEPT = "android.intercept"; + private static final String SYNTHETIC_KEY = "InterceptedNotifications.SYNTHETIC_KEY"; private final Context mContext; private final PhoneStatusBar mBar; private final ArrayMap<String, StatusBarNotification> mIntercepted = new ArrayMap<String, StatusBarNotification>(); + private final ArraySet<String> mReleased = new ArraySet<String>(); private String mSynKey; @@ -48,25 +51,45 @@ public class InterceptedNotifications { final int n = mIntercepted.size(); for (int i = 0; i < n; i++) { final StatusBarNotification sbn = mIntercepted.valueAt(i); - sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false); + mReleased.add(sbn.getKey()); mBar.addNotificationInternal(sbn, null); } mIntercepted.clear(); updateSyntheticNotification(); } - public boolean tryIntercept(StatusBarNotification notification) { - if (!notification.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) return false; + public boolean tryIntercept(StatusBarNotification notification, Ranking ranking) { + if (ranking == null) return false; if (shouldDisplayIntercepted()) return false; + if (mReleased.contains(notification.getKey())) return false; + if (!ranking.isInterceptedByDoNotDisturb(notification.getKey())) return false; mIntercepted.put(notification.getKey(), notification); updateSyntheticNotification(); return true; } + public void retryIntercepts(Ranking ranking) { + if (ranking == null) return; + + boolean changed = false; + final int N = mIntercepted.size(); + for (int i = 0; i < N; i++) { + final StatusBarNotification sbn = mIntercepted.valueAt(i); + if (!tryIntercept(sbn, ranking)) { + changed = true; + mBar.addNotificationInternal(sbn, ranking); + } + } + if (changed) { + updateSyntheticNotification(); + } + } + public void remove(String key) { if (mIntercepted.remove(key) != null) { updateSyntheticNotification(); } + mReleased.remove(key); } public boolean isSyntheticEntry(Entry ent) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 802e5e5..c8f185c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -47,6 +47,8 @@ public class NotificationPanelView extends PanelView implements ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener, View.OnClickListener, KeyguardPageSwipeHelper.Callback { + private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.4f; + private KeyguardPageSwipeHelper mPageSwiper; PhoneStatusBar mStatusBar; private StatusBarHeaderView mHeader; @@ -70,6 +72,7 @@ public class NotificationPanelView extends PanelView implements */ private boolean mIntercepting; private boolean mQsExpanded; + private boolean mQsFullyExpanded; private boolean mKeyguardShowing; private float mInitialHeightOnTouch; private float mInitialTouchX; @@ -165,7 +168,9 @@ public class NotificationPanelView extends PanelView implements mQsMinExpansionHeight = mHeader.getCollapsedHeight() + mQsPeekHeight; mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight(); if (mQsExpanded) { - setQsStackScrollerPadding(mQsMaxExpansionHeight); + if (mQsFullyExpanded) { + setQsStackScrollerPadding(mQsMaxExpansionHeight); + } } else { setQsExpansion(mQsMinExpansionHeight); positionClockAndNotifications(); @@ -522,6 +527,7 @@ public class NotificationPanelView extends PanelView implements private void setQsExpansion(float height) { height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight); + mQsFullyExpanded = height == mQsMaxExpansionHeight; if (height > mQsMinExpansionHeight && !mQsExpanded) { setQsExpanded(true); } else if (height <= mQsMinExpansionHeight && mQsExpanded) { @@ -701,8 +707,11 @@ public class NotificationPanelView extends PanelView implements @Override protected void onOverExpansionChanged(float overExpansion) { float currentOverScroll = mNotificationStackScroller.getCurrentOverScrolledPixels(true); - mNotificationStackScroller.setOverScrolledPixels(currentOverScroll + overExpansion - - mOverExpansion, true /* onTop */, false /* animate */); + float expansionChange = overExpansion - mOverExpansion; + expansionChange *= EXPANSION_RUBBER_BAND_EXTRA_FACTOR; + mNotificationStackScroller.setOverScrolledPixels(currentOverScroll + expansionChange, + true /* onTop */, + false /* animate */); super.onOverExpansionChanged(overExpansion); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 5dcd61c..f9afcf3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -505,6 +505,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override + protected void setShowLockscreenNotifications(boolean show) { + super.setShowLockscreenNotifications(show); + updateStackScrollerState(); + } + + @Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); @@ -1044,7 +1050,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (shadeEntry == null) { return; } - if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification)) { + if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification, ranking)) { // Forward the ranking so we can sort the new notification. mNotificationData.updateRanking(ranking); return; @@ -1108,6 +1114,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override + protected void updateRankingInternal(Ranking ranking) { + mNotificationData.updateRanking(ranking); + mIntercepted.retryIntercepts(ranking); + updateNotifications(); + } + + @Override public void removeNotificationInternal(String key, Ranking ranking) { StatusBarNotification old = removeNotificationViews(key, ranking); if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); @@ -2342,16 +2355,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }; - public void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned) { if (onlyProvisioned && !isDeviceProvisioned()) return; - try { - // Dismiss the lock screen when Settings starts. - ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); - } catch (RemoteException e) { - } - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); - animateCollapsePanels(); + + dismissKeyguardThenExecute(new OnDismissAction() { + @Override + public boolean onDismiss() { + try { + // Dismiss the lock screen when Settings starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { + } + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); + animateCollapsePanels(); + + return DELAY_DISMISS_TO_ACTIVITY_LAUNCH; + } + }); } private View.OnClickListener mClockClickListener = new View.OnClickListener() { @@ -2412,7 +2433,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, }; @Override - protected void startNotificationActivity(OnDismissAction action) { + protected void dismissKeyguardThenExecute(OnDismissAction action) { if (mStatusBarKeyguardViewManager.isShowing()) { mStatusBarKeyguardViewManager.dismissWithAction(action); } else { @@ -2851,7 +2872,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void updateStackScrollerState() { + if (mStackScroller == null) return; mStackScroller.setDimmed(mState == StatusBarState.KEYGUARD, false /* animate */); + mStackScroller.setVisibility(!mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD + ? View.INVISIBLE : View.VISIBLE); } public void userActivity() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 3245f1a..c097e2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -293,5 +293,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL public void setQSPanel(QSPanel qsp) { mQSPanel = qsp; + if (mQSPanel != null) { + mQSPanel.setCallback(mQsPanelCallback); + } } + + private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() { + @Override + public void onShowingDetail(boolean showingDetail) { + mBrightnessContainer.animate().alpha(showingDetail ? 0 : 1).withLayer().start(); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java index c2bd1cb..faea8de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.tv; import android.os.IBinder; +import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.StatusBarNotification; import android.view.View; @@ -54,11 +55,15 @@ public class TvStatusBar extends BaseStatusBar { } @Override + protected void updateRankingInternal(Ranking ranking) { + } + + @Override public void updateNotification(StatusBarNotification notification) { } @Override - protected void removeNotificationInternal(String key, Ranking ranking) { + public void removeNotificationInternal(String key, Ranking ranking) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java index 67f3a3d..cbfc641 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java @@ -25,12 +25,15 @@ import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; import android.media.AudioManager; import android.media.AudioService; import android.media.AudioSystem; import android.media.RingtoneManager; import android.media.ToneGenerator; import android.net.Uri; +import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.os.Vibrator; @@ -44,6 +47,7 @@ import android.view.ViewStub; import android.view.Window; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -76,6 +80,7 @@ public class VolumePanel extends Handler { private static final int MAX_VOLUME = 100; private static final int FREE_DELAY = 10000; private static final int TIMEOUT_DELAY = 3000; + private static final int TIMEOUT_DELAY_EXPANDED = 10000; private static final int MSG_VOLUME_CHANGED = 0; private static final int MSG_FREE_RESOURCES = 1; @@ -103,6 +108,7 @@ public class VolumePanel extends Handler { private boolean mRingIsSilent; private boolean mVoiceCapable; private boolean mZenModeCapable; + private int mTimeoutDelay = TIMEOUT_DELAY; // True if we want to play tones on the system stream when the master stream is specified. private final boolean mPlayMasterStreamTones; @@ -301,17 +307,26 @@ public class VolumePanel extends Handler { lp.y = res.getDimensionPixelOffset(com.android.systemui.R.dimen.volume_panel_top); lp.width = res.getDimensionPixelSize(com.android.systemui.R.dimen.volume_panel_width); lp.type = LayoutParams.TYPE_VOLUME_OVERLAY; + lp.format = PixelFormat.TRANSLUCENT; lp.windowAnimations = R.style.Animation_VolumePanel; - window.setBackgroundDrawableResource(com.android.systemui.R.drawable.qs_panel_background); window.setAttributes(lp); window.setGravity(Gravity.TOP); window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); window.requestFeature(Window.FEATURE_NO_TITLE); window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL - | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); + | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | LayoutParams.FLAG_HARDWARE_ACCELERATED); mDialog.setCanceledOnTouchOutside(true); - mDialog.setContentView(layoutId); + // temporary workaround for no window shadows + final FrameLayout layout = new FrameLayout(mContext); + final int z = res.getDimensionPixelSize(com.android.systemui.R.dimen.volume_panel_z); + layout.setPadding(z, z, z, z); + final View v = LayoutInflater.from(mContext).inflate(layoutId, layout, false); + v.setBackgroundResource(com.android.systemui.R.drawable.qs_panel_background); + v.setElevation(z); + layout.addView(v); + mDialog.setContentView(layout); mDialog.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { @@ -321,6 +336,7 @@ public class VolumePanel extends Handler { }); mDialog.create(); + mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x00000000)); mView = window.findViewById(R.id.content); mView.setOnTouchListener(new View.OnTouchListener() { @@ -513,6 +529,7 @@ public class VolumePanel extends Handler { @Override public void onInteraction() { + resetTimeout(); if (mZenPanelCallback != null) { mZenPanelCallback.onInteraction(); } @@ -521,6 +538,8 @@ public class VolumePanel extends Handler { } mZenPanel.setVisibility(View.VISIBLE); mZenPanelDivider.setVisibility(View.VISIBLE); + mTimeoutDelay = TIMEOUT_DELAY_EXPANDED; + resetTimeout(); } private void collapse() { @@ -529,6 +548,8 @@ public class VolumePanel extends Handler { mZenPanel.setVisibility(View.GONE); } mZenPanelDivider.setVisibility(View.GONE); + mTimeoutDelay = TIMEOUT_DELAY; + resetTimeout(); } public void updateStates() { @@ -1082,7 +1103,7 @@ public class VolumePanel extends Handler { public void resetTimeout() { if (LOGD) Log.d(mTag, "resetTimeout at " + System.currentTimeMillis()); removeMessages(MSG_TIMEOUT); - sendEmptyMessageDelayed(MSG_TIMEOUT, TIMEOUT_DELAY); + sendEmptyMessageDelayed(MSG_TIMEOUT, mTimeoutDelay); } private void forceTimeout() { @@ -1134,7 +1155,12 @@ public class VolumePanel extends Handler { public void onClick(View v) { if (v == mExpandButton && mZenController != null) { final boolean newZen = !mZenController.isZen(); - mZenController.setZen(newZen); + AsyncTask.execute(new Runnable() { + @Override + public void run() { + mZenController.setZen(newZen); + } + }); if (newZen) { expand(); } else { |