diff options
Diffstat (limited to 'packages')
30 files changed, 414 insertions, 117 deletions
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_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/colors.xml b/packages/SystemUI/res/values/colors.xml index 4e37dbb..e6fa535 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -67,7 +67,7 @@ <!-- 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. --> 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..61ed3cf 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -196,6 +196,9 @@ <dimen name="qs_dual_tile_height">109dp</dimen> <dimen name="qs_dual_tile_padding">12dp</dimen> + <!-- How far the hidden header peeks from the top of the screen when QS is in detail mode. --> + <dimen name="qs_header_peek_height">8dp</dimen> + <!-- How far the expanded QS panel peeks from the header in collapsed state. --> <dimen name="qs_peek_height">8dp</dimen> @@ -212,7 +215,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,10 +224,13 @@ <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> @@ -302,4 +308,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/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 41c0e78..4c7f3df 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -202,6 +202,12 @@ public class KeyguardService extends Service { checkPermission(); mKeyguardViewMediator.onBootCompleted(); } + + @Override + public void startKeyguardExitAnimation(long fadeoutDuration) { + checkPermission(); + mKeyguardViewMediator.startKeyguardExitAnimation(fadeoutDuration); + } }; } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index b2872fa..7110d8d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -46,7 +46,8 @@ import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.ViewGroup; -import android.view.WindowManager; +import android.view.IWindowManager; +import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import com.android.internal.policy.IKeyguardExitCallback; @@ -137,6 +138,7 @@ public class KeyguardViewMediator extends SystemUI { private static final int SET_OCCLUDED = 12; private static final int KEYGUARD_TIMEOUT = 13; private static final int DISMISS = 17; + private static final int START_KEYGUARD_EXIT_ANIM = 18; /** * The default amount of time we stay awake (used for all key input) @@ -180,6 +182,9 @@ public class KeyguardViewMediator extends SystemUI { /** High level access to the power manager for WakeLocks */ private PowerManager mPM; + /** High level access to the window manager for dismissing keyguard animation */ + private IWindowManager mWM; + /** UserManager for querying number of users */ private UserManager mUserManager; @@ -440,6 +445,7 @@ public class KeyguardViewMediator extends SystemUI { private void setup() { mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mWM = WindowManagerGlobal.getWindowManagerService(); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); mShowKeyguardWakeLock.setReferenceCounted(false); @@ -1076,6 +1082,9 @@ public class KeyguardViewMediator extends SystemUI { case DISMISS: handleDismiss(); break; + case START_KEYGUARD_EXIT_ANIM: + handleStartKeyguardExitAnimation((Long) msg.obj); + break; } } }; @@ -1207,6 +1216,19 @@ public class KeyguardViewMediator extends SystemUI { private void handleHide() { synchronized (KeyguardViewMediator.this) { if (DEBUG) Log.d(TAG, "handleHide"); + try { + + // Don't actually hide the Keyguard at the moment, wait for window manager until + // it tells us it's safe to do so with startKeyguardExitAnimation. + mWM.keyguardGoingAway(); + } catch (RemoteException e) { + Log.e(TAG, "Error while calling WindowManager", e); + } + } + } + + private void handleStartKeyguardExitAnimation(long fadeoutDuration) { + synchronized (KeyguardViewMediator.this) { // only play "unlock" noises if not on a call (since the incall UI // disables the keyguard) @@ -1324,6 +1346,11 @@ public class KeyguardViewMediator extends SystemUI { return mStatusBarKeyguardViewManager; } + public void startKeyguardExitAnimation(long fadeoutDuration) { + Message msg = mHandler.obtainMessage(START_KEYGUARD_EXIT_ANIM, fadeoutDuration); + mHandler.sendMessage(msg); + } + public ViewMediatorCallback getViewMediatorCallback() { return mViewMediatorCallback; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 626fc0d..6ce0e48 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); @@ -66,6 +68,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 +90,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 +164,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); @@ -239,6 +248,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 +280,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..4db81bf 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 @@ -102,7 +102,7 @@ public class Constants { 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; + public static final float StackPaddingPct = 0.085f; // 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 +113,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..1ae7a0d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -46,7 +46,9 @@ public class RecentsConfiguration { public float animationPxMovementPerSecond; - public Interpolator defaultBezierInterpolator; + public Interpolator fastOutSlowInInterpolator; + public Interpolator fastOutLinearInInterpolator; + public Interpolator linearOutSlowInInterpolator; public int filteringCurrentViewsMinAnimDuration; public int filteringNewViewsMinAnimDuration; @@ -59,6 +61,7 @@ public class RecentsConfiguration { public int taskViewRemoveAnimTranslationXPx; public int taskViewTranslationZMinPx; public int taskViewTranslationZIncrementPx; + public int taskViewShadowOutlineBottomInsetPx; public int taskViewRoundedCornerRadiusPx; public int searchBarSpaceHeightPx; @@ -130,6 +133,8 @@ public class RecentsConfiguration { 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 = @@ -141,8 +146,12 @@ public class RecentsConfiguration { taskBarViewDarkTextColor = res.getColor(R.color.recents_task_bar_dark_text_color); - defaultBezierInterpolator = AnimationUtils.loadInterpolator(context, + 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 +176,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..9e6c98e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java @@ -16,7 +16,6 @@ package com.android.systemui.recents.views; -import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -81,7 +80,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..1fbaf87 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) { @@ -700,22 +709,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 +754,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 +1565,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..422d47f 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; @@ -362,6 +371,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 +484,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 +1054,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 +1074,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 +1099,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 +1259,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(); 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..dce5a30 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -34,6 +34,7 @@ import android.view.animation.Interpolator; import android.widget.LinearLayout; import com.android.systemui.R; +import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.GestureRecorder; @@ -51,7 +52,7 @@ public class NotificationPanelView extends PanelView implements PhoneStatusBar mStatusBar; private StatusBarHeaderView mHeader; private View mQsContainer; - private View mQsPanel; + private QSPanel mQsPanel; private View mKeyguardStatusView; private ObservableScrollView mScrollView; private View mStackScrollerContainer; @@ -70,6 +71,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; @@ -81,13 +83,14 @@ public class NotificationPanelView extends PanelView implements private int mQsMaxExpansionHeight; private int mMinStackHeight; private int mQsPeekHeight; + private int mQsHeaderPeekHeight; + private boolean mQsShowingDetail; private float mNotificationTranslation; private int mStackScrollerIntrinsicPadding; private boolean mQsExpansionEnabled = true; private ValueAnimator mQsExpansionAnimator; private FlingAnimationUtils mFlingAnimationUtils; private int mStatusBarMinHeight; - private Interpolator mFastOutSlowInInterpolator; private ObjectAnimator mClockAnimator; private int mClockAnimationTarget = -1; @@ -130,7 +133,8 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusView = findViewById(R.id.keyguard_status_view); mStackScrollerContainer = findViewById(R.id.notification_container_parent); mQsContainer = findViewById(R.id.quick_settings_container); - mQsPanel = findViewById(R.id.quick_settings_panel); + mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel); + mQsPanel.setCallback(mQsPanelCallback); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); mScrollView.setListener(this); mNotificationStackScroller = (NotificationStackScrollLayout) @@ -154,6 +158,7 @@ public class NotificationPanelView extends PanelView implements mStatusBarMinHeight = getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height); + mQsHeaderPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_header_peek_height); mClockPositionAlgorithm.loadDimens(getResources()); } @@ -165,7 +170,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(); @@ -518,10 +525,39 @@ public class NotificationPanelView extends PanelView implements ? View.INVISIBLE : View.VISIBLE); mScrollView.setTouchEnabled(mQsExpanded); + if (mQsShowingDetail) { + if (mQsFullyExpanded) { + setQsHeaderPeeking(true); + } + } else { + setQsHeaderPeeking(false); + } + } + + private void setQsHeaderPeeking(boolean peeking) { + final boolean stackIsPeeking = mStackScrollerContainer.getTranslationY() != 0; + final boolean headerIsPeeking = mHeader.getTranslationY() != 0; + final int ty = mQsHeaderPeekHeight - mHeader.getExpandedHeight(); + if (peeking) { + if (!headerIsPeeking) { + mHeader.animate().translationY(ty); + } + if (!stackIsPeeking) { + mStackScrollerContainer.animate().translationY(ty); + } + } else { + if (headerIsPeeking) { + mHeader.animate().translationY(0); + } + if (stackIsPeeking) { + mStackScrollerContainer.animate().translationY(0); + } + } } 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) { @@ -614,10 +650,16 @@ public class NotificationPanelView extends PanelView implements if (!mQsExpansionEnabled) { return false; } + final float ty = mHeader.getTranslationY(); boolean onHeader = x >= mHeader.getLeft() && x <= mHeader.getRight() - && y >= mHeader.getTop() && y <= mHeader.getBottom(); + && y >= mHeader.getTop() + ty && y <= mHeader.getBottom() + ty; if (mQsExpanded) { - return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0); + if (mQsShowingDetail && onHeader) { + // bring back the header, crudely + setQsHeaderPeeking(false); + mQsPanel.setExpanded(false); + } + return !mQsShowingDetail && onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0); } else { return onHeader; } @@ -781,4 +823,12 @@ public class NotificationPanelView extends PanelView implements public View getRightIcon() { return mKeyguardBottomArea.getCameraImageView(); } + + private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() { + @Override + public void onShowingDetail(boolean showingDetail) { + mQsShowingDetail = showingDetail; + updateQsState(); + } + }; } 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..dedfff0 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(); @@ -2342,16 +2348,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 +2426,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 +2865,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/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 { |