summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI')
-rw-r--r--packages/SystemUI/res/anim/recents_from_app_enter.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_from_app_exit.xml30
-rw-r--r--packages/SystemUI/res/anim/recents_from_launcher_enter.xml8
-rw-r--r--packages/SystemUI/res/anim/recents_from_launcher_exit.xml6
-rw-r--r--packages/SystemUI/res/anim/recents_from_unknown_enter.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_from_unknown_exit.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_to_launcher_enter.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_to_launcher_exit.xml28
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.pngbin219 -> 203 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.pngbin0 -> 169 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.pngbin193 -> 181 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.pngbin0 -> 163 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.pngbin242 -> 220 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.pngbin0 -> 186 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.pngbin1123 -> 265 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.pngbin0 -> 223 bytes
-rw-r--r--packages/SystemUI/res/drawable/ic_account_circle.xml6
-rw-r--r--packages/SystemUI/res/drawable/ic_notify_zen.xml28
-rw-r--r--packages/SystemUI/res/drawable/notification_scrim.xml22
-rw-r--r--packages/SystemUI/res/drawable/recents_button_bg.xml (renamed from packages/SystemUI/res/layout/recents_nav_bar_scrim.xml)9
-rw-r--r--packages/SystemUI/res/layout/keyguard_user_switcher.xml25
-rw-r--r--packages/SystemUI/res/layout/keyguard_user_switcher_item.xml40
-rw-r--r--packages/SystemUI/res/layout/recents.xml56
-rw-r--r--packages/SystemUI/res/layout/recents_empty.xml7
-rw-r--r--packages/SystemUI/res/layout/recents_fullscreen_overlay.xml27
-rw-r--r--packages/SystemUI/res/layout/recents_task_view.xml8
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml9
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml84
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml6
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_row.xml5
-rw-r--r--packages/SystemUI/res/layout/user_switcher_item.xml13
-rw-r--r--packages/SystemUI/res/values-af/strings.xml6
-rw-r--r--packages/SystemUI/res/values-am/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml6
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml6
-rw-r--r--packages/SystemUI/res/values-da/strings.xml6
-rw-r--r--packages/SystemUI/res/values-de/strings.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es/strings.xml6
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml6
-rw-r--r--packages/SystemUI/res/values-it/strings.xml6
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml6
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml14
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml8
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-rm/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml3
-rw-r--r--packages/SystemUI/res/values-th/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml6
-rw-r--r--packages/SystemUI/res/values/attrs.xml5
-rw-r--r--packages/SystemUI/res/values/colors.xml7
-rw-r--r--packages/SystemUI/res/values/config.xml17
-rw-r--r--packages/SystemUI/res/values/dimens.xml15
-rw-r--r--packages/SystemUI/res/values/strings.xml27
-rw-r--r--packages/SystemUI/res/values/styles.xml23
-rw-r--r--packages/SystemUI/src/com/android/systemui/DessertCaseView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/RecentsComponent.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Recents.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java249
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java358
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java182
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsService.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ReferenceCountedTrigger.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Utilities.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java257
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java228
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java109
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java170
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java778
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java415
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java374
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java110
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java143
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java260
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java219
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java209
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java18
153 files changed, 4734 insertions, 1694 deletions
diff --git a/packages/SystemUI/res/anim/recents_from_app_enter.xml b/packages/SystemUI/res/anim/recents_from_app_enter.xml
new file mode 100644
index 0000000..6abe8b3
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_from_app_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="0"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_from_app_exit.xml b/packages/SystemUI/res/anim/recents_from_app_exit.xml
new file mode 100644
index 0000000..1447a5a
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_from_app_exit.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="normal">
+
+ <!-- Animate the view out only after recents is visible -->
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="1"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index 4bd7e82..305a82f 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -19,10 +19,10 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
- android:zAdjustment="top">
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:zAdjustment="normal">
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/accelerate_cubic"
- android:duration="250"/>
+ android:interpolator="@android:interpolator/linear"
+ android:duration="200"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index becc9d0..863591f 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -19,10 +19,10 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
- android:zAdjustment="normal">
+ android:zAdjustment="top">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/decelerate_cubic"
- android:duration="250"/>
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:duration="200"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_from_unknown_enter.xml b/packages/SystemUI/res/anim/recents_from_unknown_enter.xml
new file mode 100644
index 0000000..f68a143
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_from_unknown_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="200"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_from_unknown_exit.xml b/packages/SystemUI/res/anim/recents_from_unknown_exit.xml
new file mode 100644
index 0000000..31cf26a
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_from_unknown_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="normal">
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="200"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
new file mode 100644
index 0000000..adcefe0
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="normal">
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/fast_out_linear_in"
+ android:duration="200"/>
+</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
new file mode 100644
index 0000000..863591f
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:duration="200"/>
+</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
index d4fdbf3..17100f7 100644
--- a/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.png b/packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.png
new file mode 100644
index 0000000..e969d4c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
index 9fc1a3b..b53bd8f 100644
--- a/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.png b/packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.png
new file mode 100644
index 0000000..657f710
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
index f38de93..09606f6 100644
--- a/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.png
new file mode 100644
index 0000000..a444c55
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
index 8194605..427cad9 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.png
new file mode 100644
index 0000000..29cf44b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_account_circle.xml b/packages/SystemUI/res/drawable/ic_account_circle.xml
index a7e8514..4a4c1c1 100644
--- a/packages/SystemUI/res/drawable/ic_account_circle.xml
+++ b/packages/SystemUI/res/drawable/ic_account_circle.xml
@@ -22,7 +22,13 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportWidth="24.0"
android:viewportHeight="24.0"/>
+ <group
+ android:scaleX="1.2"
+ android:scaleY="1.2"
+ android:pivotX="12.0"
+ android:pivotY="12.0">
<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.0zM12.0,5.0c1.7,0.0 3.0,1.3 3.0,3.0c0.0,1.7 -1.3,3.0 -3.0,3.0c-1.7,0.0 -3.0,-1.3 -3.0,-3.0C9.0,6.3 10.3,5.0 12.0,5.0zM12.0,19.2c-2.5,0.0 -4.7,-1.3 -6.0,-3.2c0.0,-2.0 4.0,-3.1 6.0,-3.1c2.0,0.0 6.0,1.1 6.0,3.1C16.7,17.9 14.5,19.2 12.0,19.2z"/>
+ </group>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notify_zen.xml b/packages/SystemUI/res/drawable/ic_notify_zen.xml
deleted file mode 100644
index c46455b..0000000
--- a/packages/SystemUI/res/drawable/ic_notify_zen.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android" >
- <size
- android:width="24dp"
- android:height="24dp"/>
-
- <viewport
- android:viewportWidth="48.0"
- android:viewportHeight="48.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M4.0,24.0c0.0,11.0 9.0,20.0 20.0,20.0s20.0,-9.0 20.0,-20.0S35.0,4.0 24.0,4.0S4.0,13.0 4.0,24.0zM36.6,33.8L14.2,11.4C16.9,9.3 20.3,8.0 24.0,8.0c8.8,0.0 16.0,7.2 16.0,16.0C40.0,27.7 38.7,31.1 36.6,33.8zM8.0,24.0c0.0,-3.7 1.3,-7.1 3.4,-9.8L33.8,36.6C31.1,38.7 27.7,40.0 24.0,40.0C15.2,40.0 8.0,32.8 8.0,24.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/notification_scrim.xml b/packages/SystemUI/res/drawable/notification_scrim.xml
new file mode 100644
index 0000000..ff7e31f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_scrim.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#34000000" />
+ <corners android:radius="@*android:dimen/notification_material_rounded_rect_radius" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml b/packages/SystemUI/res/drawable/recents_button_bg.xml
index 4245d49..a4cb088 100644
--- a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
+++ b/packages/SystemUI/res/drawable/recents_button_bg.xml
@@ -14,10 +14,5 @@
limitations under the License.
-->
-<ImageView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|bottom"
- android:scaleType="fitXY"
- android:src="@drawable/recents_lower_gradient" /> \ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
new file mode 100644
index 0000000..5648065
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyguard_user_switcher"
+ android:orientation="vertical"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="end"
+ android:visibility="gone"
+ android:paddingTop="4dp">
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
new file mode 100644
index 0000000..691a80e
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:layout_marginEnd="8dp"
+ android:gravity="center_vertical"
+ android:clickable="true"
+ android:background="@drawable/ripple_drawable">
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="16dp"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName"
+ />
+ <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/picture"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:contentDescription="@null"
+ sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
+ sysui:activeFrameColor="@color/current_user_border_color" />
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
new file mode 100644
index 0000000..47740ee
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- Status Bar Scrim View -->
+ <ImageView
+ android:id="@+id/status_bar_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|top"
+ android:scaleType="fitXY"
+ android:src="@drawable/recents_status_gradient" />
+
+ <!-- Recents View -->
+ <com.android.systemui.recents.views.RecentsView
+ android:id="@+id/recents_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true" />
+
+ <!-- Empty View -->
+ <ViewStub android:id="@+id/empty_view_stub"
+ android:layout="@layout/recents_empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <!-- Fullscreen Transition View -->
+ <ViewStub android:id="@+id/fullscreen_overlay_stub"
+ android:layout="@layout/recents_fullscreen_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <!-- Nav Bar Scrim View -->
+ <ImageView
+ android:id="@+id/nav_bar_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:scaleType="fitXY"
+ android:src="@drawable/recents_lower_gradient" />
+</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index ac6450b..21d1711 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -16,12 +16,13 @@
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
android:textColor="#ffffffff"
- android:textStyle="italic"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif-light"
+ android:background="#80000000"
android:visibility="gone" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_fullscreen_overlay.xml b/packages/SystemUI/res/layout/recents_fullscreen_overlay.xml
new file mode 100644
index 0000000..1d021f9
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_fullscreen_overlay.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.android.systemui.recents.views.FullscreenTransitionOverlayView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone">
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitXY" />
+</com.android.systemui.recents.views.FullscreenTransitionOverlayView> \ 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 85d2f16..1bab67a 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -32,8 +32,10 @@
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_marginStart="16dp"
- android:layout_gravity="center_vertical|start" />
+ android:layout_marginStart="8dp"
+ android:layout_gravity="center_vertical|start"
+ android:padding="8dp"
+ android:background="@drawable/recents_button_bg" />
<TextView
android:id="@+id/activity_description"
android:layout_width="match_parent"
@@ -56,6 +58,8 @@
android:layout_marginEnd="4dp"
android:layout_gravity="center_vertical|end"
android:padding="18dp"
+ android:background="@drawable/recents_button_bg"
+ android:visibility="invisible"
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/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index cde83bf..b54ba1a 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -24,6 +24,7 @@
android:id="@+id/notification_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@android:color/transparent"
>
<include
@@ -91,6 +92,14 @@
<include layout="@layout/status_bar_expanded_header" />
+ <ViewStub
+ android:id="@+id/keyguard_user_switcher"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
+ android:layout_gravity="end"
+ android:layout="@layout/keyguard_user_switcher" />
+
<include
layout="@layout/keyguard_bottom_area"
android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 4028ec3..2e4c0ef 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -35,12 +35,66 @@
android:background="@drawable/notification_header_bg"
android:clickable="true"
/>
+
+ <View android:id="@+id/header_spacer"
+ android:layout_height="8dp"
+ android:layout_width="0dp" />
+
+ <TextView
+ android:id="@+id/header_emergency_calls_only"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_below="@id/header_spacer"
+ android:paddingTop="12dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:visibility="gone"
+ android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
+ android:text="@*android:string/emergency_calls_only" />
+
+ <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
+ android:layout_width="40dp"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:layout_alignParentEnd="true"
+ android:background="@null"
+ android:scaleType="centerInside"
+ android:padding="8dp" />
+
+ <ImageButton android:id="@+id/settings_button"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:layout_toStartOf="@id/multi_user_switch"
+ android:layout_width="48dp"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:layout_marginStart="8dp"
+ android:src="@drawable/ic_settings_24dp"
+ android:contentDescription="@string/accessibility_desc_quick_settings"/>
+
+ <FrameLayout android:id="@+id/system_icons_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:layout_toStartOf="@id/multi_user_switch"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_marginStart="16dp"
+ android:paddingEnd="2dp" />
+
+ <TextView
+ android:id="@+id/header_charging_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/system_icons_container"
+ android:layout_below="@id/header_spacer"
+ android:paddingTop="12dp"
+ android:paddingEnd="16dp"
+ android:paddingStart="4dp"
+ style="@style/TextAppearance.StatusBar.Expanded.ChargingInfo"/>
+
<RelativeLayout
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
- android:paddingTop="16dp"
+ android:layout_below="@id/header_emergency_calls_only"
+ android:paddingTop="8dp"
android:paddingBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
@@ -64,32 +118,6 @@
android:layout_below="@id/clock"
/>
</RelativeLayout>
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
- android:layout_width="40dp"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_alignParentEnd="true"
- android:background="@null"
- android:scaleType="centerInside"
- android:padding="8dp"
- />
-
- <ImageButton android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_toStartOf="@id/multi_user_switch"
- android:layout_width="48dp"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_marginStart="8dp"
- android:src="@drawable/ic_settings_24dp"
- android:contentDescription="@string/accessibility_desc_quick_settings"/>
-
- <FrameLayout android:id="@+id/system_icons_container"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_toStartOf="@id/multi_user_switch"
- android:layout_marginEnd="2dp"
- />
-
<com.android.keyguard.CarrierText
android:id="@+id/keyguard_carrier_text"
android:layout_width="match_parent"
@@ -106,6 +134,8 @@
layout="@layout/quick_settings_brightness_dialog"
android:id="@+id/brightness_container"
android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
/>
<TextView
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index c442f79..f0f50e1 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -49,4 +49,10 @@
android:layout_width="120dp"
android:layout_height="wrap_content"
/>
+
+ <com.android.systemui.statusbar.NotificationScrimView
+ android:id="@+id/scrim_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 5fabd3e..7663d54 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -48,4 +48,9 @@
android:padding="2dp"
/>
+ <com.android.systemui.statusbar.NotificationScrimView
+ android:id="@+id/scrim_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.ExpandableNotificationRow>
diff --git a/packages/SystemUI/res/layout/user_switcher_item.xml b/packages/SystemUI/res/layout/user_switcher_item.xml
index 43a85e7..8df2f5a 100644
--- a/packages/SystemUI/res/layout/user_switcher_item.xml
+++ b/packages/SystemUI/res/layout/user_switcher_item.xml
@@ -21,10 +21,12 @@
android:layout_width="match_parent"
android:layout_height="64dp"
android:orientation="horizontal"
+ android:gravity="center_vertical"
tools:context=".settings.UserSwitcherDialog">
<ImageView
- android:layout_width="64dp"
- android:layout_height="match_parent"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginStart="4dp"
android:id="@+id/user_picture"
tools:src="@drawable/dessert_zombiegingerbread"/>
<TextView
@@ -37,4 +39,11 @@
android:gravity="center_vertical"
tools:text="Hiroshi Lockheimer"
/>
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginEnd="4dp"
+ android:src="@*android:drawable/ic_menu_delete"
+ android:id="@+id/user_delete"
+ android:background="?android:attr/selectableItemBackground"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 3bf38cb..d9c4c0c 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Geen onlangse programme nie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Gelaai"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laai tans"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot vol"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Laai nie"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk word\ndalk gemonitor"</string>
<string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Sleep links vir kamera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Totdat jy dit afskakel"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gas"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ gas"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Een minuut lank"</item>
<item quantity="other" msgid="6924190729213550991">"%d minute lank"</item>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index dea589d..f84f028 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"ምንም የቅርብ ጊዜ መተግበሪያዎች የሉም"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"ኃይል በመሙላት ላይ"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> እስኪሞላ ድረስ"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"ባትሪ እየሞላ አይደለም"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"አውታረ መረብ\nክትትል ሊደረግበት ይችላል"</string>
<string name="description_target_search" msgid="3091587249776033139">"ፍለጋ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"ለካሜራ ወደግራ ያንሸራትቱ"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ሃይል በመሙላት ላይ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> እስከሚሞላ ድረስ)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"እንግዳ"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ እንግዳ"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item>
<item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f369d12..44e6ffe 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"ليست هناك تطبيقات حديثة"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"تم الشحن"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"جارٍ الشحن"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> حتى الاكتمال"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"لا يتم الشحن"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"قد تكون الشبكة\nخاضعة للرقابة"</string>
<string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
<string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"مرر سريعًا إلى اليمين لفتح الكاميرا"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"لحين تعطيل هذا الإعداد"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"جارٍ الشحن (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"المدعو"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ مدعو"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"لمدة دقيقة واحدة"</item>
<item quantity="other" msgid="6924190729213550991">"‏لمدة %d من الدقائق"</item>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2c3837a..71fb8b8 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Няма скорошни приложения"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарежда се"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до пълно зареждане"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Не се зарежда"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежата може\nда се наблюдава"</string>
<string name="description_target_search" msgid="3091587249776033139">"Търсене"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Прекарайте пръст наляво, за да включите камерата"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Докато не изключите това"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Гост"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ гост"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"За една минута"</item>
<item quantity="other" msgid="6924190729213550991">"За %d минути"</item>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index c0b62d5..becd731 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"No hi ha aplicacions recents."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la càrrega"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"No s\'està carregant"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string>
<string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Fes lliscar el dit cap a l\'esquerra per obrir la càmera."</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Fins que no ho desactivis"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la càrrega)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Convidat"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Convidat"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durant un minut"</item>
<item quantity="other" msgid="6924190729213550991">"Durant %d minuts"</item>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f7e3b14..97efe46 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Žádné nedávné aplikace"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíjení"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do plného nabití"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nenabíjí se"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Síť může být\nmonitorována"</string>
<string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otevřete přejetím prstem vlevo."</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokud tuto funkci nevypnete"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Host"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Přidat hosta"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Na jednu minutu"</item>
<item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 05b72ce..a86157d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Der er ingen seneste apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Oplader"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> indtil fuld opladet"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Oplader ikke"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netværket kan\nvære overvåget"</string>
<string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Stryg til venstre for at åbne kameraet"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Indtil du slår denne indstilling fra"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladning (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gæst"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Gæst"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I ét minut"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6e6280c..40e623a 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Keine neuen Apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Wird aufgeladen"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Voll in <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Wird nicht aufgeladen"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netzwerk wird\neventuell überwacht."</string>
<string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Zum Öffnen der Kamera nach links wischen"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Bis zur Deaktivierung"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Wird aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gast"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Gast"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Für eine Minute"</item>
<item quantity="other" msgid="6924190729213550991">"Für %d Minuten"</item>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a99e91e..5e5aa6a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Καμία πρόσφατη εφαρμογή"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Φόρτιση"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> για πλήρη φόρτιση"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Δεν φορτίζει"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Το δίκτυο μπορεί\nνα παρακολουθείται"</string>
<string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Σύρετε αριστερά για τη φωτογραφική μηχανή"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Μέχρι να το απενεργοποιήσετε"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Επισκέπτης"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Επισκέπτης"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item>
<item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 0938b28..82ee78c 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> until full"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Not charging"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Guest"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Guest"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"For one minute"</item>
<item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 0938b28..82ee78c 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> until full"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Not charging"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Guest"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Guest"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"For one minute"</item>
<item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index cfa809c..4145a29 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"No se está cargando"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Es posible que la red\nesté supervisada."</string>
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Desliza hacia la izquierda para acceder a la cámara."</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hasta que lo desactives"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (faltan <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Invitado"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Agregar invitado"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 242a7d0..b1dc302 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"No se está cargando"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La red se\npuede supervisar"</string>
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Desliza el dedo hacia la izquierda para acceder a la cámara"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hasta apagar el dispositivo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hasta completar)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Invitado"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Añadir invitado"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index bc9a6e6..8aab7f3 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Hiljutisi rakendusi pole"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laadimine"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Täislaadimiseks kulub <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Ei laadi"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Võrku võidakse\njälgida"</string>
<string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -237,6 +241,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Kaamera kasutamiseks pühkige vasakule"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kuni lülitate selle välja"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Külaline"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ külaline"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Üheks minutiks"</item>
<item quantity="other" msgid="6924190729213550991">"%d minutiks"</item>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 8495828..3595b6a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"هیچ برنامه جدیدی موجود نیست"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"شارژ کامل شد"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"در حال شارژ شدن"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> مانده تا شارژ کامل شود"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"شارژ نمی‌شود"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ممکن است شبکه\nتحت نظارت باشد"</string>
<string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
<string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"برای دوربین انگشت را تند به سمت راست بکشید"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"تا وقتی آن را خاموش کنید"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"در حال شارژ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"مهمان"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ مهمان"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"برای یک دقیقه"</item>
<item quantity="other" msgid="6924190729213550991">"‏برای %d دقیقه"</item>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c73caf4..019fea0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Ei viimeaikaisia sovelluksia"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ladataan"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> kunnes täynnä"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Ei lataudu"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Verkkoa saatetaan\nvalvoa"</string>
<string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Avaa kamera pyyhkäisemällä oikealle"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Vieras"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Vieras"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Minuutiksi"</item>
<item quantity="other" msgid="6924190729213550991">"%d minuutiksi"</item>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 179b54d..03ac011 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charge en cours..."</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargée dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"N\'est pas en charge"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
<string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Balayez l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours... (chargée à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Invité"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Ajouter un invité"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
<item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 3334125..d11c9be 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"En charge"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargé dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"N\'est pas en charge"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
<string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Balayer l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Invité"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Ajouter un invité"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
<item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index fe28ec5..c33c1d5 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"कोई हाल ही का ऐप्स नहीं"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हो रही है"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"पूर्ण होने में <xliff:g id="CHARGING_TIME">%s</xliff:g> शेष"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"चार्ज नहीं हो रही है"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string>
<string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्‍लाइड करें."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"कैमरे के लिए बाएं स्वाइप करें"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"जब तक आप इसे बंद नहीं कर देते"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हो रहा है (पूर्ण होने में <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> शेष)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"अतिथि"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ अतिथि"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"एक मिनट के लिए"</item>
<item quantity="other" msgid="6924190729213550991">"%d मिनट के लिए"</item>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4ee3e32..024be82 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nema nedavnih aplikacija"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napunjenosti"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Ne puni se"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se\nmožda prati"</string>
<string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Prijeđite prstom ulijevo za fotoaparat"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dok ne isključite"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gost"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ gost"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Jednu minutu"</item>
<item quantity="other" msgid="6924190729213550991">"%d min"</item>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 95af816..deeb7f4 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nincsenek nemrég használt alkalmazások"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Töltés"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> a teljes töltöttségig"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nem töltődik"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Lehet, hogy a\nhálózat felügyelt"</string>
<string name="description_target_search" msgid="3091587249776033139">"Keresés"</string>
<string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"A fényképezőgép eléréséhez csúsztassa ujját balra"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Amíg ki nem kapcsolja ezt"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Vendég"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ vendég"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Egy percen át"</item>
<item quantity="other" msgid="6924190729213550991">"%d percen át"</item>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 637d85f..4424338 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Նոր հավելվածներ չկան"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Լիցքավորվում է"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Լրիվ լիցքավորմանը մնաց <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Չի լիցքավորվում"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ցանցը կարող է\nվերահսկվել"</string>
<string name="description_target_search" msgid="3091587249776033139">"Որոնել"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Սահեցրեք վերև <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Խցիկի համար սահեցրեք ձախ"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> մինչև լրիվ լիցքավորումը)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Հյուր"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Հյուր"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item>
<item quantity="other" msgid="6924190729213550991">"%d րոպե"</item>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3cd82a7..5dbd490 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Tidak ada aplikasi terkini"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengisi daya"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> sampai penuh"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Tidak mengisi daya"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Jaringan bisa\ndiawasi"</string>
<string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Gesek ke kiri untuk kamera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hingga Anda menonaktifkan ini"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Tamu"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Tamu"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Selama satu menit"</item>
<item quantity="other" msgid="6924190729213550991">"Selama %d menit"</item>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b62d75a..ddb7669 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nessuna app recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"In carica"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> al termine della carica"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Non in carica"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La rete potrebbe\nessere monitorata"</string>
<string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Scorri verso sinistra per accedere alla fotocamera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Fino alla disattivazione"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Ospite"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ ospite"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Per un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Per %d minuti"</item>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index e1e7e00..5b68451 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"אין אפליקציות אחרונות"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"טעון"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"טוען"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> עד למילוי"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"לא בטעינה"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ייתכן שהרשת\nמנוטרת"</string>
<string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
<string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"החלק שמאלה להפעלת המצלמה"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"עד שתכבה"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"טוען (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"אורח"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ אורח"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"למשך דקה אחת"</item>
<item quantity="other" msgid="6924190729213550991">"‏למשך %d דקות"</item>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b6359e9..6ebd5c7 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"最近使ったアプリはありません"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電しています"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"充電完了まで<xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"充電していません"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ネットワークが監視される\n場合があります"</string>
<string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
<string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"左にスワイプしてカメラを表示"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中(フルになるまで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"ゲスト"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ ゲスト"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1分"</item>
<item quantity="other" msgid="6924190729213550991">"%d分"</item>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 973cd63..a35c821 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"ბოლო აპები არ არის"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"მიმდინარეობს დატენვა"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> სრულად დატენვამდე"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"არ იტენება"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"შესაძლოა ქსელზე\nმონიტორინგი ხორციელდებოდეს"</string>
<string name="description_target_search" msgid="3091587249776033139">"ძიება"</string>
<string name="description_direction_up" msgid="7169032478259485180">"გაასრიალეთ ზემოთ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"კამერისთვის მარცხენა შენაცვლება"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>-ის შეცვლა დასრულებამდე)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"სტუმარი"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ სტუმარი"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item>
<item quantity="other" msgid="6924190729213550991">"%d წუთით"</item>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 4a4a2bddf..29c5e5c 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -70,7 +70,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថត​អេក្រង់​កំពុង​ត្រូវ​បាន​រក្សាទុក។"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
<string name="screenshot_failed_text" msgid="8134011269572415402">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់​។ ឧបករណ៍​ផ្ទុក​អាច​កំពុង​ប្រើ​​។"</string>
@@ -147,7 +147,7 @@
<string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាត​ការ​ជូន​ដំណឹង។"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"បាន​បើក GPS ។"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល​​ GPS ។"</string>
- <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ​"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ"</string>
<string name="accessibility_ringer_vibrate" msgid="666585363364155055">"កម្មវិធី​រោទ៍​ញ័រ។"</string>
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធី​រោទ៍​ស្ងាត់។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
@@ -197,7 +197,7 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"បញ្ឈរ"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"ទេសភាព"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"វិធីសាស្ត្រ​បញ្ចូល"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង​"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"ទីតាំង​បាន​បិទ"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"ឧបករណ៍​មេឌៀ"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
@@ -221,7 +221,11 @@
<string name="recents_empty_message" msgid="7883614615463619450">"មិនមាន​​កម្មវិធី​ថ្មីៗ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មាន​កម្មវិធី"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
- <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ​"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បាន​បញ្ចូល​ថ្ម"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុង​បញ្ចូល​ថ្ម"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> រហូត​ដល់ពេញ"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"មិន​កំពុង​បញ្ចូល​ថ្ម"</string>
+ <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ"</string>
<string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
<string name="description_direction_up" msgid="7169032478259485180">"រុញ​ឡើង​លើ​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
<string name="description_direction_left" msgid="7207478719805562165">"រុញ​ទៅ​ឆ្វេង​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"អូស​ទៅ​ឆ្វេង​​ដើម្បី​ប្រើ​​ម៉ាស៊ីន​ថត"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"រហូត​ដល់ពេល​​អ្នក​បិទ​វា"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"កំពុង​បញ្ចូល​ថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទើប​ពេញ)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"ភ្ញៀវ"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ ភ្ញៀវ"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"សម្រាប់​មួយ​នាទី"</item>
<item quantity="other" msgid="6924190729213550991">"សម្រាប់ %d នាទី"</item>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 5435a7b..0ffb4b8 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"최근에 사용한 앱 없음"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"충전 중"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"완충까지 <xliff:g id="CHARGING_TIME">%s</xliff:g> 남음"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"충전 안함"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"네트워크가\n모니터링될 수 있음"</string>
<string name="description_target_search" msgid="3091587249776033139">"검색"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"카메라를 사용하려면 왼쪽으로 스와이프하세요."</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"이 기능을 사용 중지할 때까지"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"손님"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"새 손님 추가"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1분 동안"</item>
<item quantity="other" msgid="6924190729213550991">"%d분 동안"</item>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 604714b..b765fb7 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"ບໍ່​ມີ​ແອັບຯ​ທີ່​ຫາ​ກໍ​ໃຊ້"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"ກຳລັງສາກໄຟ"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ເຄືອຄ່າຍອາດ\nຖືກຕິດຕາມ"</string>
<string name="description_target_search" msgid="3091587249776033139">"ຊອກຫາ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ເລື່ອນຂຶ້ນເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -237,8 +241,10 @@
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນ​ຂຶ້ນ​ເພື່ອ​ປົດ​ລັອກ"</string>
<string name="phone_hint" msgid="3101468054914424646">"ປັດ​ຂວາ​ເພື່ອ​ໃຊ້​ໂທ​ລະ​ສັບ"</string>
<string name="camera_hint" msgid="5241441720959174226">"ປັດ​ຊ້າຍ​ເພື່ອ​ໃຊ້​ກ້ອງ"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ​"</string>
+ <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳ​ລັງ​ສາກ​ໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າ​ຈ​ະ​ເຕັມ)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"ແຂກ"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ ແຂກ"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ເປັນ​ເວລາ​ນຶ່ງ​ນາ​ທີ"</item>
<item quantity="other" msgid="6924190729213550991">"ເປັນ​ເວລາ %d ນາ​ທີ"</item>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6563d45..cc1ac06 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nėra naujausių programų"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kraunamas"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> iki visiško įkrovimo"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Neįkraunamas"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tinklas gali\nbūti stebimas"</string>
<string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Perbraukite į kairę, kad būtų įjungtas fotoaparatas"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kol išjungsite"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Svečias"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Svečias"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 min."</item>
<item quantity="other" msgid="6924190729213550991">"%d min."</item>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4c4031e..4e3a676 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nav nesen izmantotu lietotņu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Notiek uzlāde"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> līdz pilnam akumulatoram"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nenotiek uzlāde"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tīkls var\ntikt uzraudzīts"</string>
<string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Lai lietotu kameru, velciet pa kreisi."</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Līdz brīdim, kad izslēgsiet"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Viesis"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+Viesis"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Vienu minūti"</item>
<item quantity="other" msgid="6924190729213550991">"%d min"</item>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 2bb37f6..a2568d1 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Сүүлд ашигласан апп байхгүй"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Цэнэглэж байна"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"дүүргэхэд <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Цэнэглэхгүй байна"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Сүлжээ хянагдаж\nбайж болзошгүй"</string>
<string name="description_target_search" msgid="3091587249776033139">"Хайх"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-г гулсуулах."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Камер гаргахын тулд зүүн шударна уу"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Зочин"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Зочин"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
<item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 7f46211..2fed4bd 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Tiada apl terbaharu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengecas"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Lagi <xliff:g id="CHARGING_TIME">%s</xliff:g> untuk penuh"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Tidak mengecas"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rangkaian mungkin\nboleh dipantau"</string>
<string name="description_target_search" msgid="3091587249776033139">"Carian"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Leret ke kiri untuk kamera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Tetamu"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Tetamu"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item>
<item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 91b14da..cecbe7a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Ingen nylige apper"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Lader"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Fulladet om <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Lader ikke"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nettverket kan\nvære overvåket"</string>
<string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Sveip mot venstre for å åpne kameraet"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Inntil du slår av funksjonen"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gjest"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Gjest"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I ett minutt"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index fd7337e..b6ffecf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Geen recente apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Opladen"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot volledig opgeladen"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Wordt niet opgeladen"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk kan\nworden gecontroleerd"</string>
<string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Veeg naar links voor camera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Totdat u dit uitschakelt"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gast"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Gast"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Eén minuut"</item>
<item quantity="other" msgid="6924190729213550991">"%d minuten"</item>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 4d582e2..05dcd82 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Brak ostatnio uruchomionych aplikacji"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ładuje się"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do pełnego naładowania"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nie ładuje"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieć może być\nmonitorowana"</string>
<string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Przesuń w lewo, by przełączyć się na aparat"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dopóki nie wyłączysz"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ładuje się (pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gość"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Dodaj gościa"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Przez minutę"</item>
<item quantity="other" msgid="6924190729213550991">"Przez %d min"</item>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d576ebb..657e03f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nenhuma aplicação recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"A carregar"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até ficar completa"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Não está a carregar"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode ser\nmonitorizada"</string>
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Deslize rapidamente para a esquerda para aceder à câmara"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Até que o utilizador desative"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Convidado"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante um minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index caffae9..bcf7431 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nenhum app recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do aplicativo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Carregando"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até concluir"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Não está carregando"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode estar\nsob monitoração"</string>
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Deslize para a esquerda para usar a câmera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ convidado"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 0a5a698..689aaff 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -413,6 +413,14 @@
<skip />
<!-- no translation found for recents_search_bar_label (8074997400187836677) -->
<skip />
+ <!-- no translation found for expanded_header_battery_charged (5945855970267657951) -->
+ <skip />
+ <!-- no translation found for expanded_header_battery_charging (205623198487189724) -->
+ <skip />
+ <!-- no translation found for expanded_header_battery_charging_with_time (457559884275395376) -->
+ <skip />
+ <!-- no translation found for expanded_header_battery_not_charging (4798147152367049732) -->
+ <skip />
<!-- no translation found for ssl_ca_cert_warning (9005954106902053641) -->
<skip />
<!-- no translation found for description_target_search (3091587249776033139) -->
@@ -443,6 +451,10 @@
<skip />
<!-- no translation found for keyguard_indication_charging_time (1757251776872835768) -->
<skip />
+ <!-- no translation found for guest_nickname (8059989128963789678) -->
+ <skip />
+ <!-- no translation found for guest_new_guest (4259024453643879653) -->
+ <skip />
<!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
<!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
<!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 8d5fddc..8ec3621 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Nicio aplicație recentă"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Se încarcă"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> până la încărcare completă"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nu se încarcă"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
<string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Glisați la stânga pentru a accesa camera foto"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Invitat"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Invitat"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item>
<item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e940893..8c59e05 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Ничего не найдено."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядка батареи"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до полной зарядки"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Не заряжается"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Действия в сети\nмогут отслеживаться"</string>
<string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Чтобы включить камеру, пролистните влево"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Пока я не отключу"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядка батареи (осталось <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Гость"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Добавить гостя"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 мин."</item>
<item quantity="other" msgid="6924190729213550991">"%d мин."</item>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index e917350..9456ebd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Žiadne nedávne aplikácie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíja sa"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Úplné nabitie o <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nenabíja sa"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieť môže byť\nmonitorovaná"</string>
<string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otvoríte prejdením prstom doľava"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Hosť"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Pridať hosťa"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item>
<item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 0b117a1..10ba09f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Ni nedavnih aplikacij"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Polnjenje"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napolnjenosti"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Se ne polni"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Omrežje je\nlahko spremljano"</string>
<string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Povlecite v levo za fotoaparat"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokler tega ne izklopite"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gost"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Dodajanje gosta"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Za eno minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Za %d min"</item>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 4a49a7b..d9c1cfc 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Нема недавних апликација"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> док се не напуни"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Не пуни се"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string>
<string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Превуците улево за камеру"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Док не искључите"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Пуњење (пун је за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Гост"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Гост"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Један минут"</item>
<item quantity="other" msgid="6924190729213550991">"%d мин"</item>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d2024c4..b802a48 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Inga aktiva appar"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laddar"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tills batteriet är fulladdat"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Laddar inte"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nätverket kan\nvara övervakat"</string>
<string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Dra åt vänster om du vill visa kameran"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Tills du inaktiverar detta"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laddar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tills batteriet är fulladdat)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Gäst"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Lägg till gäst"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I en minut"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minuter"</item>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d42077f..1cd1752 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -219,6 +219,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Hakuna programu za karibuni"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Inachaji"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> hadi ijae"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Haichaji"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Huenda mtandao\nunafuatiliwa"</string>
<string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
@@ -237,6 +241,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Telezesha kidole kushoto ili ufikie kamera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Inachaji ( <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hadi ijae)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Aliyealikwa"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Aliyealikwa"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item>
<item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 47581a9..9f4c364 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -32,4 +32,7 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
+
+ <!-- Set to true to enable the user switcher on the keyguard. -->
+ <bool name="config_keyguardUserSwitcher">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index ee4ba0e..791d5f6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"ไม่มีแอปล่าสุด"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"กำลังชาร์จ"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"อีก <xliff:g id="CHARGING_TIME">%s</xliff:g> จึงจะเต็ม"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"ไม่ได้ชาร์จ"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"เครือข่ายอาจ\nถูกตรวจสอบ"</string>
<string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
<string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"กวาดไปทางซ้ายเพื่อใช้กล้องถ่ายรูป"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> เต็ม)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"ผู้เข้าร่วม"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ ผู้เข้าร่วม"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 นาที"</item>
<item quantity="other" msgid="6924190729213550991">"%d นาที"</item>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 42e168e..42f262b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Walang kamakailang mga app"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nagcha-charge"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> hanggang mapuno"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Hindi nagcha-charge"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Maaaring\nsinusubaybayan ang network"</string>
<string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Mag-swipe pakaliwa para sa camera"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nagtsa-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Bisita"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Bisita"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2967731..fbd8549f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Yakın zamanda kullanılan uygulama yok"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Şarj oluyor"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Tam şarj olmasına <xliff:g id="CHARGING_TIME">%s</xliff:g> kaldı"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Şarj olmuyor"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ağ izleniyor\nolabilir"</string>
<string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Kamera için sola kaydırın"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Şarj oluyor (tamamen dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Misafir"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Misafir"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item>
<item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 43d4146..12dd57e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Немає останніх додатків"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Заряджається"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"До повного зарядження <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Не заряджається"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мережа може\nвідстежуватися"</string>
<string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Проведіть пальцем ліворуч, щоб скористатися камерою"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Доки ви не вимкнете"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного зарядження)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Гість"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"Додати гостя"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Протягом хвилини"</item>
<item quantity="other" msgid="6924190729213550991">"Протягом %d хв"</item>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eede966..5c24e8b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Không có ứng dụng nào gần đây"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Đang sạc"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> cho đến khi đầy"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Hiện không sạc"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mạng có thể\nđược giám sát"</string>
<string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Vuốt sang trái để mở máy ảnh"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Cho đến khi bạn tắt tính năng này"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho đến khi đầy)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Khách"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Khách"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Trong một phút"</item>
<item quantity="other" msgid="6924190729213550991">"Trong %d phút"</item>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 61d59ab..f975252 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"最近没有用过任何应用"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"正在充电"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"还需<xliff:g id="CHARGING_TIME">%s</xliff:g>才能充满"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"未在充电"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"网络可能会\n受到监控"</string>
<string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"向左滑动可打开相机"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"正在充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>才能充满)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"访客"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"添加新访客"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1分钟"</item>
<item quantity="other" msgid="6924190729213550991">"%d分钟"</item>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 8843363..4b5cf08 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後完成充電"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"非充電中"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網絡可能會\n受到監控"</string>
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"向左快速滑動即可使用相機功能"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"訪客"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"新增訪客"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
<item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a6efe21..a780ad1 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -223,6 +223,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後充飽"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"未充電"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網路可能\n受到監控"</string>
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
@@ -241,6 +245,8 @@
<string name="camera_hint" msgid="5241441720959174226">"向左滑動可使用相機功能"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"訪客"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"新增訪客"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
<item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index bfeb47a..8458ca8 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -221,6 +221,10 @@
<string name="recents_empty_message" msgid="7883614615463619450">"Azikho izinhlelo zokusebenza zakamuva"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
+ <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kushajiwe"</string>
+ <string name="expanded_header_battery_charging" msgid="205623198487189724">"Iyashaja"</string>
+ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ize igcwale"</string>
+ <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Ayishaji"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Kungenzeka inethiwekhi\niqashiwe"</string>
<string name="description_target_search" msgid="3091587249776033139">"Sesha"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
@@ -239,6 +243,8 @@
<string name="camera_hint" msgid="5241441720959174226">"Swayiphela ngakwesokunxele ukuze uthole ikhamela"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Uze uvale lokhu"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
+ <string name="guest_nickname" msgid="8059989128963789678">"Isihambeli"</string>
+ <string name="guest_new_guest" msgid="4259024453643879653">"+ Isihambeli"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Iminithi elilodwa"</item>
<item quantity="other" msgid="6924190729213550991">"Amaminithi angu-%d"</item>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index c453618..8473d96 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -54,5 +54,10 @@
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
+ <declare-styleable name="UserAvatarView">
+ <attr name="frameWidth" format="dimension" />
+ <attr name="activeFrameColor" format="color" />
+ <attr name="frameColor" />
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8c1a9c7..4e38da6 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -46,9 +46,7 @@
<color name="keyguard_overflow_content_color">#ff686868</color>
<!-- The default recents task bar background color. -->
- <color name="recents_task_bar_default_background_color">#e6444444</color>
- <!-- The default recents task bar text color. -->
- <color name="recents_task_bar_default_text_color">#ffeeeeee</color>
+ <color name="recents_task_bar_default_background_color">#ffe6e6e6</color>
<!-- 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. -->
@@ -62,6 +60,9 @@
<color name="keyguard_affordance">#ffffffff</color>
+ <!-- The color of the circle around the primary user in the user switcher -->
+ <color name="current_user_border_color">@color/primary_color</color>
+
<!-- Our material color palette (deep teal) -->
<color name="primary_color">#ff7fcac3</color>
<color name="background_color_1">#ff384248</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1ef5bcd..c1f971a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -108,17 +108,25 @@
<!-- milliseconds before the heads up notification accepts touches. -->
<integer name="heads_up_sensitivity_delay">700</integer>
+ <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
+ <integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
<!-- The min animation duration for animating views that are currently visible. -->
- <integer name="recents_filter_animate_current_views_min_duration">175</integer>
+ <integer name="recents_filter_animate_current_views_duration">250</integer>
<!-- The min animation duration for animating views that are newly visible. -->
- <integer name="recents_filter_animate_new_views_min_duration">125</integer>
+ <integer name="recents_filter_animate_new_views_duration">250</integer>
<!-- The min animation duration for animating the task bar in. -->
- <integer name="recents_animate_task_bar_enter_duration">250</integer>
+ <integer name="recents_animate_task_bar_enter_duration">275</integer>
<!-- The animation delay for animating the first task in. This should roughly be the animation
duration of the transition in to recents. -->
<integer name="recents_animate_task_bar_enter_delay">225</integer>
<!-- The min animation duration for animating the task bar out. -->
+ <integer name="recents_animate_task_exit_to_home_duration">225</integer>
+ <!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_bar_exit_duration">125</integer>
+ <!-- The min animation duration for animating the task in when transitioning from home. -->
+ <integer name="recents_animate_task_enter_from_home_duration">275</integer>
+ <!-- The animation stagger to apply to each task animation when transitioning from home. -->
+ <integer name="recents_animate_task_enter_from_home_delay">10</integer>
<!-- The min animation duration for animating the nav bar scrim in. -->
<integer name="recents_nav_bar_scrim_enter_duration">400</integer>
<!-- The animation duration for animating the removal of a task view. -->
@@ -146,5 +154,8 @@
Notification.tickerText across the status bar for what seems like an
eternity. -->
<bool name="enable_ticker">false</bool>
+
+ <!-- Set to true to enable the user switcher on the keyguard. -->
+ <bool name="config_keyguardUserSwitcher">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4a15363..36c1994 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">32dp</dimen>
+ <dimen name="recents_task_view_application_icon_size">48dp</dimen>
<!-- The size of the activity icon in the recents task view. -->
<dimen name="recents_task_view_activity_icon_size">60dp</dimen>
@@ -235,9 +235,6 @@
<!-- 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>
@@ -323,6 +320,9 @@
device. -->
<dimen name="unlock_move_distance">75dp</dimen>
+ <!-- Distance after which the scrim starts fading in when dragging down the quick settings -->
+ <dimen name="notification_scrim_wait_distance">100dp</dimen>
+
<!-- Move distance for the unlock hint animation on the lockscreen -->
<dimen name="hint_move_distance">75dp</dimen>
@@ -335,4 +335,11 @@
<!-- end margin for multi user switch in expanded quick settings -->
<dimen name="multi_user_switch_expanded_margin">8dp</dimen>
+
+ <!-- end margin for system icons if multi user switch is hidden -->
+ <dimen name="system_icons_switcher_hidden_expanded_margin">16dp</dimen>
+
+ <!-- The thickness of the colored border around the current user. -->
+ <dimen name="keyguard_user_switcher_border_thickness">2dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 260f59c..f021253 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -549,6 +549,18 @@
<string name="recents_search_bar_label">search</string>
+ <!-- Expanded Status Bar Header: Battery Charged [CHAR LIMIT=40] -->
+ <string name="expanded_header_battery_charged">Charged</string>
+
+ <!-- Expanded Status Bar Header: Charging, no known time [CHAR LIMIT=40] -->
+ <string name="expanded_header_battery_charging">Charging</string>
+
+ <!-- Expanded Status Bar Header: Charging, showing time left until charged [CHAR LIMIT=40] -->
+ <string name="expanded_header_battery_charging_with_time"><xliff:g id="charging_time" example="2 hrs 25 min">%s</xliff:g> until full</string>
+
+ <!-- Expanded Status Bar Header: Not charging [CHAR LIMIT=40] -->
+ <string name="expanded_header_battery_not_charging">Not charging</string>
+
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
<string name="battery_meter_very_low_overlay_symbol">!</string>
@@ -565,14 +577,6 @@
<!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
<string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
- <!-- Zen mode: Summary notification content title. [CHAR LIMIT=NONE] -->
- <plurals name="zen_mode_notification_title">
- <item quantity="one">Notification hidden</item>
- <item quantity="other">%d notifications hidden</item>
- </plurals>
- <!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_notification_text">Touch to show</string>
-
<!-- Zen mode: Short title. [CHAR LIMIT=40] -->
<string name="zen_mode_title">Do not disturb</string>
@@ -602,6 +606,13 @@
<!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]-->
<string name="keyguard_indication_charging_time">Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
+ <!-- Related to user switcher --><skip/>
+ <!-- Name for the guest user -->
+ <string name="guest_nickname">Guest</string>
+
+ <!-- Label for adding a new guest -->
+ <string name="guest_new_guest">+ Guest</string>
+
<!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one">For one minute</item>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 79a13f8..e5d5b03 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -70,17 +70,29 @@
<style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar" />
<style name="TextAppearance.StatusBar.Expanded.Clock">
- <item name="android:textSize">18dp</item>
+ <item name="android:textSize">16dp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">#ffffff</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.Date">
+ <item name="android:textSize">14dp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">#99ffffff</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
<item name="android:textSize">12dp</item>
<item name="android:textStyle">normal</item>
- <item name="android:textColor">#afb3b6</item>
+ <item name="android:textColor">#99ffffff</item>
</style>
+ <style name="TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
+ parent="TextAppearance.StatusBar.Expanded.AboveDateTime" />
+
+ <style name="TextAppearance.StatusBar.Expanded.ChargingInfo"
+ parent="TextAppearance.StatusBar.Expanded.AboveDateTime" />
+
<style name="TextAppearance.StatusBar.Expanded.Network" parent="@style/TextAppearance.StatusBar.Expanded.Date">
<item name="android:textColor">#999999</item>
</style>
@@ -88,6 +100,13 @@
<style name="TextAppearance.StatusBar.Expanded.Network.EmergencyOnly">
</style>
+ <style name="TextAppearance.StatusBar.Expanded.UserSwitcher">
+ <item name="android:textSize">16sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">#ffffff</item>
+ </style>
+ <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" />
+
<style name="TextAppearance" />
<style name="TextAppearance.QuickSettings" />
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
index 4147155..14392b4 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
@@ -507,7 +507,6 @@ public class DessertCaseView extends FrameLayout {
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 7c85712..9650435 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -20,9 +20,14 @@ import android.view.Display;
import android.view.View;
public interface RecentsComponent {
+ public interface Callbacks {
+ public void onVisibilityChanged(boolean visible);
+ }
+
void showRecents(boolean triggeredFromAltTab, View statusBarView);
void hideRecents(boolean triggeredFromAltTab);
void toggleRecents(Display display, int layoutDirection, View statusBarView);
void preloadRecents();
void cancelPreloadingRecents();
+ void setCallback(Callbacks cb);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c006c88..b9e2e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -59,8 +59,6 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.MultiUserAvatarCache;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-import com.android.keyguard.analytics.Session;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -70,7 +68,6 @@ import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import java.io.File;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
/**
@@ -117,7 +114,6 @@ import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapte
public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
final static boolean DEBUG = false;
- private static final boolean ENABLE_ANALYTICS = false;
private final static boolean DBG_WAKE = false;
private final static String TAG = "KeyguardViewMediator";
@@ -199,8 +195,6 @@ public class KeyguardViewMediator extends SystemUI {
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private KeyguardAnalytics mKeyguardAnalytics;
-
// these are protected by synchronized (this)
/**
@@ -245,6 +239,12 @@ public class KeyguardViewMediator extends SystemUI {
private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
/**
+ * Whether a hide is pending an we are just waiting for #startKeyguardExitAnimation to be
+ * called.
+ * */
+ private boolean mHiding;
+
+ /**
* we send this intent when the keyguard is dismissed.
*/
private static final Intent USER_PRESENT_INTENT = new Intent(Intent.ACTION_USER_PRESENT)
@@ -469,22 +469,6 @@ public class KeyguardViewMediator extends SystemUI {
mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
- if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
- Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
- mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
-
- @Override
- public int getSessionType() {
- return mLockPatternUtils.isSecure() && !mUpdateMonitor.getUserHasTrust(
- mLockPatternUtils.getCurrentUser())
- ? Session.TYPE_KEYGUARD_SECURE
- : Session.TYPE_KEYGUARD_INSECURE;
- }
- }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
- } else {
- mKeyguardAnalytics = null;
- }
-
mScreenOn = mPM.isScreenOn();
mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
@@ -585,9 +569,6 @@ public class KeyguardViewMediator extends SystemUI {
} else {
doKeyguardLocked(null);
}
- if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
- mKeyguardAnalytics.getCallback().onScreenOff();
- }
}
KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
}
@@ -830,9 +811,6 @@ public class KeyguardViewMediator extends SystemUI {
updateActivityLockScreenState();
adjustStatusBarLocked();
}
- if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
- mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
- }
}
}
@@ -1197,6 +1175,7 @@ public class KeyguardViewMediator extends SystemUI {
}
mStatusBarKeyguardViewManager.show(options);
+ mHiding = false;
mShowing = true;
mKeyguardDonePending = false;
updateActivityLockScreenState();
@@ -1219,7 +1198,7 @@ public class KeyguardViewMediator extends SystemUI {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleHide");
try {
-
+ mHiding = true;
if (mShowing) {
// Don't actually hide the Keyguard at the moment, wait for window manager until
@@ -1240,6 +1219,11 @@ public class KeyguardViewMediator extends SystemUI {
private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
synchronized (KeyguardViewMediator.this) {
+ if (!mHiding) {
+ return;
+ }
+ mHiding = false;
+
// only play "unlock" noises if not on a call (since the incall UI
// disables the keyguard)
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index e8f3745..41b1f75 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -126,7 +126,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
}
private void updateNotification() {
- Slog.d(TAG, "updateNotification mWarning=" + mWarning
+ if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning
+ " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger);
if (mInvalidCharger) {
showInvalidChargerNotification();
@@ -152,6 +152,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setContentText(mContext.getString(R.string.invalid_charger_text))
.setPriority(Notification.PRIORITY_MAX)
.setCategory(Notification.CATEGORY_SYSTEM)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
.setFullScreenIntent(pendingBroadcast(ACTION_SHOW_FALLBACK_CHARGER), true);
final Notification n = nb.build();
if (n.headsUpContentView != null) {
@@ -171,6 +172,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setOngoing(true)
.setPriority(Notification.PRIORITY_MAX)
.setCategory(Notification.CATEGORY_SYSTEM)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
.setFullScreenIntent(pendingBroadcast(ACTION_SHOW_FALLBACK_WARNING), true);
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
@@ -197,7 +199,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setContentText(mContext.getString(R.string.battery_saver_notification_text))
.setOngoing(true)
.setShowWhen(false)
- .setCategory(Notification.CATEGORY_SYSTEM);
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setVisibility(Notification.VISIBILITY_PUBLIC);
if (hasSaverSettings()) {
nb.addAction(0,
mContext.getString(R.string.battery_saver_notification_action_text),
@@ -238,13 +241,13 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
@Override
public void dismissLowBatteryWarning() {
- Slog.i(TAG, "dismissing low battery warning: level=" + mBatteryLevel);
+ if (DEBUG) Slog.d(TAG, "dismissing low battery warning: level=" + mBatteryLevel);
dismissLowBatteryNotification();
mFallbackDialogs.dismissLowBatteryWarning();
}
private void dismissLowBatteryNotification() {
- Slog.i(TAG, "dismissing low battery notification");
+ if (mWarning) Slog.i(TAG, "dismissing low battery notification");
mWarning = false;
updateNotification();
}
@@ -307,7 +310,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
}
private void dismissInvalidChargerNotification() {
- Slog.i(TAG, "dismissing invalid charger notification");
+ if (mInvalidCharger) Slog.i(TAG, "dismissing invalid charger notification");
mInvalidCharger = false;
updateNotification();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
index b981ed6..c4bdb19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
@@ -69,6 +69,7 @@ public class NotificationsTile extends QSTile<NotificationsTile.NotificationsSta
@Override
public void onViewAttachedToWindow(View v) {
+ vp.updateStates();
volumeComponent.setVolumePanel(vp);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index 116d755..e03c01c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -273,6 +273,13 @@ public class Recents extends SystemUI implements RecentsComponent {
}
}
+ @Override
+ public void setCallback(Callbacks cb) {
+ if (mUseAlternateRecents) {
+ mAlternateRecents.setRecentsComponentCallback(cb);
+ }
+ }
+
/**
* Send broadcast only if BOOT_COMPLETED
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 24a31f8..8dcdcdb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -27,7 +27,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -35,16 +34,13 @@ 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;
-import android.view.Surface;
-import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -129,8 +125,10 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
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";
+ final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
+ final public static String EXTRA_FROM_APP_THUMBNAIL = "recents.animatingWithThumbnail";
+ final public static String EXTRA_FROM_APP_FULL_SCREENSHOT = "recents.thumbnail";
+ final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
final public static String KEY_CONFIGURATION_DATA = "recents.data.updateForConfiguration";
final public static String KEY_WINDOW_RECT = "recents.windowRect";
final public static String KEY_SYSTEM_INSETS = "recents.systemInsets";
@@ -138,7 +136,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
final public static String KEY_TWO_TASK_STACK_RECT = "recents.twoCountTaskRect";
final public static String KEY_MULTIPLE_TASK_STACK_RECT = "recents.multipleCountTaskRect";
-
final static int sMinToggleDelay = 425;
final static String sToggleRecentsAction = "com.android.systemui.recents.SHOW_RECENTS";
@@ -146,6 +143,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity";
final static String sRecentsService = "com.android.systemui.recents.RecentsService";
+ static Bitmap sLastScreenshot;
+ static RecentsComponent.Callbacks sRecentsComponentCallbacks;
+
Context mContext;
SystemServicesProxy mSystemServicesProxy;
@@ -213,15 +213,19 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
if (Console.Enabled) {
Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
}
+
if (mServiceIsBound && mBootCompleted) {
- // Notify recents to close it
- try {
- Bundle data = new Bundle();
- Message msg = Message.obtain(null, MSG_HIDE_RECENTS, triggeredFromAltTab ? 1 : 0, 0);
- msg.setData(data);
- mService.send(msg);
- } catch (RemoteException re) {
- re.printStackTrace();
+ if (isRecentsTopMost(null)) {
+ // Notify recents to close it
+ try {
+ Bundle data = new Bundle();
+ Message msg = Message.obtain(null, MSG_HIDE_RECENTS,
+ triggeredFromAltTab ? 1 : 0, 0);
+ msg.setData(data);
+ mService.send(msg);
+ } catch (RemoteException re) {
+ re.printStackTrace();
+ }
}
}
}
@@ -343,80 +347,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
- /** Converts from the device rotation to the degree */
- float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90:
- return 360f - 90f;
- case Surface.ROTATION_180:
- return 360f - 180f;
- case Surface.ROTATION_270:
- return 360f - 270f;
- }
- return 0f;
- }
-
- /** Takes a screenshot of the surface */
- Bitmap takeScreenshot(Display display) {
- DisplayMetrics dm = new DisplayMetrics();
- display.getRealMetrics(dm);
- float[] dims = {dm.widthPixels, dm.heightPixels};
- float degrees = getDegreesForRotation(display.getRotation());
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
- // Get the dimensions of the device in its native orientation
- Matrix m = new Matrix();
- m.preRotate(-degrees);
- m.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
- return SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
- }
-
- /** Creates the activity options for a thumbnail transition. */
- ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) {
- // Loading from thumbnail
- Bitmap thumbnail;
- Bitmap firstThumbnail = loadFirstTaskThumbnail();
- if (firstThumbnail != null) {
- // Create the thumbnail
- thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
- Bitmap.Config.ARGB_8888);
- int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
- new Rect(0, 0, taskRect.width(), taskRect.height()), null);
- c.setBitmap(null);
- // Recycle the old thumbnail
- firstThumbnail.recycle();
- } else {
- // Load the thumbnail from the screenshot if can't get one from the system
- WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Bitmap screenshot = takeScreenshot(display);
- if (screenshot != null) {
- Resources res = mContext.getResources();
- int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
- int statusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight +
- size), new Rect(0, 0, taskRect.width(), taskRect.height()), null);
- c.setBitmap(null);
- // Recycle the temporary screenshot
- screenshot.recycle();
- } else {
- return null;
- }
- }
-
- return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail,
- taskRect.left, taskRect.top, this);
- }
-
/** Returns whether the recents is currently running */
boolean isRecentsTopMost(AtomicBoolean isHomeTopMost) {
SystemServicesProxy ssp = mSystemServicesProxy;
@@ -462,10 +392,12 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
mService.send(msg);
// Time this path
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "sendToggleRecents");
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "sendToggleRecents");
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "sendToggleRecents");
+ Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
+ Constants.Log.App.TimeRecentsLaunchKey, "sendToggleRecents");
+ }
} catch (RemoteException re) {
re.printStackTrace();
}
@@ -486,6 +418,68 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
+ /**
+ * Creates the activity options for a unknown state->recents transition.
+ */
+ ActivityOptions getUnknownTransitionActivityOptions() {
+ // Reset the last screenshot
+ consumeLastScreenshot();
+ return ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_from_unknown_enter,
+ R.anim.recents_from_unknown_exit, mHandler, this);
+ }
+
+ /**
+ * Creates the activity options for a home->recents transition.
+ */
+ ActivityOptions getHomeTransitionActivityOptions() {
+ // Reset the last screenshot
+ consumeLastScreenshot();
+ return ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_from_launcher_enter,
+ R.anim.recents_from_launcher_exit, mHandler, this);
+ }
+
+ /**
+ * Creates the activity options for an app->recents transition. If this method sets the static
+ * screenshot, then we will use that for the transition.
+ */
+ ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) {
+ // Recycle the last screenshot
+ consumeLastScreenshot();
+
+ // Take the full screenshot
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
+ sLastScreenshot = mSystemServicesProxy.takeScreenshot();
+ if (sLastScreenshot != null) {
+ return ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_from_app_enter,
+ R.anim.recents_from_app_exit, mHandler, this);
+ }
+ }
+
+ // If the screenshot fails, then load the first task thumbnail and use that
+ Bitmap firstThumbnail = loadFirstTaskThumbnail();
+ if (firstThumbnail != null) {
+ // Create the new thumbnail for the animation down
+ // XXX: We should find a way to optimize this so we don't need to create a new bitmap
+ Bitmap thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+ Canvas c = new Canvas(thumbnail);
+ c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
+ new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+ c.setBitmap(null);
+ // Recycle the old thumbnail
+ firstThumbnail.recycle();
+ return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
+ thumbnail, taskRect.left, taskRect.top, this);
+ }
+
+ // If both the screenshot and thumbnail fails, then just fall back to the default transition
+ return getUnknownTransitionActivityOptions();
+ }
+
/** Starts the recents activity */
void startRecentsActivity(boolean isTopTaskHome) {
// If Recents is not the front-most activity and we should animate into it. If
@@ -498,39 +492,52 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
Rect taskRect = getAnimationTaskRect(recentTasks);
boolean useThumbnailTransition = !isTopTaskHome &&
hasValidTaskRects();
+ boolean hasRecentTasks = !recentTasks.isEmpty();
if (useThumbnailTransition) {
// Try starting with a thumbnail transition
ActivityOptions opts = getThumbnailTransitionActivityOptions(taskRect);
if (opts != null) {
- startAlternateRecentsActivity(opts, true);
+ if (sLastScreenshot != null) {
+ startAlternateRecentsActivity(opts, EXTRA_FROM_APP_FULL_SCREENSHOT);
+ } else {
+ startAlternateRecentsActivity(opts, EXTRA_FROM_APP_THUMBNAIL);
+ }
} else {
// Fall through below to the non-thumbnail transition
useThumbnailTransition = false;
}
+ } else {
+ // If there is no thumbnail transition, but is launching from home into recents, then
+ // use a quick home transition and do the animation from home
+ if (hasRecentTasks && Constants.DebugFlags.App.EnableHomeTransition) {
+ ActivityOptions opts = getHomeTransitionActivityOptions();
+ startAlternateRecentsActivity(opts, EXTRA_FROM_HOME);
+ } else {
+ // Otherwise we do the normal fade from an unknown source
+ ActivityOptions opts = getUnknownTransitionActivityOptions();
+ startAlternateRecentsActivity(opts, null);
+ }
}
- // If there is no thumbnail transition, then just use a generic transition
- if (!useThumbnailTransition) {
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit, mHandler, this);
- startAlternateRecentsActivity(opts, false);
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ Constants.Log.App.TimeRecentsStartupKey, "startRecentsActivity");
}
-
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "startRecentsActivity");
mLastToggleTime = System.currentTimeMillis();
}
/** Starts the recents activity */
- void startAlternateRecentsActivity(ActivityOptions opts, boolean animatingWithThumbnail) {
+ void startAlternateRecentsActivity(ActivityOptions opts, String extraFlag) {
Intent intent = new Intent(sToggleRecentsAction);
intent.setClassName(sRecentsPackage, sRecentsActivity);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- intent.putExtra(EXTRA_ANIMATING_WITH_THUMBNAIL, animatingWithThumbnail);
- intent.putExtra(EXTRA_FROM_ALT_TAB, mTriggeredFromAltTab);
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ if (extraFlag != null) {
+ intent.putExtra(extraFlag, true);
+ }
+ intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
if (opts != null) {
mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
UserHandle.USER_CURRENT));
@@ -539,6 +546,30 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
+ /** Returns the last screenshot taken, this will be called by the RecentsActivity. */
+ public static Bitmap getLastScreenshot() {
+ return sLastScreenshot;
+ }
+
+ /** Recycles the last screenshot taken, this will be called by the RecentsActivity. */
+ public static void consumeLastScreenshot() {
+ if (sLastScreenshot != null) {
+ sLastScreenshot.recycle();
+ sLastScreenshot = null;
+ }
+ }
+
+ /** Sets the RecentsComponent callbacks. */
+ public void setRecentsComponentCallback(RecentsComponent.Callbacks cb) {
+ sRecentsComponentCallbacks = cb;
+ }
+
+ /** Notifies the callbacks that the visibility of Recents has changed. */
+ public static void notifyVisibilityChanged(boolean visible) {
+ if (sRecentsComponentCallbacks != null) {
+ sRecentsComponentCallbacks.onVisibilityChanged(visible);
+ }
+ }
/**** OnAnimationStartedListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 147ff62..2abbad5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -25,10 +25,16 @@ public class Constants {
public static final boolean Verbose = false;
public static class App {
+ // Enables the home->Recents transition
+ public static final boolean EnableHomeTransition = true;
+ // Enables the screenshot app->Recents transition
+ public static final boolean EnableScreenshotAppTransition = false;
// Enables the filtering of tasks according to their grouping
- public static final boolean EnableTaskFiltering = false;
+ public static final boolean EnableTaskFiltering = true;
// Enables clipping of tasks against each other
public static final boolean EnableTaskStackClipping = true;
+ // Enables tapping on the TaskBar to launch the task
+ public static final boolean EnableTaskBarTouchEvents = true;
// Enables the use of theme colors as the task bar background
public static final boolean EnableTaskBarThemeColors = true;
// Enables app-info pane on long-pressing the icon
@@ -44,7 +50,7 @@ public class Constants {
// For debugging, this defines the number of mock recents packages to create
public static final int SystemServicesProxyMockPackageCount = 3;
// For debugging, this defines the number of mock recents tasks to create
- public static final int SystemServicesProxyMockTaskCount = 75;
+ public static final int SystemServicesProxyMockTaskCount = 100;
}
}
@@ -52,8 +58,11 @@ public class Constants {
public static class App {
public static final String TimeRecentsStartupKey = "startup";
public static final String TimeRecentsLaunchKey = "launchTask";
- public static final boolean TimeRecentsStartup = false;
- public static final boolean TimeRecentsLaunchTask = false;
+ public static final String TimeRecentsScreenshotTransitionKey = "screenshot";
+ public static final boolean TimeRecentsStartup = true;
+ public static final boolean TimeRecentsLaunchTask = true;
+ public static final boolean TimeRecentsScreenshotTransition = true;
+
public static final boolean RecentsComponent = false;
public static final boolean TaskDataLoader = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
new file mode 100644
index 0000000..f0b2cb6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
@@ -0,0 +1,85 @@
+/*
+ * 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.systemui.recents;
+
+import android.os.Handler;
+
+/**
+ * A dozer is a class that fires a trigger after it falls asleep. You can occasionally poke it to
+ * wake it up, but it will fall asleep if left untouched.
+ */
+public class DozeTrigger {
+
+ Handler mHandler;
+
+ boolean mIsDozing;
+ boolean mHasTriggered;
+ int mDozeDurationSeconds;
+ Runnable mSleepRunnable;
+
+ // Sleep-runnable
+ Runnable mDozeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mSleepRunnable.run();
+ mIsDozing = false;
+ mHasTriggered = true;
+ }
+ };
+
+ public DozeTrigger(int dozeDurationSeconds, Runnable sleepRunnable) {
+ mHandler = new Handler();
+ mDozeDurationSeconds = dozeDurationSeconds;
+ mSleepRunnable = sleepRunnable;
+ }
+
+ /** Starts dozing. This also resets the trigger flag. */
+ public void startDozing() {
+ forcePoke();
+ mHasTriggered = false;
+ }
+
+ /** Stops dozing. */
+ public void stopDozing() {
+ mHandler.removeCallbacks(mDozeRunnable);
+ mIsDozing = false;
+ }
+
+ /** Poke this dozer to wake it up for a little bit, if it is dozing. */
+ public void poke() {
+ if (mIsDozing) {
+ forcePoke();
+ }
+ }
+
+ /** Poke this dozer to wake it up for a little bit. */
+ void forcePoke() {
+ mHandler.removeCallbacks(mDozeRunnable);
+ mHandler.postDelayed(mDozeRunnable, mDozeDurationSeconds * 1000);
+ mIsDozing = true;
+ }
+
+ /** Returns whether we are dozing or not. */
+ public boolean isDozing() {
+ return mIsDozing;
+ }
+
+ /** Returns whether the trigger has fired at least once. */
+ public boolean hasTriggered() {
+ return mHasTriggered;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 96344d5..52a17df 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,80 +17,94 @@
package com.android.systemui.recents;
import android.app.Activity;
-import android.appwidget.AppWidgetHost;
+import android.app.ActivityOptions;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
import android.os.Bundle;
+import android.os.UserHandle;
import android.util.Pair;
-import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
+import android.view.ViewStub;
import com.android.systemui.R;
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.FullscreenTransitionOverlayView;
import com.android.systemui.recents.views.RecentsView;
+import com.android.systemui.recents.views.SystemBarScrimViews;
+import com.android.systemui.recents.views.ViewAnimation;
import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Set;
-
-/** Our special app widget host */
-class RecentsAppWidgetHost extends AppWidgetHost {
- /* Callbacks to notify when an app package changes */
- interface RecentsAppWidgetHostCallbacks {
- public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo);
- }
-
- RecentsAppWidgetHostCallbacks mCb;
-
- public RecentsAppWidgetHost(Context context, int hostId, RecentsAppWidgetHostCallbacks cb) {
- super(context, hostId);
- mCb = cb;
- }
-
- @Override
- protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
- mCb.onProviderChanged(appWidgetId, appWidget);
- }
-}
/* Activity */
public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
- FrameLayout mContainerView;
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
+ FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
+
RecentsView mRecentsView;
+ SystemBarScrimViews mScrimViews;
+ ViewStub mEmptyViewStub;
View mEmptyView;
- View mNavBarScrimView;
+ ViewStub mFullscreenOverlayStub;
+ FullscreenTransitionOverlayView mFullScreenOverlayView;
- AppWidgetHost mAppWidgetHost;
+ RecentsConfiguration mConfig;
+
+ RecentsAppWidgetHost mAppWidgetHost;
AppWidgetProviderInfo mSearchAppWidgetInfo;
AppWidgetHostView mSearchAppWidgetHostView;
boolean mVisible;
boolean mTaskLaunched;
- private static Method sPropertyMethod;
- static {
- try {
- Class<?> c = Class.forName("android.view.GLES20Canvas");
- sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
- if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
+ // Runnables to finish the Recents activity
+ FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable(true);
+ FinishRecentsRunnable mFinishWithoutAnimationRunnable = new FinishRecentsRunnable(false);
+ FinishRecentsRunnable mFinishLaunchHomeRunnable;
+
+ /**
+ * A Runnable to finish Recents either with/without a transition, and either by calling finish()
+ * or just launching the specified intent.
+ */
+ class FinishRecentsRunnable implements Runnable {
+ boolean mUseCustomFinishTransition;
+ Intent mLaunchIntent;
+ ActivityOptions mLaunchOpts;
+
+ public FinishRecentsRunnable(boolean withTransition) {
+ mUseCustomFinishTransition = withTransition;
+ }
+
+ public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
+ mLaunchIntent = launchIntent;
+ mLaunchOpts = opts;
+ }
+
+ @Override
+ public void run() {
+ // Mark Recents as no longer visible
+ AlternateRecentsComponent.notifyVisibilityChanged(false);
+ // Finish Recents
+ if (mLaunchIntent != null) {
+ if (mLaunchOpts != null) {
+ startActivityAsUser(mLaunchIntent, new UserHandle(UserHandle.USER_CURRENT));
+ } else {
+ startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(),
+ new UserHandle(UserHandle.USER_CURRENT));
+ }
+ } else {
+ finish();
+ if (mUseCustomFinishTransition) {
+ overridePendingTransition(R.anim.recents_to_launcher_enter,
+ R.anim.recents_to_launcher_exit);
+ }
+ }
}
}
@@ -108,8 +122,15 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Dismiss recents, launching the focused task
dismissRecentsIfVisible();
} else {
- // Otherwise, just finish the activity without launching any other activities
- finish();
+ // If we are mid-animation into Recents, then reverse it and finish
+ if (mFullScreenOverlayView == null ||
+ !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+ // Otherwise, either finish Recents, or launch Home directly
+ ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(context,
+ null, mFinishLaunchHomeRunnable, null);
+ mRecentsView.startExitToHomeAnimation(
+ new ViewAnimation.TaskViewExitContext(exitTrigger));
+ }
}
} else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// Try and unfilter and filtered stacks
@@ -119,7 +140,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
} else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) {
// Try and start the enter animation (or restart it on configuration changed)
- mRecentsView.startOnEnterAnimation();
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
+ // Call our callback
+ onEnterAnimationTriggered();
}
}
};
@@ -128,19 +151,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- finish();
+ mFinishWithoutAnimationRunnable.run();
}
};
/** Updates the set of recent tasks */
void updateRecentsTasks(Intent launchIntent) {
- // Update the configuration based on the launch intent
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.launchedWithThumbnailAnimation = launchIntent.getBooleanExtra(
- AlternateRecentsComponent.EXTRA_ANIMATING_WITH_THUMBNAIL, false);
- config.launchedFromAltTab = launchIntent.getBooleanExtra(
- AlternateRecentsComponent.EXTRA_FROM_ALT_TAB, false);
-
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
ArrayList<TaskStack> stacks = root.getStacks();
@@ -148,24 +164,34 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mRecentsView.setBSP(root);
}
- // Hide the scrim by default when we enter recents
- mNavBarScrimView.setVisibility(View.INVISIBLE);
+ // Update the configuration based on the launch intent
+ mConfig.launchedFromHome = launchIntent.getBooleanExtra(
+ AlternateRecentsComponent.EXTRA_FROM_HOME, false);
+ mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
+ AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
+ mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra(
+ AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
+ mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
+ AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
+ mConfig.launchedWithNoRecentTasks = !root.hasTasks();
+
+ // Show the scrim if we animate into Recents without window transitions
+ mScrimViews.prepareEnterRecentsAnimation();
// Add the default no-recents layout
- if (stacks.size() == 1 && stacks.get(0).getTaskCount() == 0) {
+ if (mEmptyView == null) {
+ mEmptyView = mEmptyViewStub.inflate();
+ }
+ if (mConfig.launchedWithNoRecentTasks) {
mEmptyView.setVisibility(View.VISIBLE);
} else {
mEmptyView.setVisibility(View.GONE);
}
-
- // Dim the background
- mRecentsView.setBackgroundColor(0x80000000);
}
/** Attempts to allocate and bind the search bar app widget */
void bindSearchBarAppWidget() {
if (Constants.DebugFlags.App.EnableSearchLayout) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
// Reset the host view and widget info
@@ -173,7 +199,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mSearchAppWidgetInfo = null;
// Try and load the app widget id from the settings
- int appWidgetId = config.searchBarAppWidgetId;
+ int appWidgetId = mConfig.searchBarAppWidgetId;
if (appWidgetId >= 0) {
mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
if (mSearchAppWidgetInfo == null) {
@@ -203,7 +229,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
// Save the app widget id into the settings
- config.updateSearchBarAppWidgetId(this, widgetInfo.first);
+ mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first);
mSearchAppWidgetInfo = widgetInfo.second;
}
}
@@ -213,8 +239,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Creates the search bar app widget view */
void addSearchBarAppWidgetView() {
if (Constants.DebugFlags.App.EnableSearchLayout) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- int appWidgetId = config.searchBarAppWidgetId;
+ int appWidgetId = mConfig.searchBarAppWidgetId;
if (appWidgetId >= 0) {
if (Console.Enabled) {
Console.log(Constants.Log.App.SystemUIHandshake,
@@ -240,9 +265,24 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
boolean dismissRecentsIfVisible() {
if (mVisible) {
- if (!mRecentsView.launchFocusedTask()) {
- if (!mRecentsView.launchFirstTask()) {
- finish();
+ // If we are mid-animation into Recents, then reverse it and finish
+ if (mFullScreenOverlayView == null ||
+ !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+ // If we have a focused task, then launch that task
+ if (!mRecentsView.launchFocusedTask()) {
+ if (mConfig.launchedFromHome) {
+ // Just start the animation out of recents
+ ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
+ null, mFinishLaunchHomeRunnable, null);
+ mRecentsView.startExitToHomeAnimation(
+ new ViewAnimation.TaskViewExitContext(exitTrigger));
+ } else {
+ // Otherwise, try and launch the first task
+ if (!mRecentsView.launchFirstTask()) {
+ // If there are no tasks, then just finish recents
+ mFinishLaunchHomeRunnable.run();
+ }
+ }
}
}
return true;
@@ -264,38 +304,41 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Initialize the loader and the configuration
RecentsTaskLoader.initialize(this);
- RecentsConfiguration.reinitialize(this);
+ mConfig = RecentsConfiguration.reinitialize(this);
+
+ // Create the home intent runnable
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
+ ActivityOptions.makeCustomAnimation(this, R.anim.recents_to_launcher_enter,
+ R.anim.recents_to_launcher_exit));
// Initialize the widget host (the host id is static and does not change)
- mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId, this);
+ mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
- // Create the view hierarchy
- mRecentsView = new RecentsView(this);
+ // Set the Recents layout
+ setContentView(R.layout.recents);
+ mRecentsView = (RecentsView) findViewById(R.id.recents_view);
mRecentsView.setCallbacks(this);
- mRecentsView.setLayoutParams(new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.MATCH_PARENT));
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-
- // Create the empty view
- LayoutInflater inflater = LayoutInflater.from(this);
- mEmptyView = inflater.inflate(R.layout.recents_empty, mContainerView, false);
- mNavBarScrimView = inflater.inflate(R.layout.recents_nav_bar_scrim, mContainerView, false);
- mNavBarScrimView.setLayoutParams(new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
-
- mContainerView = new FrameLayout(this);
- mContainerView.addView(mRecentsView);
- mContainerView.addView(mEmptyView);
- mContainerView.addView(mNavBarScrimView);
- setContentView(mContainerView);
+ mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
+ mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
+ mScrimViews = new SystemBarScrimViews(this, mConfig);
// Update the recent tasks
updateRecentsTasks(getIntent());
+ // Prepare the screenshot transition if necessary
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
+ mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
+ mFullScreenOverlayView.setCallbacks(this);
+ mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
+ }
+
// Bind the search app widget when we first start up
bindSearchBarAppWidget();
// Add the search bar layout
@@ -306,10 +349,10 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
onConfigurationChange();
}
- // XXX: Update the shadows
+ // Private API calls to make the shadows look better
try {
- sPropertyMethod.invoke(null, "ambientShadowStrength", String.valueOf(35f));
- sPropertyMethod.invoke(null, "ambientRatio", String.valueOf(0.5f));
+ Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
+ Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
@@ -319,7 +362,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
void onConfigurationChange() {
// Try and start the enter animation (or restart it on configuration changed)
- mRecentsView.startOnEnterAnimation();
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
+ // Call our callback
+ onEnterAnimationTriggered();
}
@Override
@@ -338,11 +383,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Initialize the loader and the configuration
RecentsTaskLoader.initialize(this);
- RecentsConfiguration.reinitialize(this);
+ mConfig = RecentsConfiguration.reinitialize(this);
// Update the recent tasks
updateRecentsTasks(intent);
+ // Prepare the screenshot transition if necessary
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
+ mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
+ }
+
// Don't attempt to rebind the search bar widget, but just add the search bar layout
addSearchBarAppWidgetView();
}
@@ -355,12 +405,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
super.onStart();
- // Start listening for widget package changes if there is one bound
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (config.searchBarAppWidgetId >= 0) {
- mAppWidgetHost.startListening();
- }
-
mVisible = true;
}
@@ -396,6 +440,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Register any broadcast receivers for the task loader
RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
+
+ // Start listening for widget package changes if there is one bound
+ if (mConfig.searchBarAppWidgetId >= 0) {
+ mAppWidgetHost.startListening(this);
+ }
}
@Override
@@ -411,6 +460,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
unregisterReceiver(mServiceBroadcastReceiver);
unregisterReceiver(mScreenOffReceiver);
RecentsTaskLoader.getInstance().unregisterReceivers();
+
+ // Stop listening for widget package changes if there was one bound
+ if (mConfig.searchBarAppWidgetId >= 0) {
+ mAppWidgetHost.stopListening();
+ }
}
@Override
@@ -430,12 +484,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
super.onStop();
- // Stop listening for widget package changes if there was one bound
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (config.searchBarAppWidgetId >= 0) {
- mAppWidgetHost.stopListening();
- }
-
mVisible = false;
mTaskLaunched = false;
}
@@ -470,58 +518,78 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
@Override
+ public void onUserInteraction() {
+ mRecentsView.onUserInteraction();
+ }
+
+ @Override
public void onBackPressed() {
- // Unfilter any stacks
- if (!mRecentsView.unfilterFilteredStacks()) {
- if (!mRecentsView.launchFirstTask()) {
- super.onBackPressed();
+ // If we are mid-animation into Recents, then reverse it and finish
+ if (mFullScreenOverlayView == null ||
+ !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+ // If we are currently filtering in any stacks, unfilter them first
+ if (!mRecentsView.unfilterFilteredStacks()) {
+ if (mConfig.launchedFromHome) {
+ // Just start the animation out of recents
+ ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
+ null, mFinishLaunchHomeRunnable, null);
+ mRecentsView.startExitToHomeAnimation(
+ new ViewAnimation.TaskViewExitContext(exitTrigger));
+ } else {
+ // Otherwise, try and launch the first task
+ if (!mRecentsView.launchFirstTask()) {
+ // If there are no tasks, then just finish recents
+ mFinishLaunchHomeRunnable.run();
+ }
+ }
}
}
}
- @Override
public void onEnterAnimationTriggered() {
- // Fade in the scrim
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (config.hasNavBarScrim()) {
- mNavBarScrimView.setVisibility(View.VISIBLE);
- mNavBarScrimView.setAlpha(0f);
- mNavBarScrimView.animate().alpha(1f)
- .setStartDelay(config.taskBarEnterAnimDelay)
- .setDuration(config.navBarScrimEnterDuration)
- .setInterpolator(config.fastOutSlowInInterpolator)
- .withLayer()
- .start();
+ // Animate the scrims in
+ mScrimViews.startEnterRecentsAnimation();
+ }
+
+ /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/
+
+ @Override
+ public void onEnterAnimationComplete(boolean canceled) {
+ if (!canceled) {
+ // Reset the full screenshot transition view
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
+ mFullScreenOverlayView.reset();
+ }
+
+ // XXX: We should clean up the screenshot in this case as well, but it needs to happen
+ // after to animate up
}
+ // Recycle the full screen screenshot
+ AlternateRecentsComponent.consumeLastScreenshot();
}
+ /**** RecentsView.RecentsViewCallbacks Implementation ****/
+
@Override
- public void onTaskLaunching(boolean isTaskInStackBounds) {
+ public void onExitToHomeAnimationTriggered() {
+ // Animate the scrims out
+ mScrimViews.startExitRecentsAnimation();
+ }
+
+ @Override
+ public void onTaskLaunching() {
mTaskLaunched = true;
- // Fade out the scrim
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (!isTaskInStackBounds && config.hasNavBarScrim()) {
- mNavBarScrimView.animate().alpha(0f)
- .setStartDelay(0)
- .setDuration(config.taskBarExitAnimDuration)
- .setInterpolator(config.fastOutSlowInInterpolator)
- .withLayer()
- .start();
- }
+ // Mark recents as no longer visible
+ AlternateRecentsComponent.notifyVisibilityChanged(false);
}
+ /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
+
@Override
- public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
- if (appWidgetId > -1 && appWidgetId == config.searchBarAppWidgetId) {
- // The search provider may have changed, so just delete the old widget and bind it again
- ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
- config.updateSearchBarAppWidgetId(this, -1);
- // Load the widget again
- bindSearchBarAppWidget();
- addSearchBarAppWidgetView();
- }
+ public void refreshSearchWidget() {
+ // Load the Search widget again
+ bindSearchBarAppWidget();
+ addSearchBarAppWidgetView();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
new file mode 100644
index 0000000..d55eba7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -0,0 +1,67 @@
+/*
+ * 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.systemui.recents;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+
+/** Our special app widget host for the Search widget */
+public class RecentsAppWidgetHost extends AppWidgetHost {
+
+ /* Callbacks to notify when an app package changes */
+ interface RecentsAppWidgetHostCallbacks {
+ public void refreshSearchWidget();
+ }
+
+ Context mContext;
+ RecentsAppWidgetHostCallbacks mCb;
+ RecentsConfiguration mConfig;
+
+ public RecentsAppWidgetHost(Context context, int hostId) {
+ super(context, hostId);
+ mContext = context;
+ mConfig = RecentsConfiguration.getInstance();
+ }
+
+ public void startListening(RecentsAppWidgetHostCallbacks cb) {
+ mCb = cb;
+ super.startListening();
+ }
+
+ @Override
+ public void stopListening() {
+ super.stopListening();
+ // Ensure that we release any references to the callbacks
+ mCb = null;
+ mContext = null;
+ }
+
+ @Override
+ protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
+ if (mCb == null) return;
+
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+ if (appWidgetId > -1 && appWidgetId == mConfig.searchBarAppWidgetId) {
+ // The search provider may have changed, so just delete the old widget and bind it again
+ ssp.unbindSearchAppWidget(this, appWidgetId);
+ // Update the search widget
+ mConfig.updateSearchBarAppWidgetId(mContext, -1);
+ mCb.refreshSearchWidget();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 0cf6ee6..10978ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -37,27 +37,40 @@ public class RecentsConfiguration {
DisplayMetrics mDisplayMetrics;
- public Rect systemInsets = new Rect();
- public Rect displayRect = new Rect();
-
- boolean isLandscape;
- boolean transposeRecentsLayoutWithOrientation;
- int searchBarAppWidgetId = -1;
-
+ /** Animations */
public float animationPxMovementPerSecond;
+ /** Interpolators */
public Interpolator fastOutSlowInInterpolator;
public Interpolator fastOutLinearInInterpolator;
public Interpolator linearOutSlowInInterpolator;
+ public Interpolator quintOutInterpolator;
- public int filteringCurrentViewsMinAnimDuration;
- public int filteringNewViewsMinAnimDuration;
+ /** Filtering */
+ public int filteringCurrentViewsAnimDuration;
+ public int filteringNewViewsAnimDuration;
- public int taskStackScrollDismissInfoPaneDistance;
+ /** Insets */
+ public Rect systemInsets = new Rect();
+ public Rect displayRect = new Rect();
+
+ /** Layout */
+ boolean isLandscape;
+ boolean transposeRecentsLayoutWithOrientation;
+
+ /** Search bar */
+ int searchBarAppWidgetId = -1;
+ public int searchBarSpaceHeightPx;
+
+ /** Task stack */
public int taskStackMaxDim;
- public float taskStackWidthPaddingPct;
public int taskStackTopPaddingPx;
+ public float taskStackWidthPaddingPct;
+ /** Task view animation and styles */
+ public int taskViewEnterFromHomeDuration;
+ public int taskViewEnterFromHomeDelay;
+ public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
public int taskViewTranslationZMinPx;
@@ -66,32 +79,56 @@ public class RecentsConfiguration {
public int taskViewRoundedCornerRadiusPx;
public int taskViewHighlightPx;
- public int searchBarSpaceHeightPx;
-
+ /** Task bar colors */
public int taskBarViewDefaultBackgroundColor;
- public int taskBarViewDefaultTextColor;
public int taskBarViewLightTextColor;
public int taskBarViewDarkTextColor;
public int taskBarViewHighlightColor;
+ /** Task bar animations */
public int taskBarEnterAnimDuration;
public int taskBarEnterAnimDelay;
public int taskBarExitAnimDuration;
+ public int taskBarDismissDozeDelaySeconds;
+ /** Nav bar scrim */
public int navBarScrimEnterDuration;
- public boolean launchedFromAltTab;
- public boolean launchedWithThumbnailAnimation;
+ /** Launch states */
+ public boolean launchedWithAltTab;
+ public boolean launchedWithNoRecentTasks;
+ public boolean launchedFromAppWithThumbnail;
+ public boolean launchedFromAppWithScreenshot;
+ public boolean launchedFromHome;
+ /** Dev options */
public boolean developerOptionsEnabled;
/** Private constructor */
- private RecentsConfiguration() {}
+ private RecentsConfiguration(Context context) {
+ // Properties that don't have to be reloaded with each configuration change can be loaded
+ // here.
+
+ // Interpolators
+ 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);
+ quintOutInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.decelerate_quint);
+
+ // Check if the developer options are enabled
+ ContentResolver cr = context.getContentResolver();
+ developerOptionsEnabled = Settings.Global.getInt(cr,
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+ }
/** Updates the configuration to the current context */
public static RecentsConfiguration reinitialize(Context context) {
if (sInstance == null) {
- sInstance = new RecentsConfiguration();
+ sInstance = new RecentsConfiguration(context);
}
sInstance.update(context);
return sInstance;
@@ -108,33 +145,46 @@ public class RecentsConfiguration {
DisplayMetrics dm = res.getDisplayMetrics();
mDisplayMetrics = dm;
+ // Animations
+ animationPxMovementPerSecond =
+ res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
+
+ // Filtering
+ filteringCurrentViewsAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_current_views_duration);
+ filteringNewViewsAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_new_views_duration);
+
+ // Insets
+ displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
+
+ // Layout
isLandscape = res.getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE;
transposeRecentsLayoutWithOrientation =
res.getBoolean(R.bool.recents_transpose_layout_with_orientation);
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout,
- "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
- Console.AnsiGreen);
- }
- displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
- animationPxMovementPerSecond =
- res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
- filteringCurrentViewsMinAnimDuration =
- res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
- filteringNewViewsMinAnimDuration =
- res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
+ // Search bar
+ searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
- taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
- R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
- taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
+ // Update the search widget id
+ SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+ searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
+ // Task stack
TypedValue widthPaddingPctValue = new TypedValue();
res.getValue(R.dimen.recents_stack_width_padding_percentage, widthPaddingPctValue, true);
taskStackWidthPaddingPct = widthPaddingPctValue.getFloat();
+ taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
+ // Task view animation and styles
+ taskViewEnterFromHomeDuration =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+ taskViewEnterFromHomeDelay =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+ taskViewExitToHomeDuration =
+ res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_remove_duration);
taskViewRemoveAnimTranslationXPx =
@@ -148,12 +198,9 @@ public class RecentsConfiguration {
taskViewShadowOutlineBottomInsetPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_shadow_outline_bottom_inset);
- searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
-
+ // Task bar colors
taskBarViewDefaultBackgroundColor =
res.getColor(R.color.recents_task_bar_default_background_color);
- taskBarViewDefaultTextColor =
- res.getColor(R.color.recents_task_bar_default_text_color);
taskBarViewLightTextColor =
res.getColor(R.color.recents_task_bar_light_text_color);
taskBarViewDarkTextColor =
@@ -161,31 +208,25 @@ public class RecentsConfiguration {
taskBarViewHighlightColor =
res.getColor(R.color.recents_task_bar_highlight_color);
+ // Task bar animations
taskBarEnterAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
taskBarEnterAnimDelay =
res.getInteger(R.integer.recents_animate_task_bar_enter_delay);
taskBarExitAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
+ taskBarDismissDozeDelaySeconds =
+ res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
+ // Nav bar scrim
navBarScrimEnterDuration =
res.getInteger(R.integer.recents_nav_bar_scrim_enter_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();
- developerOptionsEnabled = Settings.Global.getInt(cr,
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
-
- // Update the search widget id
- SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
- searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.MeasureAndLayout,
+ "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
+ Console.AnsiGreen);
+ }
}
/** Updates the system insets */
@@ -204,8 +245,11 @@ public class RecentsConfiguration {
/** Called when the configuration has changed, and we want to reset any configuration specific
* members. */
public void updateOnConfigurationChange() {
- launchedFromAltTab = false;
- launchedWithThumbnailAnimation = false;
+ launchedWithAltTab = false;
+ launchedWithNoRecentTasks = false;
+ launchedFromAppWithThumbnail = false;
+ launchedFromAppWithScreenshot = false;
+ launchedFromHome = false;
}
/** Returns whether the search bar app widget exists. */
@@ -213,9 +257,26 @@ public class RecentsConfiguration {
return searchBarAppWidgetId >= 0;
}
+ /** Returns whether the status bar scrim should be animated when shown for the first time. */
+ public boolean shouldAnimateStatusBarScrim() {
+ return launchedFromHome;
+ }
+
+ /** Returns whether the status bar scrim should be visible. */
+ public boolean hasStatusBarScrim() {
+ return !launchedWithNoRecentTasks;
+ }
+
+ /** Returns whether the nav bar scrim should be animated when shown for the first time. */
+ public boolean shouldAnimateNavBarScrim() {
+ return true;
+ }
+
/** Returns whether the nav bar scrim should be visible. */
public boolean hasNavBarScrim() {
- return !transposeRecentsLayoutWithOrientation || !isLandscape;
+ // Only show the scrim if we have recent tasks, and if the nav bar is not transposed
+ return !launchedWithNoRecentTasks &&
+ (!transposeRecentsLayoutWithOrientation || !isLandscape);
}
/**
@@ -257,15 +318,4 @@ public class RecentsConfiguration {
searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
}
}
-
- /** Converts from DPs to PXs */
- public int pxFromDp(float size) {
- return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- size, mDisplayMetrics));
- }
- /** Converts from SPs to PXs */
- public int pxFromSp(float size) {
- return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
- size, mDisplayMetrics));
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
index 8bcc7f5..04d1f1f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
@@ -37,29 +37,29 @@ public class RecentsPackageMonitor extends PackageMonitor {
PackageCallbacks mCb;
List<ActivityManager.RecentTaskInfo> mTasks;
- SystemServicesProxy mSsp;
- boolean mRegistered;
-
- public RecentsPackageMonitor(Context context) {
- mSsp = new SystemServicesProxy(context);
- }
+ SystemServicesProxy mSystemServicesProxy;
/** Registers the broadcast receivers with the specified callbacks. */
public void register(Context context, PackageCallbacks cb) {
+ mSystemServicesProxy = new SystemServicesProxy(context);
mCb = cb;
- if (!mRegistered) {
+ try {
register(context, Looper.getMainLooper(), false);
- mRegistered = true;
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
}
}
/** Unregisters the broadcast receivers. */
@Override
public void unregister() {
- if (mRegistered) {
+ try {
super.unregister();
- mRegistered = false;
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
}
+ mSystemServicesProxy = null;
+ mCb = null;
mTasks.clear();
}
@@ -106,7 +106,7 @@ public class RecentsPackageMonitor extends PackageMonitor {
// If we know that the component still exists in the package, then skip
continue;
}
- if (mSsp.getActivityInfo(cn) != null) {
+ if (mSystemServicesProxy.getActivityInfo(cn) != null) {
componentsKnownToExist.add(cn);
} else {
componentsToRemove.add(cn);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 113efe3..e554af7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -134,10 +134,12 @@ class SystemUIMessageHandler extends Handler {
context.sendBroadcast(intent);
// Time this path
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "receivedToggleRecents");
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "receivedToggleRecents");
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+ 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);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 4685186..07a6a56 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -118,6 +118,7 @@ class TaskResourceLoader implements Runnable {
TaskResourceLoadQueue mLoadQueue;
DrawableLruCache mApplicationIconCache;
BitmapLruCache mThumbnailCache;
+ Bitmap mDefaultThumbnail;
boolean mCancelled;
boolean mWaitingOnLoadQueue;
@@ -125,10 +126,12 @@ class TaskResourceLoader implements Runnable {
/** Constructor, creates a new loading thread that loads task resources in the background */
public TaskResourceLoader(TaskResourceLoadQueue loadQueue,
DrawableLruCache applicationIconCache,
- BitmapLruCache thumbnailCache) {
+ BitmapLruCache thumbnailCache,
+ Bitmap defaultThumbnail) {
mLoadQueue = loadQueue;
mApplicationIconCache = applicationIconCache;
mThumbnailCache = thumbnailCache;
+ mDefaultThumbnail = defaultThumbnail;
mMainThreadHandler = new Handler();
mLoadThread = new HandlerThread("Recents-TaskResourceLoader");
mLoadThread.setPriority(Thread.NORM_PRIORITY - 1);
@@ -238,6 +241,7 @@ class TaskResourceLoader implements Runnable {
loadThumbnail = thumbnail;
mThumbnailCache.put(t.key, thumbnail);
} else {
+ loadThumbnail = mDefaultThumbnail;
Console.logError(mContext,
"Failed to load task top thumbnail for: " +
t.key.baseIntent.getComponent().getPackageName());
@@ -330,6 +334,7 @@ public class RecentsTaskLoader {
BitmapDrawable mDefaultApplicationIcon;
Bitmap mDefaultThumbnail;
+ Bitmap mLoadingThumbnail;
/** Private Constructor */
private RecentsTaskLoader(Context context) {
@@ -352,22 +357,26 @@ public class RecentsTaskLoader {
// Initialize the proxy, cache and loaders
mSystemServicesProxy = new SystemServicesProxy(context);
- mPackageMonitor = new RecentsPackageMonitor(context);
+ mPackageMonitor = new RecentsPackageMonitor();
mLoadQueue = new TaskResourceLoadQueue();
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
- mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache);
+ mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
+ mDefaultThumbnail);
// Create the default assets
Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
icon.eraseColor(0x00000000);
mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- mDefaultThumbnail.eraseColor(0x00000000);
+ mDefaultThumbnail.eraseColor(0xFFffffff);
+ mLoadingThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ mLoadingThumbnail.eraseColor(0x00000000);
mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
if (Console.Enabled) {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|defaultBitmaps]",
- "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+ "icon: " + mDefaultApplicationIcon +
+ " default thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
}
}
@@ -394,7 +403,7 @@ public class RecentsTaskLoader {
SystemServicesProxy ssp = mSystemServicesProxy;
List<ActivityManager.RecentTaskInfo> tasks =
- ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
+ ssp.getRecentTasks(50, UserHandle.CURRENT.getIdentifier());
Collections.reverse(tasks);
if (Console.Enabled) {
Console.log(Constants.Log.App.TimeSystemCalls,
@@ -478,7 +487,7 @@ public class RecentsTaskLoader {
// Load the thumbnail (if possible and not the foremost task, from the cache)
if (!isForemostTask) {
task.thumbnail = mThumbnailCache.get(task.key);
- if (task.thumbnail != null) {
+ if (task.thumbnail != null && !tasksToForceLoad.contains(task)) {
// Even though we get things from the cache, we should update them if
// they've changed in the bg
tasksToForceLoad.add(task);
@@ -489,6 +498,7 @@ public class RecentsTaskLoader {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|loadingTaskThumbnail]");
}
+
task.thumbnail = ssp.getTaskThumbnail(task.key.id);
if (task.thumbnail != null) {
task.thumbnail.setHasAlpha(false);
@@ -512,20 +522,6 @@ public class RecentsTaskLoader {
"" + (System.currentTimeMillis() - t1) + "ms");
}
- /*
- // Get all the stacks
- t1 = System.currentTimeMillis();
- List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
- Console.log(Constants.Log.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
- for (ActivityManager.StackInfo s : stackInfos) {
- Console.log(Constants.Log.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
- if (stacks.containsKey(s.stackId)) {
- stacks.get(s.stackId).setRect(s.bounds);
- }
- }
- */
-
// Start the task loader
mLoader.start(context);
@@ -557,7 +553,7 @@ public class RecentsTaskLoader {
requiresLoad = true;
}
if (thumbnail == null) {
- thumbnail = mDefaultThumbnail;
+ thumbnail = mLoadingThumbnail;
requiresLoad = true;
}
if (requiresLoad) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/ReferenceCountedTrigger.java
new file mode 100644
index 0000000..d525546
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/ReferenceCountedTrigger.java
@@ -0,0 +1,105 @@
+/*
+ * 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.systemui.recents;
+
+import android.content.Context;
+
+import java.util.ArrayList;
+
+/**
+ * A ref counted trigger that does some logic when the count is first incremented, or last
+ * decremented. Not thread safe as it's not currently needed.
+ */
+public class ReferenceCountedTrigger {
+
+ Context mContext;
+ int mCount;
+ ArrayList<Runnable> mFirstIncRunnables = new ArrayList<Runnable>();
+ ArrayList<Runnable> mLastDecRunnables = new ArrayList<Runnable>();
+ Runnable mErrorRunnable;
+
+ // Convenience runnables
+ Runnable mIncrementRunnable = new Runnable() {
+ @Override
+ public void run() {
+ increment();
+ }
+ };
+ Runnable mDecrementRunnable = new Runnable() {
+ @Override
+ public void run() {
+ decrement();
+ }
+ };
+
+ public ReferenceCountedTrigger(Context context, Runnable firstIncRunnable,
+ Runnable lastDecRunnable, Runnable errorRunanable) {
+ mContext = context;
+ if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable);
+ if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable);
+ mErrorRunnable = errorRunanable;
+ }
+
+ /** Increments the ref count */
+ public void increment() {
+ if (mCount == 0 && !mFirstIncRunnables.isEmpty()) {
+ int numRunnables = mFirstIncRunnables.size();
+ for (int i = 0; i < numRunnables; i++) {
+ mFirstIncRunnables.get(i).run();
+ }
+ }
+ mCount++;
+ }
+
+ /** Convenience method to increment this trigger as a runnable */
+ public Runnable incrementAsRunnable() {
+ return mIncrementRunnable;
+ }
+
+ /** Adds a runnable to the last-decrement runnables list. */
+ public void addLastDecrementRunnable(Runnable r) {
+ mLastDecRunnables.add(r);
+ }
+
+ /** Decrements the ref count */
+ public void decrement() {
+ mCount--;
+ if (mCount == 0 && !mLastDecRunnables.isEmpty()) {
+ int numRunnables = mLastDecRunnables.size();
+ for (int i = 0; i < numRunnables; i++) {
+ mLastDecRunnables.get(i).run();
+ }
+ } else if (mCount < 0) {
+ if (mErrorRunnable != null) {
+ mErrorRunnable.run();
+ } else {
+ new Throwable("Invalid ref count").printStackTrace();
+ Console.logError(mContext, "Invalid ref count");
+ }
+ }
+ }
+
+ /** Convenience method to decrement this trigger as a runnable */
+ public Runnable decrementAsRunnable() {
+ return mDecrementRunnable;
+ }
+
+ /** Returns the current ref count */
+ public int getCount() {
+ return mCount;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 7a3ffb8..c47f7d7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -30,13 +30,23 @@ import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import android.util.Pair;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Iterator;
@@ -48,16 +58,22 @@ import java.util.Random;
* a point of injection when testing UI.
*/
public class SystemServicesProxy {
+ final static String TAG = "SystemServicesProxy";
+
ActivityManager mAm;
AppWidgetManager mAwm;
PackageManager mPm;
IPackageManager mIpm;
UserManager mUm;
SearchManager mSm;
+ WindowManager mWm;
+ Display mDisplay;
String mRecentsPackage;
ComponentName mAssistComponent;
Bitmap mDummyIcon;
+ Paint mBgProtectionPaint;
+ Canvas mBgProtectionCanvas;
/** Private constructor */
public SystemServicesProxy(Context context) {
@@ -67,8 +83,16 @@ public class SystemServicesProxy {
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+ mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mDisplay = mWm.getDefaultDisplay();
mRecentsPackage = context.getPackageName();
+ // Create the protection paints
+ mBgProtectionPaint = new Paint();
+ mBgProtectionPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
+ mBgProtectionPaint.setColor(0xFFffffff);
+ mBgProtectionCanvas = new Canvas();
+
// Resolve the assist intent
Intent assist = mSm.getAssistIntent(context, false);
if (assist != null) {
@@ -184,7 +208,20 @@ public class SystemServicesProxy {
return thumbnail;
}
- return mAm.getTaskTopThumbnail(taskId);
+ Bitmap thumbnail = mAm.getTaskTopThumbnail(taskId);
+ if (thumbnail != null) {
+ // We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
+ // left pixel, then assume the whole thumbnail is transparent. Generally, proper
+ // screenshots are always composed onto a bitmap that has no alpha.
+ if (Color.alpha(thumbnail.getPixel(0, 0)) == 0) {
+ mBgProtectionCanvas.setBitmap(thumbnail);
+ mBgProtectionCanvas.drawRect(0, 0, thumbnail.getWidth(), thumbnail.getHeight(),
+ mBgProtectionPaint);
+ mBgProtectionCanvas.setBitmap(null);
+ Log.e(TAG, "Invalid screenshot detected from getTaskThumbnail()");
+ }
+ }
+ return thumbnail;
}
/** Moves a task to the front with the specified activity options */
@@ -325,4 +362,13 @@ public class SystemServicesProxy {
// Delete the app widget
host.deleteAppWidgetId(appWidgetId);
}
+
+ /**
+ * Takes a screenshot of the current surface.
+ */
+ public Bitmap takeScreenshot() {
+ DisplayInfo di = new DisplayInfo();
+ mDisplay.getDisplayInfo(di);
+ return SurfaceControl.screenshot(di.getNaturalWidth(), di.getNaturalHeight());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 46e6ee9..25875bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,8 +20,26 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
/* Common code */
public class Utilities {
+
+ // Reflection methods for altering shadows
+ private static Method sPropertyMethod;
+ static {
+ try {
+ Class<?> c = Class.forName("android.view.GLES20Canvas");
+ sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
+ if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+ }
+
/**
* Calculates a consistent animation duration (ms) for all animations depending on the movement
* of the object being animated.
@@ -66,4 +84,10 @@ public class Utilities {
int greyscale = colorToGreyscale(color);
return (greyscale < 128) ? lightRes : darkRes;
}
+
+ /** Sets some private shadow properties. */
+ public static void setShadowProperty(String property, String value)
+ throws IllegalAccessException, InvocationTargetException {
+ sPropertyMethod.invoke(null, property, value);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
index 1dd1be6..20be415 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
@@ -56,6 +56,13 @@ public class SpaceNode {
return mStack;
}
+ /** Returns whether there are any tasks in any stacks below this node. */
+ public boolean hasTasks() {
+ return (mStack.getTaskCount() > 0) ||
+ (mStartNode != null && mStartNode.hasTasks()) ||
+ (mEndNode != null && mEndNode.hasTasks());
+ }
+
/** Returns whether this is a leaf node */
boolean isLeafNode() {
return (mStartNode == null) && (mEndNode == null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 47a506c..f366ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.model;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
new file mode 100644
index 0000000..2c632cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
@@ -0,0 +1,257 @@
+/*
+ * 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.systemui.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import com.android.systemui.R;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
+
+
+/**
+ * The full screen transition view that gets animated down from the full screen into a task
+ * thumbnail view.
+ */
+public class FullscreenTransitionOverlayView extends FrameLayout {
+
+ /** The FullscreenTransitionOverlayView callbacks */
+ public interface FullScreenTransitionViewCallbacks {
+ void onEnterAnimationComplete(boolean canceled);
+ }
+
+ RecentsConfiguration mConfig;
+
+ FullScreenTransitionViewCallbacks mCb;
+
+ ImageView mScreenshotView;
+ Rect mClipRect = new Rect();
+ Paint mLayerPaint = new Paint();
+
+ boolean mIsAnimating;
+ AnimatorSet mEnterAnimation;
+
+ public FullscreenTransitionOverlayView(Context context) {
+ super(context);
+ }
+
+ public FullscreenTransitionOverlayView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mConfig = RecentsConfiguration.getInstance();
+ setClipTop(getClipTop());
+ setClipBottom(getClipBottom());
+ setWillNotDraw(false);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mScreenshotView = (ImageView) findViewById(R.id.image);
+ }
+
+ /** Sets the callbacks */
+ public void setCallbacks(FullScreenTransitionViewCallbacks cb) {
+ mCb = cb;
+ }
+
+ /** Sets the top clip */
+ public void setClipTop(int clip) {
+ mClipRect.top = clip;
+ postInvalidateOnAnimation();
+ }
+
+ /** Gets the top clip */
+ public int getClipTop() {
+ return mClipRect.top;
+ }
+
+ /** Sets the bottom clip */
+ public void setClipBottom(int clip) {
+ mClipRect.bottom = clip;
+ postInvalidateOnAnimation();
+ }
+
+ /** Gets the top clip */
+ public int getClipBottom() {
+ return mClipRect.bottom;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ canvas.clipRect(mClipRect);
+ super.draw(canvas);
+ canvas.restoreToCount(restoreCount);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ /** Prepares the screenshot view for the transition into Recents */
+ public void prepareAnimateOnEnterRecents(Bitmap screenshot) {
+ if (!mConfig.launchedFromAppWithScreenshot) return;
+
+ if (Console.Enabled) {
+ Console.logStartTracingTime(Constants.Log.App.TimeRecentsScreenshotTransition,
+ Constants.Log.App.TimeRecentsScreenshotTransitionKey);
+ }
+
+ setClipTop(0);
+ setClipBottom(getMeasuredHeight());
+ setTranslationY(0f);
+ setScaleX(1f);
+ setScaleY(1f);
+ setVisibility(mConfig.launchedFromAppWithScreenshot ? View.VISIBLE : View.INVISIBLE);
+ if (screenshot != null) {
+ mScreenshotView.setImageBitmap(screenshot);
+ } else {
+ mScreenshotView.setImageDrawable(null);
+ }
+ }
+
+ /** Resets the transition view */
+ public void reset() {
+ setVisibility(View.INVISIBLE);
+ mScreenshotView.setImageDrawable(null);
+ }
+
+ /** Animates this view as it enters recents */
+ public void animateOnEnterRecents(ViewAnimation.TaskViewEnterContext ctx,
+ final Runnable postAnimRunnable) {
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsScreenshotTransition,
+ Constants.Log.App.TimeRecentsScreenshotTransitionKey, "Starting");
+ }
+
+ // Cancel the current animation
+ if (mEnterAnimation != null) {
+ mEnterAnimation.removeAllListeners();
+ mEnterAnimation.cancel();
+ }
+
+ // Calculate the bottom clip
+ float scale = (float) ctx.taskRect.width() / getMeasuredWidth();
+ int translationY = -mConfig.systemInsets.top + ctx.stackRectSansPeek.top +
+ ctx.transform.translationY;
+ int clipBottom = mConfig.systemInsets.top + (int) (ctx.taskRect.height() / scale);
+
+ // Enable the HW Layers on the screenshot view
+ mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+
+ // Compose the animation
+ mEnterAnimation = new AnimatorSet();
+ mEnterAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Notify any callbacks
+ mCb.onEnterAnimationComplete(false);
+ // Run the given post-anim runnable
+ postAnimRunnable.run();
+ // Mark that we are no longer animating
+ mIsAnimating = false;
+ // Disable the HW Layers on this view
+ setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsScreenshotTransition,
+ Constants.Log.App.TimeRecentsScreenshotTransitionKey, "Completed");
+ }
+ }
+ });
+ mEnterAnimation.setStartDelay(0);
+ mEnterAnimation.setDuration(475);
+ mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mEnterAnimation.playTogether(
+ ObjectAnimator.ofInt(this, "clipTop", mConfig.systemInsets.top),
+ ObjectAnimator.ofInt(this, "clipBottom", clipBottom),
+ ObjectAnimator.ofFloat(this, "translationY", translationY),
+ ObjectAnimator.ofFloat(this, "scaleX", scale),
+ ObjectAnimator.ofFloat(this, "scaleY", scale)
+ );
+ mEnterAnimation.start();
+
+ mIsAnimating = true;
+ }
+
+ /** Animates this view back out of Recents if we were in the process of animating in. */
+ public boolean cancelAnimateOnEnterRecents(final Runnable postAnimRunnable) {
+ if (mIsAnimating) {
+ // Cancel the current animation
+ if (mEnterAnimation != null) {
+ mEnterAnimation.removeAllListeners();
+ mEnterAnimation.cancel();
+ }
+
+ // Compose the animation
+ mEnterAnimation = new AnimatorSet();
+ mEnterAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Notify any callbacks
+ mCb.onEnterAnimationComplete(true);
+ // Run the given post-anim runnable
+ postAnimRunnable.run();
+ // Mark that we are no longer animating
+ mIsAnimating = false;
+ // Disable the HW Layers on the screenshot view
+ mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ }
+ });
+ mEnterAnimation.setDuration(475);
+ mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mEnterAnimation.playTogether(
+ ObjectAnimator.ofInt(this, "clipTop", 0),
+ ObjectAnimator.ofInt(this, "clipBottom", getMeasuredHeight()),
+ ObjectAnimator.ofFloat(this, "translationY", 0f),
+ ObjectAnimator.ofFloat(this, "scaleX", 1f),
+ ObjectAnimator.ofFloat(this, "scaleY", 1f)
+ );
+ mEnterAnimation.start();
+
+ return true;
+ }
+ return false;
+ }
+}
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 db398b1..8afc5b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -28,6 +28,7 @@ import android.graphics.Rect;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
@@ -44,7 +45,6 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.Set;
-
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
* to their SpaceNode bounds.
@@ -54,10 +54,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
- public void onTaskLaunching(boolean isTaskInStackBounds);
- public void onEnterAnimationTriggered();
+ public void onTaskLaunching();
+ public void onExitToHomeAnimationTriggered();
}
+ RecentsConfiguration mConfig;
+ LayoutInflater mInflater;
+
// The space partitioning root of this container
SpaceNode mBSP;
// Whether there are any tasks
@@ -67,12 +70,22 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// Recents view callbacks
RecentsViewCallbacks mCb;
- LayoutInflater mInflater;
-
public RecentsView(Context context) {
super(context);
+ }
+
+ public RecentsView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mConfig = RecentsConfiguration.getInstance();
mInflater = LayoutInflater.from(context);
- setWillNotDraw(false);
}
/** Sets the callbacks */
@@ -160,18 +173,40 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
/** Requests all task stacks to start their enter-recents animation */
- public void startOnEnterAnimation() {
- // Notify callbacks that we are starting the enter animation
- mCb.onEnterAnimationTriggered();
-
+ public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child instanceof TaskStackView) {
TaskStackView stackView = (TaskStackView) child;
- stackView.startOnEnterAnimation();
+ stackView.startEnterRecentsAnimation(ctx);
+ }
+ }
+ }
+
+ /** Requests all task stacks to start their exit-recents animation */
+ public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
+ // Handle the case when there are no views by incrementing and decrementing after all
+ // animations are started.
+ ctx.postAnimationTrigger.increment();
+
+ if (Constants.DebugFlags.App.EnableHomeTransition) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ TaskStackView stackView = (TaskStackView) child;
+ stackView.startExitToHomeAnimation(ctx);
+ }
}
}
+
+ // Handle the case when there are no views by incrementing and decrementing after all
+ // animations are started.
+ ctx.postAnimationTrigger.decrement();
+
+ // Notify of the exit animation
+ mCb.onExitToHomeAnimationTriggered();
}
/** Adds the search bar */
@@ -215,10 +250,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
// Get the search bar bounds and measure the search bar layout
- RecentsConfiguration config = RecentsConfiguration.getInstance();
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
- config.getSearchBarBounds(width, height - config.systemInsets.top, searchBarSpaceBounds);
+ mConfig.getSearchBarBounds(width, height - mConfig.systemInsets.top, searchBarSpaceBounds);
mSearchBar.measure(
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
@@ -229,9 +263,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// In addition, we give it the full height, not including the top inset or search bar space,
// since we want the tasks to render under the navigation buttons in portrait.
Rect taskStackBounds = new Rect();
- config.getTaskStackBounds(width, height, taskStackBounds);
- int childWidth = width - config.systemInsets.right;
- int childHeight = taskStackBounds.height() - config.systemInsets.top;
+ mConfig.getTaskStackBounds(width, height, taskStackBounds);
+ int childWidth = width - mConfig.systemInsets.right;
+ int childHeight = taskStackBounds.height() - mConfig.systemInsets.top;
// Measure each TaskStackView
int childCount = getChildCount();
@@ -259,23 +293,22 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
// Get the search bar bounds so that we lay it out
- RecentsConfiguration config = RecentsConfiguration.getInstance();
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
- mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
- config.systemInsets.top + searchBarSpaceBounds.top,
- config.systemInsets.left + mSearchBar.getMeasuredWidth(),
- config.systemInsets.top + mSearchBar.getMeasuredHeight());
+ mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
+ mSearchBar.layout(mConfig.systemInsets.left + searchBarSpaceBounds.left,
+ mConfig.systemInsets.top + searchBarSpaceBounds.top,
+ mConfig.systemInsets.left + mSearchBar.getMeasuredWidth(),
+ mConfig.systemInsets.top + mSearchBar.getMeasuredHeight());
}
// We offset the stack view by the left inset (if any), but lay it out under the search bar.
// In addition, we offset our stack views by the top inset and search bar height, but not
// the bottom insets because we want it to render under the navigation buttons.
Rect taskStackBounds = new Rect();
- config.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
- left += config.systemInsets.left;
- top += config.systemInsets.top + taskStackBounds.top;
+ mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
+ left += mConfig.systemInsets.left;
+ top += mConfig.systemInsets.top + taskStackBounds.top;
// Layout each child
// XXX: Based on the space node for that task view
@@ -289,6 +322,20 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
}
+ /** Notifies each task view of the user interaction. */
+ public void onUserInteraction() {
+ // Get the first stack view
+ TaskStackView stackView = null;
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ stackView = (TaskStackView) child;
+ stackView.onUserInteraction();
+ }
+ }
+ }
+
/** Focuses the next task in the first stack view */
public void focusNextTask(boolean forward) {
// Get the first stack view
@@ -324,8 +371,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
// Update the configuration with the latest system insets and trigger a relayout
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.updateSystemInsets(insets.getSystemWindowInsets());
+ mConfig.updateSystemInsets(insets.getSystemWindowInsets());
requestLayout();
return insets.consumeSystemWindowInsets(false, false, false, true);
@@ -355,56 +401,58 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
final TaskStack stack, final Task task) {
// Notify any callbacks of the launching of a new task
if (mCb != null) {
- boolean isTaskInStackBounds = false;
- if (stackView != null && tv != null) {
- isTaskInStackBounds = stackView.isTaskInStackBounds(tv);
- }
- mCb.onTaskLaunching(isTaskInStackBounds);
+ mCb.onTaskLaunching();
+ }
+
+ // Upfront the processing of the thumbnail
+ TaskViewTransform transform;
+ View sourceView = tv;
+ int offsetX = 0;
+ int offsetY = 0;
+ int stackScroll = stackView.getStackScroll();
+ if (tv == null) {
+ // If there is no actual task view, then use the stack view as the source view
+ // and then offset to the expected transform rect, but bound this to just
+ // outside the display rect (to ensure we don't animate from too far away)
+ sourceView = stackView;
+ transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
+ offsetX = transform.rect.left;
+ offsetY = Math.min(transform.rect.top, mConfig.displayRect.height());
+ } else {
+ transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
}
+ // Compute the thumbnail to scale up from
+ ActivityOptions opts = null;
+ int thumbnailWidth = transform.rect.width();
+ int thumbnailHeight = transform.rect.height();
+ if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
+ task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
+ // Resize the thumbnail to the size of the view that we are animating from
+ Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ c.drawBitmap(task.thumbnail,
+ new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()),
+ new Rect(0, 0, thumbnailWidth, thumbnailHeight), null);
+ c.setBitmap(null);
+ opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView,
+ b, offsetX, offsetY);
+ }
+
+ final ActivityOptions launchOpts = opts;
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
- TaskViewTransform transform;
- View sourceView = tv;
- int offsetX = 0;
- int offsetY = 0;
- int stackScroll = stackView.getStackScroll();
- if (tv == null) {
- // If there is no actual task view, then use the stack view as the source view
- // and then offset to the expected transform rect, but bound this to just
- // outside the display rect (to ensure we don't animate from too far away)
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- sourceView = stackView;
- transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
- offsetX = transform.rect.left;
- offsetY = Math.min(transform.rect.top, config.displayRect.height());
- } else {
- transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
- }
-
- // Compute the thumbnail to scale up from
- ActivityOptions opts = null;
- int thumbnailWidth = transform.rect.width();
- int thumbnailHeight = transform.rect.height();
- if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
- task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
- // Resize the thumbnail to the size of the view that we are animating from
- Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight,
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
- c.drawBitmap(task.thumbnail,
- new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()),
- new Rect(0, 0, thumbnailWidth, thumbnailHeight), null);
- c.setBitmap(null);
- opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView,
- b, offsetX, offsetY);
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
+ Constants.Log.App.TimeRecentsLaunchKey, "preStartActivity");
}
if (task.isActive) {
// Bring an active task to the foreground
RecentsTaskLoader.getInstance().getSystemServicesProxy()
- .moveTaskToFront(task.key.id, opts);
+ .moveTaskToFront(task.key.id, launchOpts);
} else {
// Launch the activity anew with the desired animation
Intent i = new Intent(task.key.baseIntent);
@@ -413,8 +461,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
| Intent.FLAG_ACTIVITY_NEW_TASK);
try {
UserHandle taskUser = new UserHandle(task.userId);
- if (opts != null) {
- getContext().startActivityAsUser(i, opts.toBundle(), taskUser);
+ if (launchOpts != null) {
+ getContext().startActivityAsUser(i, launchOpts.toBundle(), taskUser);
} else {
getContext().startActivityAsUser(i, taskUser);
}
@@ -426,19 +474,23 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
onTaskRemoved(task);
}
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "startActivity");
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
+ Constants.Log.App.TimeRecentsLaunchKey, "startActivity");
+ }
}
};
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "onTaskLaunched");
+ if (Console.Enabled) {
+ Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
+ Constants.Log.App.TimeRecentsLaunchKey, "onTaskLaunched");
+ }
// Launch the app right away if there is no task view, otherwise, animate the icon out first
if (tv == null) {
post(launchRunnable);
} else {
- tv.animateOnLeavingRecents(launchRunnable);
+ stackView.animateOnLaunchingTask(tv, launchRunnable);
}
}
@@ -469,6 +521,34 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
isDocument);
}
+ @Override
+ public void onTaskStackFilterTriggered() {
+ // Hide the search bar
+ if (mSearchBar != null) {
+ mSearchBar.animate()
+ .alpha(0f)
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.filteringCurrentViewsAnimDuration)
+ .withLayer()
+ .start();
+ }
+ }
+
+ @Override
+ public void onTaskStackUnfilterTriggered() {
+ // Show the search bar
+ if (mSearchBar != null) {
+ mSearchBar.animate()
+ .alpha(1f)
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.filteringNewViewsAnimDuration)
+ .withLayer()
+ .start();
+ }
+ }
+
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
new file mode 100644
index 0000000..5b17b41
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -0,0 +1,109 @@
+/*
+ * 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.systemui.recents.views;
+
+import android.app.Activity;
+import android.view.View;
+import com.android.systemui.R;
+import com.android.systemui.recents.RecentsConfiguration;
+
+/** Manages the scrims for the various system bars. */
+public class SystemBarScrimViews {
+
+ RecentsConfiguration mConfig;
+
+ View mStatusBarScrimView;
+ View mNavBarScrimView;
+
+ boolean mHasNavBarScrim;
+ boolean mShouldAnimateStatusBarScrim;
+ boolean mHasStatusBarScrim;
+ boolean mShouldAnimateNavBarScrim;
+
+ public SystemBarScrimViews(Activity activity, RecentsConfiguration config) {
+ mConfig = config;
+ mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
+ mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
+ }
+
+ /**
+ * Prepares the scrim views for animating when entering Recents. This will be called before
+ * the first draw.
+ */
+ public void prepareEnterRecentsAnimation() {
+ mHasNavBarScrim = mConfig.hasNavBarScrim();
+ mShouldAnimateNavBarScrim = mConfig.shouldAnimateNavBarScrim();
+ mHasStatusBarScrim = mConfig.hasStatusBarScrim();
+ mShouldAnimateStatusBarScrim = mConfig.shouldAnimateStatusBarScrim();
+
+ mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
+ View.VISIBLE : View.INVISIBLE);
+ mStatusBarScrimView.setVisibility(mHasStatusBarScrim && !mShouldAnimateStatusBarScrim ?
+ View.VISIBLE : View.INVISIBLE);
+ }
+
+ /**
+ * Starts animating the scrim views when entering Recents.
+ */
+ public void startEnterRecentsAnimation() {
+ if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
+ mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
+ mStatusBarScrimView.animate()
+ .translationY(0)
+ .setStartDelay(mConfig.taskBarEnterAnimDelay)
+ .setDuration(mConfig.navBarScrimEnterDuration)
+ .setInterpolator(mConfig.quintOutInterpolator)
+ .withStartAction(new Runnable() {
+ @Override
+ public void run() {
+ mStatusBarScrimView.setVisibility(View.VISIBLE);
+ }
+ })
+ .start();
+ }
+ if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
+ mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
+ mNavBarScrimView.animate()
+ .translationY(0)
+ .setStartDelay(mConfig.taskBarEnterAnimDelay)
+ .setDuration(mConfig.navBarScrimEnterDuration)
+ .setInterpolator(mConfig.quintOutInterpolator)
+ .withStartAction(new Runnable() {
+ @Override
+ public void run() {
+ mNavBarScrimView.setVisibility(View.VISIBLE);
+ }
+ })
+ .start();
+ }
+ }
+
+ /**
+ * Starts animating the scrim views when leaving Recents (either via launching a task, or
+ * going home).
+ */
+ public void startExitRecentsAnimation() {
+ if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
+ mNavBarScrimView.animate()
+ .translationY(mNavBarScrimView.getMeasuredHeight())
+ .setStartDelay(0)
+ .setDuration(mConfig.taskBarExitAnimDuration)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .start();
+ }
+ }
+}
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 c10ddd1..80f804d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -23,7 +23,11 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@@ -36,6 +40,9 @@ import com.android.systemui.recents.model.Task;
/* The task bar view */
class TaskBarView extends FrameLayout {
+
+ RecentsConfiguration mConfig;
+
Task mTask;
ImageView mDismissButton;
@@ -45,6 +52,7 @@ class TaskBarView extends FrameLayout {
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
+ Paint mLayerPaint = new Paint();
static Paint sHighlightPaint;
public TaskBarView(Context context) {
@@ -61,6 +69,7 @@ class TaskBarView extends FrameLayout {
public TaskBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mConfig = RecentsConfiguration.getInstance();
setWillNotDraw(false);
// Load the dismiss resources
@@ -70,59 +79,77 @@ class TaskBarView extends FrameLayout {
// 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.setStrokeWidth(mConfig.taskViewHighlightPx);
+ sHighlightPaint.setColor(mConfig.taskBarViewHighlightColor);
sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
sHighlightPaint.setAntiAlias(true);
}
}
@Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (Constants.DebugFlags.App.EnableTaskBarTouchEvents) {
+ return super.onTouchEvent(event);
+ }
+ // We ignore taps on the task bar except on the filter and dismiss buttons
+ return true;
+ }
+
+ @Override
protected void onFinishInflate() {
// Initialize the icon and description views
mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
mActivityDescription = (TextView) findViewById(R.id.activity_description);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+
+ // Hide the backgrounds if they are ripple drawables
+ if (!Constants.DebugFlags.App.EnableTaskFiltering) {
+ if (mApplicationIcon.getBackground() instanceof RippleDrawable) {
+ mApplicationIcon.setBackground(null);
+ }
+ }
}
@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;
+ float offset = mConfig.taskViewHighlightPx / 2f;
+ float radius = mConfig.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) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (duration > 0) {
- if (animateFromTransform != null) {
- mDismissButton.setAlpha(animateFromTransform.dismissAlpha);
- }
- mDismissButton.animate()
- .alpha(toTransform.dismissAlpha)
+ void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
+ if (duration > 0 && (mDismissButton.getVisibility() == View.VISIBLE)) {
+ ViewPropertyAnimator anim = mDismissButton.animate();
+
+ // Animate to the final state
+ if (toTransform.hasDismissAlphaChangedFrom(mDismissButton.getAlpha())) {
+ anim.alpha(toTransform.dismissAlpha)
.setStartDelay(0)
.setDuration(duration)
- .setInterpolator(config.fastOutSlowInInterpolator)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
.withLayer()
.start();
+ }
} else {
- mDismissButton.setAlpha(toTransform.dismissAlpha);
+ // Set the changed properties
+ if (toTransform.hasDismissAlphaChangedFrom(mDismissButton.getAlpha())) {
+ mDismissButton.setAlpha(toTransform.dismissAlpha);
+ }
}
- mDismissButton.invalidate();
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
}
/** Binds the bar view to the task */
void rebindToTask(Task t, boolean animate) {
- RecentsConfiguration configuration = RecentsConfiguration.getInstance();
mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
@@ -134,19 +161,14 @@ class TaskBarView extends FrameLayout {
mActivityDescription.setText(t.activityLabel);
// Try and apply the system ui tint
int tint = t.colorPrimary;
- if (Constants.DebugFlags.App.EnableTaskBarThemeColors && tint != 0) {
- setBackgroundColor(tint);
- mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint,
- configuration.taskBarViewLightTextColor, configuration.taskBarViewDarkTextColor));
- mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint,
- mLightDismissDrawable, mDarkDismissDrawable));
- } else {
- setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
- mActivityDescription.setTextColor(configuration.taskBarViewDefaultTextColor);
- }
- if (animate) {
- // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
+ if (!Constants.DebugFlags.App.EnableTaskBarThemeColors || tint == 0) {
+ tint = mConfig.taskBarViewDefaultBackgroundColor;
}
+ setBackgroundColor(tint);
+ mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint,
+ mConfig.taskBarViewLightTextColor, mConfig.taskBarViewDarkTextColor));
+ mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint,
+ mLightDismissDrawable, mDarkDismissDrawable));
}
/** Unbinds the bar view from the task */
@@ -155,4 +177,88 @@ class TaskBarView extends FrameLayout {
mApplicationIcon.setImageDrawable(null);
mActivityDescription.setText("");
}
+
+ /** 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 prepareEnterRecentsAnimation() {
+ setVisibility(View.INVISIBLE);
+ }
+
+ /** Animates this task bar as it enters recents */
+ public void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
+ // Animate the task bar of the first task view
+ setVisibility(View.VISIBLE);
+ setTranslationY(-getMeasuredHeight());
+ animate()
+ .translationY(0)
+ .setStartDelay(delay)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.taskBarEnterAnimDuration)
+ .withEndAction(postAnimRunnable)
+ .start();
+ }
+
+ /** Animates this task bar as it exits recents */
+ public void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
+ // Animate the task bar out of the first task view
+ animate()
+ .translationY(-getMeasuredHeight())
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskBarExitAnimDuration)
+ .withStartAction(preAnimRunnable)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ post(postAnimRunnable);
+ }
+ })
+ .start();
+ }
+
+ /** Animates this task bar dismiss button when launching a task. */
+ public void startLaunchTaskDismissAnimation() {
+ if (mDismissButton.getVisibility() == View.VISIBLE) {
+ mDismissButton.animate().cancel();
+ mDismissButton.animate()
+ .alpha(0f)
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.taskBarExitAnimDuration)
+ .withLayer()
+ .start();
+ }
+ }
+
+ /** Animates this task bar if the user does not interact with the stack after a certain time. */
+ public void startNoUserInteractionAnimation() {
+ mDismissButton.setVisibility(View.VISIBLE);
+ mDismissButton.setAlpha(0f);
+ mDismissButton.animate()
+ .alpha(1f)
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskBarEnterAnimDuration)
+ .withLayer()
+ .start();
+ }
+
+ /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ public void setNoUserInteractionState() {
+ if (mDismissButton.getVisibility() != View.VISIBLE) {
+ mDismissButton.animate().cancel();
+ mDismissButton.setVisibility(View.VISIBLE);
+ mDismissButton.setAlpha(1f);
+ }
+ }
+
+ /** Enable the hw layers on this task view */
+ void enableHwLayers() {
+ mDismissButton.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+ }
+
+ /** Disable the hw layers on this task view */
+ void disableHwLayers() {
+ mDismissButton.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ }
}
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 8d9f8be..1cf28b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -26,21 +26,19 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Region;
-import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.OverScroller;
import com.android.systemui.R;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.DozeTrigger;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsPackageMonitor;
import com.android.systemui.recents.RecentsTaskLoader;
+import com.android.systemui.recents.ReferenceCountedTrigger;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -60,12 +58,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
public void onTaskAppInfoLaunched(Task t);
public void onTaskRemoved(Task t);
+ public void onTaskStackFilterTriggered();
+ public void onTaskStackUnfilterTriggered();
}
+ RecentsConfiguration mConfig;
+
TaskStack mStack;
TaskStackViewTouchHandler mTouchHandler;
TaskStackViewCallbacks mCb;
ViewPool<TaskView, Task> mViewPool;
+ ArrayList<TaskViewTransform> mTaskTransforms = new ArrayList<TaskViewTransform>();
+ DozeTrigger mUIDozeTrigger;
// The various rects that define the stack view
Rect mRect = new Rect();
@@ -83,24 +87,74 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ObjectAnimator mScrollAnimator;
// Optimizations
- int mHwLayersRefCount;
+ ReferenceCountedTrigger mHwLayersTrigger;
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
boolean mAwaitingFirstLayout = true;
boolean mStartEnterAnimationRequestedAfterLayout;
+ ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
int[] mTmpVisibleRange = new int[2];
Rect mTmpRect = new Rect();
Rect mTmpRect2 = new Rect();
LayoutInflater mInflater;
+ Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
+ @Override
+ public void run() {
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ mViewPool.returnViewToPool((TaskView) getChildAt(i));
+ }
+ }
+ };
+
public TaskStackView(Context context, TaskStack stack) {
super(context);
+ mConfig = RecentsConfiguration.getInstance();
mStack = stack;
mStack.setCallbacks(this);
mScroller = new OverScroller(context);
mTouchHandler = new TaskStackViewTouchHandler(context, this);
mViewPool = new ViewPool<TaskView, Task>(context, this);
mInflater = LayoutInflater.from(context);
+ mUIDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
+ @Override
+ public void run() {
+ // Show the task bar dismiss buttons
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.startNoUserInteractionAnimation();
+ }
+ }
+ });
+ mHwLayersTrigger = new ReferenceCountedTrigger(getContext(), new Runnable() {
+ @Override
+ public void run() {
+ // Enable hw layers on each of the children
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.enableHwLayers();
+ }
+ }
+ }, new Runnable() {
+ @Override
+ public void run() {
+ // Disable hw layers on each of the children
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.disableHwLayers();
+ }
+ }
+ }, new Runnable() {
+ @Override
+ public void run() {
+ new Throwable("Invalid hw layers ref count").printStackTrace();
+ Console.logError(getContext(), "Invalid HW layers ref count");
+ }
+ });
}
/** Sets the callbacks */
@@ -118,7 +172,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
"[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
}
if (!mStackViewsDirty) {
- invalidate();
+ invalidate(mStackRect);
}
if (mAwaitingFirstLayout) {
// Skip the animation if we are awaiting first layout
@@ -129,7 +183,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackViewsDirty = true;
}
- // XXX: Optimization: Use a mapping of Task -> View
+ /** Finds the child view given a specific task */
private TaskView getChildViewForTask(Task t) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -141,12 +195,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
return null;
}
- /** Update/get the transform */
+ /** Update/get the transform (creates a new TaskViewTransform) */
public TaskViewTransform getStackTransform(int indexInStack, int stackScroll) {
TaskViewTransform transform = new TaskViewTransform();
+ return getStackTransform(indexInStack, stackScroll, transform);
+ }
+ /** Update/get the transform */
+ public TaskViewTransform getStackTransform(int indexInStack, int stackScroll,
+ TaskViewTransform transformOut) {
// Return early if we have an invalid index
- if (indexInStack < 0) return transform;
+ if (indexInStack < 0) {
+ transformOut.reset();
+ return transformOut;
+ }
// Map the items to an continuous position relative to the specified scroll
int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
@@ -163,54 +225,66 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
float scale = Math.max(minScale, Math.min(1f, minScale +
((boundedT + (numPeekCards + 1)) * scaleInc)));
float scaleYOffset = ((1f - scale) * mTaskRect.height()) / 2;
- transform.scale = scale;
+ transformOut.scale = scale;
- // Set the translation
+ // Set the y translation
if (boundedT < 0f) {
- transform.translationY = (int) ((Math.max(-numPeekCards, boundedT) /
+ transformOut.translationY = (int) ((Math.max(-numPeekCards, boundedT) /
numPeekCards) * peekHeight - scaleYOffset);
} else {
- transform.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
+ transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
}
// Set the z translation
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- int minZ = config.taskViewTranslationZMinPx;
- int incZ = config.taskViewTranslationZIncrementPx;
- transform.translationZ = (int) Math.max(minZ, minZ + ((boundedT + numPeekCards) * incZ));
+ int minZ = mConfig.taskViewTranslationZMinPx;
+ int incZ = mConfig.taskViewTranslationZIncrementPx;
+ transformOut.translationZ = (int) Math.max(minZ, minZ + ((boundedT + numPeekCards) * incZ));
// Set the alphas
- transform.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f;
+ transformOut.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f;
// Update the rect and visibility
- transform.rect.set(mTaskRect);
+ transformOut.rect.set(mTaskRect);
if (t < -(numPeekCards + 1)) {
- transform.visible = false;
+ transformOut.visible = false;
} else {
- transform.rect.offset(0, transform.translationY);
- Utilities.scaleRectAboutCenter(transform.rect, transform.scale);
- transform.visible = Rect.intersects(mRect, transform.rect);
+ transformOut.rect.offset(0, transformOut.translationY);
+ Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
+ transformOut.visible = Rect.intersects(mRect, transformOut.rect);
}
- transform.t = t;
- return transform;
+ transformOut.t = t;
+ return transformOut;
}
/**
* Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
*/
- private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
- int stackScroll,
- int[] visibleRangeOut,
- boolean boundTranslationsToRect) {
+ private void updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
+ ArrayList<Task> tasks,
+ int stackScroll,
+ int[] visibleRangeOut,
+ boolean boundTranslationsToRect) {
// XXX: Optimization: Use binary search to find the visible range
- ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
+ int taskTransformCount = taskTransforms.size();
int taskCount = tasks.size();
int firstVisibleIndex = -1;
int lastVisibleIndex = -1;
+
+ // We can reuse the task transforms where possible to reduce object allocation
+ if (taskTransformCount < taskCount) {
+ // If there are less transforms than tasks, then add as many transforms as necessary
+ for (int i = taskTransformCount; i < taskCount; i++) {
+ taskTransforms.add(new TaskViewTransform());
+ }
+ } else if (taskTransformCount > taskCount) {
+ // If there are more transforms than tasks, then just subset the transform list
+ taskTransforms.subList(0, taskCount);
+ }
+
+ // Update the stack transforms
for (int i = 0; i < taskCount; i++) {
- TaskViewTransform transform = getStackTransform(i, stackScroll);
- taskTransforms.add(transform);
+ TaskViewTransform transform = getStackTransform(i, stackScroll, taskTransforms.get(i));
if (transform.visible) {
if (firstVisibleIndex < 0) {
firstVisibleIndex = i;
@@ -226,6 +300,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
visibleRangeOut[0] = firstVisibleIndex;
visibleRangeOut[1] = lastVisibleIndex;
}
+ }
+
+ /**
+ * Gets the stack transforms of a list of tasks, and returns the visible range of tasks. This
+ * call is less optimal than calling updateStackTransforms directly.
+ */
+ private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
+ int stackScroll,
+ int[] visibleRangeOut,
+ boolean boundTranslationsToRect) {
+ ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
+ updateStackTransforms(taskTransforms, tasks, stackScroll, visibleRangeOut,
+ boundTranslationsToRect);
return taskTransforms;
}
@@ -245,14 +332,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int[] visibleRange = mTmpVisibleRange;
int stackScroll = getStackScroll();
ArrayList<Task> tasks = mStack.getTasks();
- ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
- visibleRange, false);
+ updateStackTransforms(mTaskTransforms, tasks, stackScroll, visibleRange, false);
// Update the visible state of all the tasks
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
- TaskViewTransform transform = taskTransforms.get(i);
+ TaskViewTransform transform = mTaskTransforms.get(i);
TaskView tv = getChildViewForTask(task);
if (transform.visible) {
@@ -263,7 +349,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (mStackViewsAnimationDuration > 0 && i != 0) {
int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
(visibleRange[1] + 1);
- tv.updateViewPropertiesToTaskTransform(null,
+ tv.updateViewPropertiesToTaskTransform(
getStackTransform(fromIndex, stackScroll), 0);
}
}
@@ -281,10 +367,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
- if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
+ if (taskIndex < 0 || !mTaskTransforms.get(taskIndex).visible) {
mViewPool.returnViewToPool(tv);
} else {
- tv.updateViewPropertiesToTaskTransform(null, taskTransforms.get(taskIndex),
+ tv.updateViewPropertiesToTaskTransform(mTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration);
}
}
@@ -302,11 +388,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Sets the current stack scroll */
public void setStackScroll(int value) {
mStackScroll = value;
+ mUIDozeTrigger.poke();
requestSynchronizeStackViewsWithModel();
}
/** Sets the current stack scroll without synchronizing the stack view with the model */
public void setStackScrollRaw(int value) {
mStackScroll = value;
+ mUIDozeTrigger.poke();
}
/** Sets the current stack scroll to the initial state when you first enter recents */
public void setStackScrollToInitialState() {
@@ -361,7 +449,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().fastOutSlowInInterpolator);
+ mScrollAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -473,6 +561,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ /** Animates a task view in this stack as it launches. */
+ public void animateOnLaunchingTask(TaskView tv, final Runnable r) {
+ // Hide each of the task bar dismiss buttons
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView t = (TaskView) getChildAt(i);
+ if (t == tv) {
+ t.startLaunchTaskAnimation(r, true);
+ } else {
+ t.startLaunchTaskAnimation(null, false);
+ }
+ }
+ }
+
/** Focuses the task at the specified index in the stack */
void focusTask(int taskIndex, boolean scrollToNewPosition) {
if (Console.Enabled) {
@@ -543,48 +645,31 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Enables the hw layers and increments the hw layer requirement ref count */
void addHwLayersRefCount(String reason) {
if (Console.Enabled) {
+ int refCount = mHwLayersTrigger.getCount();
Console.log(Constants.Log.UI.HwLayers,
"[TaskStackView|addHwLayersRefCount] refCount: " +
- mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
+ refCount + "->" + (refCount + 1) + " " + reason);
}
- if (mHwLayersRefCount == 0) {
- // Enable hw layers on each of the children
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.enableHwLayers();
- }
- }
- mHwLayersRefCount++;
+ mHwLayersTrigger.increment();
}
/** Decrements the hw layer requirement ref count and disables the hw layers when we don't
need them anymore. */
void decHwLayersRefCount(String reason) {
if (Console.Enabled) {
+ int refCount = mHwLayersTrigger.getCount();
Console.log(Constants.Log.UI.HwLayers,
"[TaskStackView|decHwLayersRefCount] refCount: " +
- mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
- }
- mHwLayersRefCount--;
- if (mHwLayersRefCount == 0) {
- // Disable hw layers on each of the children
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.disableHwLayers();
- }
- } else if (mHwLayersRefCount < 0) {
- new Throwable("Invalid hw layers ref count").printStackTrace();
- Console.logError(getContext(), "Invalid HW layers ref count");
+ refCount + "->" + (refCount - 1) + " " + reason);
}
+ mHwLayersTrigger.decrement();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
setStackScroll(mScroller.getCurrY());
- invalidate();
+ invalidate(mStackRect);
// If we just finished scrolling, then disable the hw layers
if (mScroller.isFinished()) {
@@ -616,7 +701,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (Constants.DebugFlags.App.EnableTaskStackClipping) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
TaskView tv = (TaskView) child;
TaskView nextTv = null;
TaskView tmpTv = null;
@@ -632,13 +716,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Clip against the next view (if we aren't animating its alpha)
- if (nextTv != null && nextTv.getAlpha() == 1f) {
+ if (nextTv != null) {
Rect curRect = tv.getClippingRect(mTmpRect);
Rect nextRect = nextTv.getClippingRect(mTmpRect2);
// The hit rects are relative to the task view, which needs to be offset by
// the system bar height
- curRect.offset(0, config.systemInsets.top);
- nextRect.offset(0, config.systemInsets.top);
+ curRect.offset(0, mConfig.systemInsets.top);
+ nextRect.offset(0, mConfig.systemInsets.top);
// Compute the clip region
Region clipRegion = new Region();
clipRegion.op(curRect, Region.Op.UNION);
@@ -660,7 +744,6 @@ 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);
@@ -668,8 +751,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackRect.left += insetLeft;
mStackRect.bottom -= insetBottom;
- int widthPadding = (int) (config.taskStackWidthPaddingPct * mStackRect.width());
- int heightPadding = config.taskStackTopPaddingPx;
+ int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width());
+ int heightPadding = mConfig.taskStackTopPaddingPx;
if (Constants.DebugFlags.App.EnableSearchLayout) {
mStackRect.top += heightPadding;
mStackRect.left += widthPadding;
@@ -707,10 +790,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Compute our stack/task rects
- RecentsConfiguration config = RecentsConfiguration.getInstance();
Rect taskStackBounds = new Rect();
- config.getTaskStackBounds(width, height, taskStackBounds);
- computeRects(width, height, taskStackBounds.left, config.systemInsets.bottom);
+ mConfig.getTaskStackBounds(width, height, taskStackBounds);
+ computeRects(width, height, taskStackBounds.left, mConfig.systemInsets.bottom);
// Debug logging
if (Constants.Log.UI.MeasureAndLayout) {
@@ -768,48 +850,73 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
if (mAwaitingFirstLayout) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
+ // Mark that we have completely the first layout
+ mAwaitingFirstLayout = false;
- // 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);
- }
+ // Start dozing
+ mUIDozeTrigger.startDozing();
// Prepare the first view for its enter animation
- if (config.launchedWithThumbnailAnimation) {
- TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
- if (tv != null) {
- tv.prepareAnimateOnEnterRecents();
- }
+ int offsetTopAlign = -mTaskRect.top;
+ int offscreenY = mRect.bottom - (mTaskRect.top - mRect.top);
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.prepareEnterRecentsAnimation((i == (getChildCount() - 1)), offsetTopAlign,
+ offscreenY, mTaskRect);
}
- // 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();
+ startEnterRecentsAnimation(mStartEnterAnimationContext);
+ mStartEnterAnimationRequestedAfterLayout = false;
+ mStartEnterAnimationContext = null;
+ }
+
+ // Update the focused task index to be the next item to the top task
+ if (mConfig.launchedWithAltTab) {
+ focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
}
}
}
/** Requests this task stacks to start it's enter-recents animation */
- public void startOnEnterAnimation() {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (!config.launchedWithThumbnailAnimation) return;
-
+ public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
// If we are still waiting to layout, then just defer until then
if (mAwaitingFirstLayout) {
mStartEnterAnimationRequestedAfterLayout = true;
+ mStartEnterAnimationContext = ctx;
return;
}
- // Animate the task bar of the first task view
- TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
- if (tv != null) {
- tv.animateOnEnterRecents();
+ // Animate all the task views into view
+ ctx.taskRect = mTaskRect;
+ ctx.stackRectSansPeek = mStackRectSansPeek;
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) getChildAt(i);
+ TaskViewTransform transform = getStackTransform(mStack.indexOfTask(tv.getTask()),
+ getStackScroll());
+ ctx.stackViewIndex = i;
+ ctx.stackViewCount = childCount;
+ ctx.isFrontMost = (i == (getChildCount() - 1));
+ ctx.transform = transform;
+ tv.startEnterRecentsAnimation(ctx);
+ }
+ }
+
+ /** Requests this task stacks to start it's exit-recents animation. */
+ public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
+ // Animate all the task views into view
+ ctx.offscreenTranslationY = mRect.bottom - (mTaskRect.top - mRect.top);
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.startExitToHomeAnimation(ctx);
}
+
+ // Add a runnable to the post animation ref counter to clear all the views
+ ctx.postAnimationTrigger.addLastDecrementRunnable(mReturnAllViewsToPoolRunnable);
}
@Override
@@ -822,6 +929,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
return isTransformedTouchPointInView(x, y, child, null);
}
+ /** Pokes the dozer on user interaction. */
+ void onUserInteraction() {
+ // Poke the doze trigger if it is dozing
+ mUIDozeTrigger.poke();
+ }
+
/**** TaskStackCallbacks Implementation ****/
@Override
@@ -833,15 +946,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void onStackTaskRemoved(TaskStack stack, Task t) {
// Remove the view associated with this task, we can't rely on updateTransforms
// to work here because the task is no longer in the list
- int childCount = getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- TaskView tv = (TaskView) getChildAt(i);
- if (tv.getTask() == t) {
- mViewPool.returnViewToPool(tv);
- break;
- }
+ TaskView tv = getChildViewForTask(t);
+ if (tv != null) {
+ mViewPool.returnViewToPool(tv);
}
+ // Notify the callback that we've removed the task and it can clean up after it
+ mCb.onTaskRemoved(t);
+
// Update the min/max scroll and animate other task views into their new positions
updateMinMaxScroll(true);
int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
@@ -870,11 +982,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int getExitTransformsForFilterAnimation(ArrayList<Task> curTasks,
ArrayList<TaskViewTransform> curTaskTransforms,
ArrayList<Task> tasks, ArrayList<TaskViewTransform> taskTransforms,
- HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut,
- ArrayList<TaskView> childrenToRemoveOut,
- RecentsConfiguration config) {
+ HashMap<TaskView, TaskViewTransform> childViewTransformsOut,
+ ArrayList<TaskView> childrenToRemoveOut) {
// Animate all of the existing views out of view (if they are not in the visible range in
// the new stack) or to their final positions in the new stack
+ int offset = 0;
int movement = 0;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -899,10 +1011,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
movement = Math.max(movement, Math.abs(toTransform.translationY -
(int) tv.getTranslationY()));
}
- childViewTransformsOut.put(tv, new Pair(0, toTransform));
+
+ toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay;
+ childViewTransformsOut.put(tv, toTransform);
+ offset++;
}
- return Utilities.calculateTranslationAnimationDuration(movement,
- config.filteringCurrentViewsMinAnimDuration);
+ return mConfig.filteringCurrentViewsAnimDuration;
}
/**
@@ -911,8 +1025,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
*/
int getEnterTransformsForFilterAnimation(ArrayList<Task> tasks,
ArrayList<TaskViewTransform> taskTransforms,
- HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut,
- RecentsConfiguration config) {
+ HashMap<TaskView, TaskViewTransform> childViewTransformsOut) {
int offset = 0;
int movement = 0;
int taskCount = tasks.size();
@@ -928,11 +1041,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compose a new transform to fade and slide the new task in
TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
- tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+ tv.updateViewPropertiesToTaskTransform(fromTransform, 0);
- int startDelay = offset *
- Constants.Values.TaskStackView.FilterStartDelay;
- childViewTransformsOut.put(tv, new Pair(startDelay, toTransform));
+ toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay;
+ childViewTransformsOut.put(tv, toTransform);
// Use the movement of the new views to calculate the duration of the animation
movement = Math.max(movement,
@@ -941,8 +1053,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
}
- return Utilities.calculateTranslationAnimationDuration(movement,
- config.filteringNewViewsMinAnimDuration);
+ return mConfig.filteringNewViewsAnimDuration;
}
/** Orchestrates the animations of the current child views and any new views. */
@@ -950,31 +1061,28 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ArrayList<TaskViewTransform> curTaskTransforms,
final ArrayList<Task> tasks,
final ArrayList<TaskViewTransform> taskTransforms) {
- final RecentsConfiguration config = RecentsConfiguration.getInstance();
-
// Calculate the transforms to animate out all the existing views if they are not in the
// new visible range (or to their final positions in the stack if they are)
final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
- final HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransforms =
- new HashMap<TaskView, Pair<Integer, TaskViewTransform>>();
+ final HashMap<TaskView, TaskViewTransform> childViewTransforms =
+ new HashMap<TaskView, TaskViewTransform>();
int duration = getExitTransformsForFilterAnimation(curTasks, curTaskTransforms, tasks,
- taskTransforms, childViewTransforms, childrenToRemove, config);
+ taskTransforms, childViewTransforms, childrenToRemove);
// If all the current views are in the visible range of the new stack, then don't wait for
// views to animate out and animate all the new views into their place
final boolean unifyNewViewAnimation = childrenToRemove.isEmpty();
if (unifyNewViewAnimation) {
int inDuration = getEnterTransformsForFilterAnimation(tasks, taskTransforms,
- childViewTransforms, config);
+ childViewTransforms);
duration = Math.max(duration, inDuration);
}
// Animate all the views to their final transforms
for (final TaskView tv : childViewTransforms.keySet()) {
- Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv);
+ TaskViewTransform t = childViewTransforms.get(tv);
tv.animate().cancel();
tv.animate()
- .setStartDelay(t.first)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -989,17 +1097,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For views that are not already visible, animate them in
childViewTransforms.clear();
int duration = getEnterTransformsForFilterAnimation(tasks,
- taskTransforms, childViewTransforms, config);
+ taskTransforms, childViewTransforms);
for (final TaskView tv : childViewTransforms.keySet()) {
- Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv);
- tv.animate().setStartDelay(t.first);
- tv.updateViewPropertiesToTaskTransform(null, t.second, duration);
+ TaskViewTransform t = childViewTransforms.get(tv);
+ tv.updateViewPropertiesToTaskTransform(t, duration);
}
}
}
}
});
- tv.updateViewPropertiesToTaskTransform(null, t.second, duration);
+ tv.updateViewPropertiesToTaskTransform(t, duration);
}
}
@@ -1026,6 +1133,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Animate
doFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
+
+ // Notify any callbacks
+ mCb.onTaskStackFilterTriggered();
}
@Override
@@ -1049,6 +1159,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Clear the saved vars
mStashedScroll = 0;
+
+ // Notify any callbacks
+ mCb.onTaskStackUnfilterTriggered();
}
/**** ViewPoolConsumer Implementation ****/
@@ -1095,7 +1208,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Request that this tasks's data be filled
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
loader.loadTaskData(task);
-
// Find the index where this task should be placed in the children
int insertIndex = -1;
int childCount = getChildCount();
@@ -1111,6 +1223,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// but just in case, re-enable it here
tv.setClipViewInStack(true);
+ // If the doze trigger has already fired, then update the state for this task view
+ if (mUIDozeTrigger.hasTriggered()) {
+ tv.setNoUserInteractionState();
+ }
+
// Add/attach the view to the hierarchy
if (Console.Enabled) {
Console.log(Constants.Log.ViewPool.PoolCallbacks, " [TaskStackView|insertIndex]",
@@ -1127,7 +1244,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Enable hw layers on this view if hw layers are enabled on the stack
- if (mHwLayersRefCount > 0) {
+ if (mHwLayersTrigger.getCount() > 0) {
tv.enableHwLayers();
}
}
@@ -1172,8 +1289,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Task task = tv.getTask();
// Remove the task from the view
mStack.removeTask(task);
- // Notify the callback that we've removed the task and it can clean up after it
- mCb.onTaskRemoved(task);
}
/**** View.OnClickListener Implementation ****/
@@ -1187,6 +1302,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
task + " cb: " + mCb);
}
+ // Cancel any doze triggers
+ mUIDozeTrigger.stopDozing();
+
if (mCb != null) {
mCb.onTaskLaunched(this, tv, mStack, task);
}
@@ -1196,7 +1314,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void onComponentRemoved(Set<ComponentName> cns) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
@@ -1205,7 +1322,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = getChildViewForTask(t);
if (tv != null) {
// For visible children, defer removing the task until after the animation
- tv.animateRemoval(new Runnable() {
+ tv.startDeleteTaskAnimation(new Runnable() {
@Override
public void run() {
mStack.removeTask(t);
@@ -1218,393 +1335,4 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
}
-}
-
-/* Handles touch events */
-class TaskStackViewTouchHandler implements SwipeHelper.Callback {
- static int INACTIVE_POINTER_ID = -1;
-
- TaskStackView mSv;
- VelocityTracker mVelocityTracker;
-
- boolean mIsScrolling;
-
- int mInitialMotionX, mInitialMotionY;
- int mLastMotionX, mLastMotionY;
- int mActivePointerId = INACTIVE_POINTER_ID;
- TaskView mActiveTaskView = null;
-
- int mTotalScrollMotion;
- int mMinimumVelocity;
- int mMaximumVelocity;
- // The scroll touch slop is used to calculate when we start scrolling
- int mScrollTouchSlop;
- // The page touch slop is used to calculate when we start swiping
- float mPagingTouchSlop;
-
- SwipeHelper mSwipeHelper;
- boolean mInterceptedBySwipeHelper;
-
- public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
- ViewConfiguration configuration = ViewConfiguration.get(context);
- mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
- mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mScrollTouchSlop = configuration.getScaledTouchSlop();
- mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
- mSv = sv;
-
-
- float densityScale = context.getResources().getDisplayMetrics().density;
- mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
- mSwipeHelper.setMinAlpha(1f);
- }
-
- /** Velocity tracker helpers */
- void initOrResetVelocityTracker() {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- } else {
- mVelocityTracker.clear();
- }
- }
- void initVelocityTrackerIfNotExists() {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- }
- void recycleVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- /** Returns the view at the specified coordinates */
- TaskView findViewAtPoint(int x, int y) {
- int childCount = mSv.getChildCount();
- for (int i = childCount - 1; i >= 0; i--) {
- TaskView tv = (TaskView) mSv.getChildAt(i);
- if (tv.getVisibility() == View.VISIBLE) {
- if (mSv.isTransformedTouchPointInView(x, y, tv)) {
- return tv;
- }
- }
- }
- return null;
- }
-
- /** Touch preprocessing for handling below */
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|interceptTouchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
-
- // Return early if we have no children
- boolean hasChildren = (mSv.getChildCount() > 0);
- if (!hasChildren) {
- return false;
- }
-
- // Pass through to swipe helper if we are swiping
- mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
- if (mInterceptedBySwipeHelper) {
- return true;
- }
-
- boolean wasScrolling = !mSv.mScroller.isFinished() ||
- (mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
- int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- // Save the touch down info
- mInitialMotionX = mLastMotionX = (int) ev.getX();
- mInitialMotionY = mLastMotionY = (int) ev.getY();
- mActivePointerId = ev.getPointerId(0);
- mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
- // Stop the current scroll if it is still flinging
- mSv.abortScroller();
- mSv.abortBoundScrollAnimation();
- // Initialize the velocity tracker
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Check if the scroller is finished yet
- mIsScrolling = !mSv.mScroller.isFinished();
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- if (mActivePointerId == INACTIVE_POINTER_ID) break;
-
- int activePointerIndex = ev.findPointerIndex(mActivePointerId);
- int y = (int) ev.getY(activePointerIndex);
- int x = (int) ev.getX(activePointerIndex);
- if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
- // Save the touch move info
- mIsScrolling = true;
- // Initialize the velocity tracker if necessary
- initVelocityTrackerIfNotExists();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount("stackScroll");
- }
-
- mLastMotionX = x;
- mLastMotionY = y;
- break;
- }
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- // Animate the scroll back if we've cancelled
- mSv.animateBoundScroll();
- // Disable HW layers
- if (mIsScrolling) {
- mSv.decHwLayersRefCount("stackScroll");
- }
- // Reset the drag state and the velocity tracker
- mIsScrolling = false;
- mActivePointerId = INACTIVE_POINTER_ID;
- mActiveTaskView = null;
- mTotalScrollMotion = 0;
- recycleVelocityTracker();
- break;
- }
- }
-
- return wasScrolling || mIsScrolling;
- }
-
- /** Handles touch events once we have intercepted them */
- public boolean onTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|touchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
-
- // Short circuit if we have no children
- boolean hasChildren = (mSv.getChildCount() > 0);
- if (!hasChildren) {
- return false;
- }
-
- // Pass through to swipe helper if we are swiping
- if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
- return true;
- }
-
- // Update the velocity tracker
- initVelocityTrackerIfNotExists();
- mVelocityTracker.addMovement(ev);
-
- int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- // Save the touch down info
- mInitialMotionX = mLastMotionX = (int) ev.getX();
- mInitialMotionY = mLastMotionY = (int) ev.getY();
- mActivePointerId = ev.getPointerId(0);
- mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
- // Stop the current scroll if it is still flinging
- mSv.abortScroller();
- mSv.abortBoundScrollAnimation();
- // Initialize the velocity tracker
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- break;
- }
- case MotionEvent.ACTION_POINTER_DOWN: {
- final int index = ev.getActionIndex();
- mActivePointerId = ev.getPointerId(index);
- mLastMotionX = (int) ev.getX(index);
- mLastMotionY = (int) ev.getY(index);
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- if (mActivePointerId == INACTIVE_POINTER_ID) break;
-
- int activePointerIndex = ev.findPointerIndex(mActivePointerId);
- int x = (int) ev.getX(activePointerIndex);
- int y = (int) ev.getY(activePointerIndex);
- int yTotal = Math.abs(y - mInitialMotionY);
- int deltaY = mLastMotionY - y;
- if (!mIsScrolling) {
- if (yTotal > mScrollTouchSlop) {
- mIsScrolling = true;
- // Initialize the velocity tracker
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- // Enable HW layers
- mSv.addHwLayersRefCount("stackScroll");
- }
- }
- if (mIsScrolling) {
- int curStackScroll = mSv.getStackScroll();
- int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
- if (overScrollAmount != 0) {
- // Bound the overscroll to a fixed amount, and inversely scale the y-movement
- // relative to how close we are to the max overscroll
- float maxOverScroll = mSv.mTaskRect.height() / 3f;
- deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
- / maxOverScroll)));
- }
- mSv.setStackScroll(curStackScroll + deltaY);
- if (mSv.isScrollOutOfBounds()) {
- mVelocityTracker.clear();
- }
- }
- mLastMotionX = x;
- mLastMotionY = y;
- mTotalScrollMotion += Math.abs(deltaY);
- break;
- }
- case MotionEvent.ACTION_UP: {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
- if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
- // Enable HW layers on the stack
- mSv.addHwLayersRefCount("flingScroll");
- // XXX: Make this animation a function of the velocity AND distance
- int overscrollRange = (int) (Math.min(1f,
- Math.abs((float) velocity / mMaximumVelocity)) *
- Constants.Values.TaskStackView.TaskStackOverscrollRange);
-
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|fling]",
- "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
- " maxVelocity: " + mMaximumVelocity +
- " overscrollRange: " + overscrollRange,
- Console.AnsiGreen);
- }
-
- // Fling scroll
- mSv.mScroller.fling(0, mSv.getStackScroll(),
- 0, -velocity,
- 0, 0,
- mSv.mMinScroll, mSv.mMaxScroll,
- 0, overscrollRange);
- // Invalidate to kick off computeScroll
- mSv.invalidate();
- } else if (mSv.isScrollOutOfBounds()) {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll();
- }
-
- if (mIsScrolling) {
- // Disable HW layers
- mSv.decHwLayersRefCount("stackScroll");
- }
- mActivePointerId = INACTIVE_POINTER_ID;
- mIsScrolling = false;
- mTotalScrollMotion = 0;
- recycleVelocityTracker();
- break;
- }
- case MotionEvent.ACTION_POINTER_UP: {
- int pointerIndex = ev.getActionIndex();
- int pointerId = ev.getPointerId(pointerIndex);
- if (pointerId == mActivePointerId) {
- // Select a new active pointer id and reset the motion state
- final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
- mActivePointerId = ev.getPointerId(newPointerIndex);
- mLastMotionX = (int) ev.getX(newPointerIndex);
- mLastMotionY = (int) ev.getY(newPointerIndex);
- mVelocityTracker.clear();
- }
- break;
- }
- case MotionEvent.ACTION_CANCEL: {
- if (mIsScrolling) {
- // Disable HW layers
- mSv.decHwLayersRefCount("stackScroll");
- }
- if (mSv.isScrollOutOfBounds()) {
- // Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll();
- }
- mActivePointerId = INACTIVE_POINTER_ID;
- mIsScrolling = false;
- mTotalScrollMotion = 0;
- recycleVelocityTracker();
- break;
- }
- }
- return true;
- }
-
- /**** SwipeHelper Implementation ****/
-
- @Override
- public View getChildAtPosition(MotionEvent ev) {
- return findViewAtPoint((int) ev.getX(), (int) ev.getY());
- }
-
- @Override
- public boolean canChildBeDismissed(View v) {
- return true;
- }
-
- @Override
- public void onBeginDrag(View v) {
- // Enable HW layers
- mSv.addHwLayersRefCount("swipeBegin");
- // Disable clipping with the stack while we are swiping
- TaskView tv = (TaskView) v;
- tv.setClipViewInStack(false);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
- }
-
- @Override
- public void onSwipeChanged(View v, float delta) {
- // Do nothing
- }
-
- @Override
- public void onChildDismissed(View v) {
- TaskView tv = (TaskView) v;
- mSv.onTaskDismissed(tv);
-
- // Re-enable clipping with the stack (we will reuse this view)
- tv.setClipViewInStack(true);
-
- // Disable HW layers
- mSv.decHwLayersRefCount("swipeComplete");
- }
-
- @Override
- public void onSnapBackCompleted(View v) {
- // Re-enable clipping with the stack
- TaskView tv = (TaskView) v;
- tv.setClipViewInStack(true);
- }
-
- @Override
- public void onDragCancelled(View v) {
- // Disable HW layers
- mSv.decHwLayersRefCount("swipeCancelled");
- }
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
new file mode 100644
index 0000000..d2f18ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -0,0 +1,415 @@
+/*
+ * 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.systemui.recents.views;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewParent;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
+
+/* Handles touch events for a TaskStackView. */
+class TaskStackViewTouchHandler implements SwipeHelper.Callback {
+ static int INACTIVE_POINTER_ID = -1;
+
+ TaskStackView mSv;
+ VelocityTracker mVelocityTracker;
+
+ boolean mIsScrolling;
+
+ int mInitialMotionX, mInitialMotionY;
+ int mLastMotionX, mLastMotionY;
+ int mActivePointerId = INACTIVE_POINTER_ID;
+ TaskView mActiveTaskView = null;
+
+ int mTotalScrollMotion;
+ int mMinimumVelocity;
+ int mMaximumVelocity;
+ // The scroll touch slop is used to calculate when we start scrolling
+ int mScrollTouchSlop;
+ // The page touch slop is used to calculate when we start swiping
+ float mPagingTouchSlop;
+
+ SwipeHelper mSwipeHelper;
+ boolean mInterceptedBySwipeHelper;
+
+ public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
+ ViewConfiguration configuration = ViewConfiguration.get(context);
+ mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+ mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ mScrollTouchSlop = configuration.getScaledTouchSlop();
+ mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
+ mSv = sv;
+
+
+ float densityScale = context.getResources().getDisplayMetrics().density;
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
+ mSwipeHelper.setMinAlpha(1f);
+ }
+
+ /** Velocity tracker helpers */
+ void initOrResetVelocityTracker() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ } else {
+ mVelocityTracker.clear();
+ }
+ }
+ void initVelocityTrackerIfNotExists() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ }
+ void recycleVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ /** Returns the view at the specified coordinates */
+ TaskView findViewAtPoint(int x, int y) {
+ int childCount = mSv.getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) mSv.getChildAt(i);
+ if (tv.getVisibility() == View.VISIBLE) {
+ if (mSv.isTransformedTouchPointInView(x, y, tv)) {
+ return tv;
+ }
+ }
+ }
+ return null;
+ }
+
+ /** Touch preprocessing for handling below */
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|interceptTouchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
+
+ // Return early if we have no children
+ boolean hasChildren = (mSv.getChildCount() > 0);
+ if (!hasChildren) {
+ return false;
+ }
+
+ // Pass through to swipe helper if we are swiping
+ mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
+ if (mInterceptedBySwipeHelper) {
+ return true;
+ }
+
+ boolean wasScrolling = !mSv.mScroller.isFinished() ||
+ (mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
+ int action = ev.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ // Save the touch down info
+ mInitialMotionX = mLastMotionX = (int) ev.getX();
+ mInitialMotionY = mLastMotionY = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
+ mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
+ // Stop the current scroll if it is still flinging
+ mSv.abortScroller();
+ mSv.abortBoundScrollAnimation();
+ // Initialize the velocity tracker
+ initOrResetVelocityTracker();
+ mVelocityTracker.addMovement(ev);
+ // Check if the scroller is finished yet
+ mIsScrolling = !mSv.mScroller.isFinished();
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (mActivePointerId == INACTIVE_POINTER_ID) break;
+
+ int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+ int y = (int) ev.getY(activePointerIndex);
+ int x = (int) ev.getX(activePointerIndex);
+ if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+ // Save the touch move info
+ mIsScrolling = true;
+ // Initialize the velocity tracker if necessary
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ // Enable HW layers
+ mSv.addHwLayersRefCount("stackScroll");
+ }
+
+ mLastMotionX = x;
+ mLastMotionY = y;
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP: {
+ // Animate the scroll back if we've cancelled
+ mSv.animateBoundScroll();
+ // Disable HW layers
+ if (mIsScrolling) {
+ mSv.decHwLayersRefCount("stackScroll");
+ }
+ // Reset the drag state and the velocity tracker
+ mIsScrolling = false;
+ mActivePointerId = INACTIVE_POINTER_ID;
+ mActiveTaskView = null;
+ mTotalScrollMotion = 0;
+ recycleVelocityTracker();
+ break;
+ }
+ }
+
+ return wasScrolling || mIsScrolling;
+ }
+
+ /** Handles touch events once we have intercepted them */
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|touchEvent]",
+ Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+ }
+
+ // Short circuit if we have no children
+ boolean hasChildren = (mSv.getChildCount() > 0);
+ if (!hasChildren) {
+ return false;
+ }
+
+ // Pass through to swipe helper if we are swiping
+ if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
+ return true;
+ }
+
+ // Update the velocity tracker
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+
+ int action = ev.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ // Save the touch down info
+ mInitialMotionX = mLastMotionX = (int) ev.getX();
+ mInitialMotionY = mLastMotionY = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
+ mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
+ // Stop the current scroll if it is still flinging
+ mSv.abortScroller();
+ mSv.abortBoundScrollAnimation();
+ // Initialize the velocity tracker
+ initOrResetVelocityTracker();
+ mVelocityTracker.addMovement(ev);
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ break;
+ }
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ mActivePointerId = ev.getPointerId(index);
+ mLastMotionX = (int) ev.getX(index);
+ mLastMotionY = (int) ev.getY(index);
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (mActivePointerId == INACTIVE_POINTER_ID) break;
+
+ int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+ int x = (int) ev.getX(activePointerIndex);
+ int y = (int) ev.getY(activePointerIndex);
+ int yTotal = Math.abs(y - mInitialMotionY);
+ int deltaY = mLastMotionY - y;
+ if (!mIsScrolling) {
+ if (yTotal > mScrollTouchSlop) {
+ mIsScrolling = true;
+ // Initialize the velocity tracker
+ initOrResetVelocityTracker();
+ mVelocityTracker.addMovement(ev);
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ // Enable HW layers
+ mSv.addHwLayersRefCount("stackScroll");
+ }
+ }
+ if (mIsScrolling) {
+ int curStackScroll = mSv.getStackScroll();
+ int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
+ if (overScrollAmount != 0) {
+ // Bound the overscroll to a fixed amount, and inversely scale the y-movement
+ // relative to how close we are to the max overscroll
+ float maxOverScroll = mSv.mTaskRect.height() / 3f;
+ deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
+ / maxOverScroll)));
+ }
+ mSv.setStackScroll(curStackScroll + deltaY);
+ if (mSv.isScrollOutOfBounds()) {
+ mVelocityTracker.clear();
+ }
+ }
+ mLastMotionX = x;
+ mLastMotionY = y;
+ mTotalScrollMotion += Math.abs(deltaY);
+ break;
+ }
+ case MotionEvent.ACTION_UP: {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+ if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
+ // Enable HW layers on the stack
+ mSv.addHwLayersRefCount("flingScroll");
+ // XXX: Make this animation a function of the velocity AND distance
+ int overscrollRange = (int) (Math.min(1f,
+ Math.abs((float) velocity / mMaximumVelocity)) *
+ Constants.Values.TaskStackView.TaskStackOverscrollRange);
+
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.TouchEvents,
+ "[TaskStackViewTouchHandler|fling]",
+ "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
+ " maxVelocity: " + mMaximumVelocity +
+ " overscrollRange: " + overscrollRange,
+ Console.AnsiGreen);
+ }
+
+ // Fling scroll
+ mSv.mScroller.fling(0, mSv.getStackScroll(),
+ 0, -velocity,
+ 0, 0,
+ mSv.mMinScroll, mSv.mMaxScroll,
+ 0, overscrollRange);
+ // Invalidate to kick off computeScroll
+ mSv.invalidate(mSv.mStackRect);
+ } else if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll();
+ }
+
+ if (mIsScrolling) {
+ // Disable HW layers
+ mSv.decHwLayersRefCount("stackScroll");
+ }
+ mActivePointerId = INACTIVE_POINTER_ID;
+ mIsScrolling = false;
+ mTotalScrollMotion = 0;
+ recycleVelocityTracker();
+ break;
+ }
+ case MotionEvent.ACTION_POINTER_UP: {
+ int pointerIndex = ev.getActionIndex();
+ int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // Select a new active pointer id and reset the motion state
+ final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ mLastMotionX = (int) ev.getX(newPointerIndex);
+ mLastMotionY = (int) ev.getY(newPointerIndex);
+ mVelocityTracker.clear();
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL: {
+ if (mIsScrolling) {
+ // Disable HW layers
+ mSv.decHwLayersRefCount("stackScroll");
+ }
+ if (mSv.isScrollOutOfBounds()) {
+ // Animate the scroll back into bounds
+ // XXX: Make this animation a function of the velocity OR distance
+ mSv.animateBoundScroll();
+ }
+ mActivePointerId = INACTIVE_POINTER_ID;
+ mIsScrolling = false;
+ mTotalScrollMotion = 0;
+ recycleVelocityTracker();
+ break;
+ }
+ }
+ return true;
+ }
+
+ /**** SwipeHelper Implementation ****/
+
+ @Override
+ public View getChildAtPosition(MotionEvent ev) {
+ return findViewAtPoint((int) ev.getX(), (int) ev.getY());
+ }
+
+ @Override
+ public boolean canChildBeDismissed(View v) {
+ return true;
+ }
+
+ @Override
+ public void onBeginDrag(View v) {
+ // Enable HW layers
+ mSv.addHwLayersRefCount("swipeBegin");
+ // Disable clipping with the stack while we are swiping
+ TaskView tv = (TaskView) v;
+ tv.setClipViewInStack(false);
+ // Disallow parents from intercepting touch events
+ final ViewParent parent = mSv.getParent();
+ if (parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ @Override
+ public void onSwipeChanged(View v, float delta) {
+ // Do nothing
+ }
+
+ @Override
+ public void onChildDismissed(View v) {
+ TaskView tv = (TaskView) v;
+ mSv.onTaskDismissed(tv);
+
+ // Re-enable clipping with the stack (we will reuse this view)
+ tv.setClipViewInStack(true);
+
+ // Disable HW layers
+ mSv.decHwLayersRefCount("swipeComplete");
+ }
+
+ @Override
+ public void onSnapBackCompleted(View v) {
+ // Re-enable clipping with the stack
+ TaskView tv = (TaskView) v;
+ tv.setClipViewInStack(true);
+ }
+
+ @Override
+ public void onDragCancelled(View v) {
+ // Disable HW layers
+ mSv.decHwLayersRefCount("swipeCancelled");
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index 8a9250a..c2b2094 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -17,15 +17,23 @@
package com.android.systemui.recents.views;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.ImageView;
import com.android.systemui.recents.model.Task;
/** The task thumbnail view */
public class TaskThumbnailView extends ImageView {
+
Task mTask;
+ // Task bar clipping
+ Rect mClipRect;
+ boolean mClipTaskBar = true;
+
public TaskThumbnailView(Context context) {
this(context, null);
}
@@ -43,14 +51,42 @@ public class TaskThumbnailView extends ImageView {
setScaleType(ScaleType.FIT_XY);
}
+ @Override
+ public void draw(Canvas canvas) {
+ if (mClipTaskBar && (mClipRect != null)) {
+ int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ canvas.clipRect(mClipRect);
+ super.draw(canvas);
+ canvas.restoreToCount(restoreCount);
+ } else {
+ super.draw(canvas);
+ }
+ }
+
+ /** Updates the clip rect based on the given task bar. */
+ void updateTaskBarClip(View taskBar) {
+ // If mClipTaskBar is unset first, then we don't bother setting mTaskBar
+ if (mClipTaskBar) {
+ int top = (int) Math.max(0, taskBar.getTranslationY() +
+ taskBar.getMeasuredHeight() - 1);
+ mClipRect = new Rect(0, top, getMeasuredWidth(), getMeasuredHeight());
+ invalidate(0, 0, taskBar.getMeasuredWidth(), taskBar.getMeasuredHeight() + 1);
+ }
+ }
+
+ /** Disables the task bar clipping. */
+ void disableClipTaskBarView() {
+ mClipTaskBar = false;
+ if (mClipRect != null) {
+ invalidate(0, 0, mClipRect.width(), mClipRect.top);
+ }
+ }
+
/** Binds the thumbnail view to the task */
void rebindToTask(Task t, boolean animate) {
mTask = t;
if (t.thumbnail != null) {
setImageBitmap(t.thumbnail);
- if (animate) {
- // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
- }
}
}
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 5df5e4d..cfba74c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,11 +16,13 @@
package com.android.systemui.recents.views;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
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;
@@ -28,9 +30,11 @@ import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewPropertyAnimator;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.Task;
@@ -45,10 +49,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
public void onTaskAppInfoClicked(TaskView tv);
public void onTaskFocused(TaskView tv);
public void onTaskDismissed(TaskView tv);
-
- // public void onTaskViewReboundToTask(TaskView tv, Task t);
}
+ RecentsConfiguration mConfig;
+
int mDim;
int mMaxDim;
TimeInterpolator mDimInterpolator = new AccelerateInterpolator();
@@ -59,11 +63,34 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
boolean mClipViewInStack;
Point mLastTouchDown = new Point();
Path mRoundedRectClipPath = new Path();
+ Rect mTmpRect = new Rect();
+ Paint mLayerPaint = new Paint();
TaskThumbnailView mThumbnailView;
TaskBarView mBarView;
TaskViewCallbacks mCb;
+ // Optimizations
+ ValueAnimator.AnimatorUpdateListener mUpdateDimListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateDimOverlayFromScale();
+ }
+ };
+ Runnable mEnableThumbnailClip = new Runnable() {
+ @Override
+ public void run() {
+ mThumbnailView.updateTaskBarClip(mBarView);
+ }
+ };
+ Runnable mDisableThumbnailClip = new Runnable() {
+ @Override
+ public void run() {
+ mThumbnailView.disableClipTaskBarView();
+ }
+ };
+
public TaskView(Context context) {
this(context, null);
@@ -79,20 +106,21 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mConfig = RecentsConfiguration.getInstance();
setWillNotDraw(false);
+ setDim(getDim());
}
@Override
protected void onFinishInflate() {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- mMaxDim = config.taskStackMaxDim;
+ mMaxDim = mConfig.taskStackMaxDim;
// By default, all views are clipped to other views in their stack
mClipViewInStack = true;
// Bind the views
- mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
+ mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
if (mTaskDataLoaded) {
onTaskDataLoaded(false);
@@ -104,8 +132,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Update the rounded rect clip path
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- float radius = config.taskViewRoundedCornerRadiusPx;
+ float radius = mConfig.taskViewRoundedCornerRadiusPx;
mRoundedRectClipPath.reset();
mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
radius, radius, Path.Direction.CW);
@@ -113,7 +140,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
// Update the outline
Outline o = new Outline();
o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight() -
- config.taskViewShadowOutlineBottomInsetPx, radius);
+ mConfig.taskViewShadowOutlineBottomInsetPx, radius);
setOutline(o);
}
@@ -139,52 +166,64 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
}
/** Synchronizes this view's properties with the task's transform */
- void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
- TaskViewTransform toTransform, int duration) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
+ void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
+ if (Console.Enabled) {
+ Console.log(Constants.Log.UI.Draw, "[TaskView|updateViewPropertiesToTaskTransform]",
+ "duration: " + duration, Console.AnsiPurple);
+ }
// Update the bar view
- mBarView.updateViewPropertiesToTaskTransform(animateFromTransform, toTransform, duration);
+ mBarView.updateViewPropertiesToTaskTransform(toTransform, duration);
- // Update this task view
+ // Check to see if any properties have changed, and update the task view
if (duration > 0) {
- if (animateFromTransform != null) {
- setTranslationY(animateFromTransform.translationY);
- if (Constants.DebugFlags.App.EnableShadows) {
- setTranslationZ(animateFromTransform.translationZ);
- }
- setScaleX(animateFromTransform.scale);
- setScaleY(animateFromTransform.scale);
- setAlpha(animateFromTransform.alpha);
+ ViewPropertyAnimator anim = animate();
+ boolean useLayers = false;
+
+ // Animate to the final state
+ if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
+ anim.translationY(toTransform.translationY);
}
- if (Constants.DebugFlags.App.EnableShadows) {
- animate().translationZ(toTransform.translationZ);
+ if (Constants.DebugFlags.App.EnableShadows &&
+ toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
+ anim.translationZ(toTransform.translationZ);
}
- animate().translationY(toTransform.translationY)
- .scaleX(toTransform.scale)
+ if (toTransform.hasScaleChangedFrom(getScaleX())) {
+ anim.scaleX(toTransform.scale)
.scaleY(toTransform.scale)
- .alpha(toTransform.alpha)
- .setDuration(duration)
- .setInterpolator(config.fastOutSlowInInterpolator)
- .withLayer()
- .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateDimOverlayFromScale();
- }
- })
- .start();
+ .setUpdateListener(mUpdateDimListener);
+ useLayers = true;
+ }
+ if (toTransform.hasAlphaChangedFrom(getAlpha())) {
+ // Use layers if we animate alpha
+ anim.alpha(toTransform.alpha);
+ useLayers = true;
+ }
+ if (useLayers) {
+ anim.withLayer();
+ }
+ anim.setStartDelay(toTransform.startDelay)
+ .setDuration(duration)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .start();
} else {
- setTranslationY(toTransform.translationY);
- if (Constants.DebugFlags.App.EnableShadows) {
+ // Set the changed properties
+ if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
+ setTranslationY(toTransform.translationY);
+ }
+ if (Constants.DebugFlags.App.EnableShadows &&
+ toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
setTranslationZ(toTransform.translationZ);
}
- setScaleX(toTransform.scale);
- setScaleY(toTransform.scale);
- setAlpha(toTransform.alpha);
+ if (toTransform.hasScaleChangedFrom(getScaleX())) {
+ setScaleX(toTransform.scale);
+ setScaleY(toTransform.scale);
+ updateDimOverlayFromScale();
+ }
+ if (toTransform.hasAlphaChangedFrom(getAlpha())) {
+ setAlpha(toTransform.alpha);
+ }
}
- updateDimOverlayFromScale();
- invalidate();
}
/** Resets this view's properties */
@@ -197,6 +236,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
setScaleX(1f);
setScaleY(1f);
setAlpha(1f);
+ setDim(0);
invalidate();
}
@@ -208,6 +248,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
// Fade the view out and slide it away
toTransform.alpha = 0f;
toTransform.translationY += 200;
+ toTransform.translationZ = 0;
}
/**
@@ -221,66 +262,176 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
/** 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);
+ public void prepareEnterRecentsAnimation(boolean isTaskViewFrontMost, int offsetY, int offscreenY,
+ Rect taskRect) {
+ if (mConfig.launchedFromAppWithScreenshot) {
+ if (isTaskViewFrontMost) {
+ // Hide the task view as we are going to animate the full screenshot into view
+ // and then replace it with this view once we are done
+ setVisibility(View.INVISIBLE);
+ // Also hide the front most task bar view so we can animate it in
+ mBarView.prepareEnterRecentsAnimation();
+ } else {
+ // Top align the task views
+ setTranslationY(offsetY);
+ setScaleX(1f);
+ setScaleY(1f);
+ }
+
+ } else if (mConfig.launchedFromAppWithThumbnail) {
+ if (isTaskViewFrontMost) {
+ // Hide the front most task bar view so we can animate it in
+ mBarView.prepareEnterRecentsAnimation();
+ // Set the dim to 0 so we can animate it in
+ setDim(0);
+ }
+
+ } else if (mConfig.launchedFromHome) {
+ // Move the task view off screen (below) so we can animate it in
+ setTranslationY(offscreenY);
+ setTranslationZ(0);
+ setScaleX(1f);
+ setScaleY(1f);
+ }
}
/** Animates this task view as it enters recents */
- public void animateOnEnterRecents() {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- mBarView.setVisibility(View.VISIBLE);
- mBarView.setTranslationY(-mBarView.getMeasuredHeight());
- mBarView.animate()
- .translationY(0)
- .setStartDelay(config.taskBarEnterAnimDelay)
- .setInterpolator(config.fastOutSlowInInterpolator)
- .setDuration(config.taskBarEnterAnimDuration)
+ public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
+ TaskViewTransform transform = ctx.transform;
+
+ if (mConfig.launchedFromAppWithScreenshot) {
+ if (ctx.isFrontMost) {
+ // Animate the full screenshot down first, before swapping with this task view
+ ctx.fullScreenshot.animateOnEnterRecents(ctx, new Runnable() {
+ @Override
+ public void run() {
+ // Animate the task bar of the first task view
+ mBarView.startEnterRecentsAnimation(0, mEnableThumbnailClip);
+ setVisibility(View.VISIBLE);
+ }
+ });
+ } else {
+ // Animate the tasks down behind the full screenshot
+ animate()
+ .scaleX(transform.scale)
+ .scaleY(transform.scale)
+ .translationY(transform.translationY)
+ .setStartDelay(0)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.linearOutSlowInInterpolator)
+ .setDuration(475)
+ .withLayer()
+ .withEndAction(mEnableThumbnailClip)
+ .start();
+ }
+
+ } else if (mConfig.launchedFromAppWithThumbnail) {
+ if (ctx.isFrontMost) {
+ // Animate the task bar of the first task view
+ mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
+
+ // Animate the dim into view as well
+ ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimOverlayFromScale());
+ anim.setStartDelay(mConfig.taskBarEnterAnimDelay);
+ anim.setDuration(mConfig.taskBarEnterAnimDuration);
+ anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+ anim.start();
+ } else {
+ mEnableThumbnailClip.run();
+ }
+
+ } else if (mConfig.launchedFromHome) {
+ // Animate the tasks up
+ int frontIndex = (ctx.stackViewCount - ctx.stackViewIndex - 1);
+ int delay = mConfig.taskBarEnterAnimDelay +
+ frontIndex * mConfig.taskViewEnterFromHomeDelay;
+ animate()
+ .scaleX(transform.scale)
+ .scaleY(transform.scale)
+ .translationY(transform.translationY)
+ .translationZ(transform.translationZ)
+ .setStartDelay(delay)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.quintOutInterpolator)
+ .setDuration(mConfig.taskViewEnterFromHomeDuration)
+ .withLayer()
+ .withEndAction(mEnableThumbnailClip)
+ .start();
+ }
+ }
+
+ /** Animates this task view as it leaves recents by pressing home. */
+ public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
+ animate()
+ .translationY(ctx.offscreenTranslationY)
+ .setStartDelay(0)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskViewExitToHomeDuration)
.withLayer()
+ .withEndAction(ctx.postAnimationTrigger.decrementAsRunnable())
.start();
+ ctx.postAnimationTrigger.increment();
}
/** Animates this task view as it exits recents */
- public void animateOnLeavingRecents(final Runnable r) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- mBarView.animate()
- .translationY(-mBarView.getMeasuredHeight())
- .setStartDelay(0)
- .setInterpolator(config.fastOutLinearInInterpolator)
- .setDuration(config.taskBarExitAnimDuration)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- post(r);
- }
- })
- .start();
+ public void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask) {
+ if (isLaunchingTask) {
+ // Disable the thumbnail clip and animate the bar out
+ mBarView.startLaunchTaskAnimation(mDisableThumbnailClip, r);
+
+ // Animate the dim
+ if (mDim > 0) {
+ ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
+ anim.setDuration(mConfig.taskBarExitAnimDuration);
+ anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+ anim.start();
+ }
+ } else {
+ // Hide the dismiss button
+ mBarView.startLaunchTaskDismissAnimation();
+ }
}
/** Animates the deletion of this task view */
- public void animateRemoval(final Runnable r) {
+ public void startDeleteTaskAnimation(final Runnable r) {
// Disabling clipping with the stack while the view is animating away
setClipViewInStack(false);
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- animate().translationX(config.taskViewRemoveAnimTranslationXPx)
+ animate().translationX(mConfig.taskViewRemoveAnimTranslationXPx)
.alpha(0f)
.setStartDelay(0)
- .setInterpolator(config.fastOutSlowInInterpolator)
- .setDuration(config.taskViewRemoveAnimDuration)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.taskViewRemoveAnimDuration)
.withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
- post(r);
+ // We just throw this into a runnable because starting a view property
+ // animation using layers can cause inconsisten results if we try and
+ // update the layers while the animation is running. In some cases,
+ // the runnabled passed in may start an animation which also uses layers
+ // so we defer all this by posting this.
+ r.run();
// Re-enable clipping with the stack (we will reuse this view)
- setClipViewInStack(false);
+ setClipViewInStack(true);
}
})
.start();
}
+ /** Animates this task view if the user does not interact with the stack after a certain time. */
+ public void startNoUserInteractionAnimation() {
+ mBarView.startNoUserInteractionAnimation();
+ }
+
+ /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ public void setNoUserInteractionState() {
+ mBarView.setNoUserInteractionState();
+ }
+
/** Returns the rect we want to clip (it may not be the full rect) */
Rect getClippingRect(Rect outRect) {
getHitRect(outRect);
@@ -292,12 +443,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
/** Enable the hw layers on this task view */
void enableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+ mBarView.enableHwLayers();
}
/** Disable the hw layers on this task view */
void disableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ mBarView.disableHwLayers();
}
/**
@@ -305,7 +458,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
* view.
*/
boolean shouldClipViewInStack() {
- return mClipViewInStack;
+ return mClipViewInStack && (getVisibility() == View.VISIBLE);
}
/** Sets whether this view should be clipped, or clipped against. */
@@ -313,28 +466,44 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
if (clip != mClipViewInStack) {
mClipViewInStack = clip;
if (getParent() instanceof View) {
- Rect r = new Rect();
- getHitRect(r);
- ((View) getParent()).invalidate(r);
+ getHitRect(mTmpRect);
+ ((View) getParent()).invalidate(mTmpRect);
}
}
}
- /** Update the dim as a function of the scale of this view. */
- void updateDimOverlayFromScale() {
+ /** Returns the current dim. */
+ public void setDim(int dim) {
+ mDim = dim;
+ postInvalidateOnAnimation();
+ }
+
+ /** Returns the current dim. */
+ public int getDim() {
+ return mDim;
+ }
+
+ /** Compute the dim as a function of the scale of this view. */
+ int getDimOverlayFromScale() {
float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
float scaleRange = 1f - minScale;
float dim = (1f - getScaleX()) / scaleRange;
dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
- mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+ return Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+ }
+
+ /** Update the dim as a function of the scale of this view. */
+ void updateDimOverlayFromScale() {
+ setDim(getDimOverlayFromScale());
}
@Override
public void draw(Canvas canvas) {
+ int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
// Apply the rounded rect clip path on the whole view
canvas.clipPath(mRoundedRectClipPath);
-
super.draw(canvas);
+ canvas.restoreToCount(restoreCount);
// Apply the dim if necessary
if (mDim > 0) {
@@ -391,8 +560,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mBarView.mApplicationIcon.setOnClickListener(this);
mBarView.mDismissButton.setOnClickListener(this);
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (config.developerOptionsEnabled) {
+ if (mConfig.developerOptionsEnabled) {
mBarView.mApplicationIcon.setOnLongClickListener(this);
}
}
@@ -418,19 +586,25 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
}
@Override
- public void onClick(View v) {
- if (v == mBarView.mApplicationIcon) {
- mCb.onTaskIconClicked(this);
- } else if (v == mBarView.mDismissButton) {
- // Animate out the view and call the callback
- final TaskView tv = this;
- animateRemoval(new Runnable() {
- @Override
- public void run() {
- mCb.onTaskDismissed(tv);
+ public void onClick(final View v) {
+ // We purposely post the handler delayed to allow for the touch feedback to draw
+ final TaskView tv = this;
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (v == mBarView.mApplicationIcon) {
+ mCb.onTaskIconClicked(tv);
+ } else if (v == mBarView.mDismissButton) {
+ // Animate out the view and call the callback
+ startDeleteTaskAnimation(new Runnable() {
+ @Override
+ public void run() {
+ mCb.onTaskDismissed(tv);
+ }
+ });
}
- });
- }
+ }
+ }, 125);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 3c3ebd7..b351b03 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -21,6 +21,7 @@ import android.graphics.Rect;
/* The transform state for a task view */
public class TaskViewTransform {
+ public int startDelay = 0;
public int translationY = 0;
public int translationZ = 0;
public float scale = 1f;
@@ -28,13 +29,14 @@ public class TaskViewTransform {
public float dismissAlpha = 1f;
public boolean visible = false;
public Rect rect = new Rect();
- float t;
+ float t = 0f;
public TaskViewTransform() {
// Do nothing
}
public TaskViewTransform(TaskViewTransform o) {
+ startDelay = o.startDelay;
translationY = o.translationY;
translationZ = o.translationZ;
scale = o.scale;
@@ -45,9 +47,40 @@ public class TaskViewTransform {
t = o.t;
}
+ /** Resets the current transform */
+ public void reset() {
+ startDelay = 0;
+ translationY = 0;
+ translationZ = 0;
+ scale = 1f;
+ alpha = 1f;
+ dismissAlpha = 1f;
+ visible = false;
+ rect.setEmpty();
+ t = 0f;
+ }
+
+ /** Convenience functions to compare against current property values */
+ public boolean hasAlphaChangedFrom(float v) {
+ return (Float.compare(alpha, v) != 0);
+ }
+ public boolean hasDismissAlphaChangedFrom(float v) {
+ return (Float.compare(dismissAlpha, v) != 0);
+ }
+ public boolean hasScaleChangedFrom(float v) {
+ return (Float.compare(scale, v) != 0);
+ }
+ public boolean hasTranslationYChangedFrom(float v) {
+ return (Float.compare(translationY, v) != 0);
+ }
+ public boolean hasTranslationZChangedFrom(float v) {
+ return (Float.compare(translationZ, v) != 0);
+ }
+
@Override
public String toString() {
- return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
- " visible: " + visible + " rect: " + rect + " dismissAlpha: " + dismissAlpha;
+ return "TaskViewTransform delay: " + startDelay + " y: " + translationY + " z: " + translationZ +
+ " scale: " + scale + " alpha: " + alpha + " visible: " + visible + " rect: " + rect +
+ " dismissAlpha: " + dismissAlpha;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
new file mode 100644
index 0000000..13407aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -0,0 +1,60 @@
+/*
+ * 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.systemui.recents.views;
+
+import android.graphics.Rect;
+import com.android.systemui.recents.ReferenceCountedTrigger;
+
+/* Common code related to view animations */
+public class ViewAnimation {
+
+ /* The animation context for a task view animation into Recents */
+ public static class TaskViewEnterContext {
+ // The full screenshot view that we are animating down
+ FullscreenTransitionOverlayView fullScreenshot;
+ // The transform of the current task view
+ TaskViewTransform transform;
+ // The stack rect that the transform is relative to
+ Rect stackRectSansPeek;
+ // The task rect
+ Rect taskRect;
+ // The view index of the current task view
+ int stackViewIndex;
+ // The total number of task views
+ int stackViewCount;
+ // Whether this is the front most task view
+ boolean isFrontMost;
+
+ public TaskViewEnterContext(FullscreenTransitionOverlayView fss) {
+ fullScreenshot = fss;
+ }
+ }
+
+ /* The animation context for a task view animation out of Recents */
+ public static class TaskViewExitContext {
+ // A trigger to run some logic when all the animations complete. This works around the fact
+ // that it is difficult to coordinate ViewPropertyAnimators
+ ReferenceCountedTrigger postAnimationTrigger;
+ // The translationY to apply to a TaskView to move it off screen
+ int offscreenTranslationY;
+
+ public TaskViewExitContext(ReferenceCountedTrigger t) {
+ postAnimationTrigger = t;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
index d67e7cb..a3b10f2 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
@@ -21,8 +21,16 @@ import com.android.systemui.R;
import android.app.ActivityManagerNative;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.UserManager;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
@@ -43,15 +51,18 @@ import java.util.List;
/**
* A quick and dirty view to show a user switcher.
*/
-public class UserSwitcherHostView extends FrameLayout implements ListView.OnItemClickListener {
+public class UserSwitcherHostView extends FrameLayout
+ implements ListView.OnItemClickListener, View.OnClickListener {
private static final String TAG = "UserSwitcherDialog";
private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
+ private UserInfo mGuestUser;
private Adapter mAdapter = new Adapter();
private UserManager mUserManager;
private Runnable mFinishRunnable;
private ListView mListView;
+ private boolean mGuestUserEnabled;
public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@@ -60,6 +71,9 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
return;
}
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+
+ mGuestUserEnabled = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.GUEST_USER_ENABLED, 0) == 1;
}
public UserSwitcherHostView(Context context, AttributeSet attrs) {
@@ -80,7 +94,39 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
- int userId = mAdapter.getItem(position).id;
+ // Last item is the guest
+ if (position == mUserInfo.size()) {
+ postDelayed(new Runnable() {
+ public void run() {
+ switchToGuestUser();
+ }
+ }, 100);
+ } else {
+ final int userId = mAdapter.getItem(position).id;
+ postDelayed(new Runnable() {
+ public void run() {
+ switchUser(userId);
+ }
+ }, 100);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ // Delete was clicked
+ postDelayed(new Runnable() {
+ public void run() {
+ if (mGuestUser != null) {
+ switchUser(0);
+ mUserManager.removeUser(mGuestUser.id);
+ mGuestUser = null;
+ refreshUsers();
+ }
+ }
+ }, 100);
+ }
+
+ private void switchUser(int userId) {
try {
WindowManagerGlobal.getWindowManagerService().lockNow(null);
ActivityManagerNative.getDefault().switchUser(userId);
@@ -90,6 +136,15 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
}
}
+ private void switchToGuestUser() {
+ if (mGuestUser == null) {
+ // No guest user. Create one.
+ mGuestUser = mUserManager.createGuest(mContext,
+ mContext.getResources().getString(R.string.guest_nickname));
+ }
+ switchUser(mGuestUser.id);
+ }
+
private void finish() {
if (mFinishRunnable != null) {
mFinishRunnable.run();
@@ -119,9 +174,12 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
public void refreshUsers() {
mUserInfo.clear();
+ mGuestUser = null;
List<UserInfo> users = mUserManager.getUsers(true);
for (UserInfo user : users) {
- if (!user.isManagedProfile()) {
+ if (user.isGuest()) {
+ mGuestUser = user;
+ } else if (!user.isManagedProfile()) {
mUserInfo.add(user);
}
}
@@ -132,17 +190,25 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
@Override
public int getCount() {
- return mUserInfo.size();
+ return mUserInfo.size() + (mGuestUserEnabled ? 1 : 0);
}
@Override
public UserInfo getItem(int position) {
- return mUserInfo.get(position);
+ if (position < mUserInfo.size()) {
+ return mUserInfo.get(position);
+ } else {
+ return mGuestUser;
+ }
}
@Override
public long getItemId(int position) {
- return getItem(position).serialNumber;
+ if (position < mUserInfo.size()) {
+ return getItem(position).serialNumber;
+ } else {
+ return mGuestUser != null ? mGuestUser.serialNumber : -1;
+ }
}
@Override
@@ -161,18 +227,46 @@ public class UserSwitcherHostView extends FrameLayout implements ListView.OnItem
ViewHolder h = new ViewHolder();
h.name = (TextView) v.findViewById(R.id.user_name);
h.picture = (ImageView) v.findViewById(R.id.user_picture);
+ h.delete = (ImageView) v.findViewById(R.id.user_delete);
v.setTag(h);
return v;
}
private void bindView(ViewHolder h, UserInfo item) {
- h.name.setText(item.name);
- h.picture.setImageBitmap(mUserManager.getUserIcon(item.id));
+ if (item != null) {
+ h.name.setText(item.name);
+ h.picture.setImageBitmap(circularClip(mUserManager.getUserIcon(item.id)));
+ h.delete.setVisibility(item.isGuest() ? View.VISIBLE : View.GONE);
+ h.delete.setOnClickListener(UserSwitcherHostView.this);
+ if (item.isGuest()) {
+ h.picture.setImageResource(R.drawable.ic_account_circle);
+ }
+ } else {
+ h.name.setText(R.string.guest_new_guest);
+ h.picture.setImageResource(R.drawable.ic_account_circle);
+ h.delete.setVisibility(View.GONE);
+ }
+ }
+
+ private Bitmap circularClip(Bitmap input) {
+ if (input == null) {
+ return null;
+ }
+ Bitmap output = Bitmap.createBitmap(input.getWidth(),
+ input.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+ final Paint paint = new Paint();
+ paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
+ paint.setAntiAlias(true);
+ canvas.drawCircle(input.getWidth() / 2, input.getHeight() / 2, input.getWidth() / 2,
+ paint);
+ return output;
}
class ViewHolder {
TextView name;
ImageView picture;
+ ImageView delete;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 8d19f50..f6f78e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -119,6 +119,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private NotificationBackgroundView mBackgroundNormal;
private NotificationBackgroundView mBackgroundDimmed;
+ private NotificationScrimView mScrimView;
private ObjectAnimator mBackgroundAnimator;
private RectF mAppearAnimationRect = new RectF();
private PorterDuffColorFilter mAppearAnimationFilter;
@@ -153,6 +154,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
updateBackground();
updateBackgroundResources();
+ mScrimView = (NotificationScrimView) findViewById(R.id.scrim_view);
}
private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -379,6 +381,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
setPivotY(actualHeight / 2);
mBackgroundNormal.setActualHeight(actualHeight);
mBackgroundDimmed.setActualHeight(actualHeight);
+ mScrimView.setActualHeight(actualHeight);
}
@Override
@@ -386,6 +389,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
super.setClipTopAmount(clipTopAmount);
mBackgroundNormal.setClipTopAmount(clipTopAmount);
mBackgroundDimmed.setClipTopAmount(clipTopAmount);
+ mScrimView.setClipTopAmount(clipTopAmount);
}
@Override
@@ -405,6 +409,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
}
+ @Override
+ public void setScrimAmount(float scrimAmount) {
+ mScrimView.setAlpha(scrimAmount);
+ }
+
private void startAppearAnimation(boolean isAppearing,
float translationDirection, long delay, final Runnable onFinishedRunnable) {
if (mAppearAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index b94493e..c621f31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -89,11 +89,11 @@ import java.util.Locale;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
- CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener {
+ CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
+ RecentsComponent.Callbacks {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
- private static final boolean USE_NOTIFICATION_LISTENER = true;
protected static final int MSG_SHOW_RECENT_APPS = 1019;
protected static final int MSG_HIDE_RECENT_APPS = 1020;
@@ -297,7 +297,7 @@ public abstract class BaseStatusBar extends SystemUI implements
@Override
public void run() {
for (StatusBarNotification sbn : notifications) {
- addNotificationInternal(sbn, currentRanking);
+ addNotification(sbn, currentRanking);
}
}
});
@@ -324,16 +324,16 @@ public abstract class BaseStatusBar extends SystemUI implements
// wasn't a group child, remove the old instance.
// Otherwise just update the ranking.
if (isUpdate) {
- removeNotificationInternal(sbn.getKey(), rankingMap);
+ removeNotification(sbn.getKey(), rankingMap);
} else {
- updateRankingInternal(rankingMap);
+ updateNotificationRanking(rankingMap);
}
return;
}
if (isUpdate) {
- updateNotificationInternal(sbn, rankingMap);
+ updateNotification(sbn, rankingMap);
} else {
- addNotificationInternal(sbn, rankingMap);
+ addNotification(sbn, rankingMap);
}
}
});
@@ -346,7 +346,7 @@ public abstract class BaseStatusBar extends SystemUI implements
mHandler.post(new Runnable() {
@Override
public void run() {
- removeNotificationInternal(sbn.getKey(), rankingMap);
+ removeNotification(sbn.getKey(), rankingMap);
}
});
}
@@ -357,7 +357,7 @@ public abstract class BaseStatusBar extends SystemUI implements
mHandler.post(new Runnable() {
@Override
public void run() {
- updateRankingInternal(rankingMap);
+ updateNotificationRanking(rankingMap);
}
});
}
@@ -404,6 +404,7 @@ public abstract class BaseStatusBar extends SystemUI implements
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mRecents = getComponent(RecentsComponent.class);
+ mRecents.setCallback(this);
mLocale = mContext.getResources().getConfiguration().locale;
mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
@@ -412,14 +413,12 @@ public abstract class BaseStatusBar extends SystemUI implements
// Connect in to the status bar manager service
StatusBarIconList iconList = new StatusBarIconList();
- ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
mCommandQueue = new CommandQueue(this, iconList);
int[] switches = new int[8];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
try {
- mBarService.registerStatusBar(mCommandQueue, iconList, notifications,
- switches, binders);
+ mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
@@ -445,19 +444,12 @@ public abstract class BaseStatusBar extends SystemUI implements
}
// Set up the initial notification state.
- if (USE_NOTIFICATION_LISTENER) {
- try {
- mNotificationListener.registerAsSystemService(
- new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
- UserHandle.USER_ALL);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to register notification listener", e);
- }
- } else {
- N = notifications.size();
- for (int i=0; i<N; i++) {
- addNotification(notifications.get(i));
- }
+ try {
+ mNotificationListener.registerAsSystemService(
+ new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to register notification listener", e);
}
@@ -787,6 +779,11 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ // Do nothing
+ }
+
public abstract void resetHeadsUpDecayTimer();
public abstract void scheduleHeadsUpOpen();
@@ -1187,7 +1184,7 @@ public abstract class BaseStatusBar extends SystemUI implements
* WARNING: this will call back into us. Don't hold any locks.
*/
void handleNotificationError(StatusBarNotification n, String message) {
- removeNotification(n.getKey());
+ removeNotification(n.getKey(), null);
try {
mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
n.getInitialPid(), message, n.getUserId());
@@ -1323,34 +1320,11 @@ public abstract class BaseStatusBar extends SystemUI implements
protected abstract void updateExpandedViewPos(int expandedPosition);
protected abstract boolean shouldDisableNavbarGestures();
- @Override
- public void addNotification(StatusBarNotification notification) {
- if (!USE_NOTIFICATION_LISTENER) {
- addNotificationInternal(notification, null);
- }
- }
-
- public abstract void addNotificationInternal(StatusBarNotification notification,
+ public abstract void addNotification(StatusBarNotification notification,
RankingMap ranking);
-
- protected abstract void updateRankingInternal(RankingMap ranking);
-
- @Override
- public void removeNotification(String key) {
- if (!USE_NOTIFICATION_LISTENER) {
- removeNotificationInternal(key, null);
- }
- }
-
- public abstract void removeNotificationInternal(String key, RankingMap ranking);
-
- public void updateNotification(StatusBarNotification notification) {
- if (!USE_NOTIFICATION_LISTENER) {
- updateNotificationInternal(notification, null);
- }
- }
-
- public void updateNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
+ protected abstract void updateNotificationRanking(RankingMap ranking);
+ public abstract void removeNotification(String key, RankingMap ranking);
+ public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final String key = notification.getKey();
@@ -1467,7 +1441,7 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
if (shouldInterrupt && alertAgain) {
removeNotificationViews(key, ranking);
- addNotificationInternal(notification, ranking); //this will pop the headsup
+ addNotification(notification, ranking); //this will pop the headsup
} else {
updateNotificationViews(oldEntry, notification);
}
@@ -1507,7 +1481,7 @@ public abstract class BaseStatusBar extends SystemUI implements
if (shouldInterrupt && alertAgain) {
if (DEBUG) Log.d(TAG, "reposting to invoke heads up for key: " + key);
removeNotificationViews(key, ranking);
- addNotificationInternal(notification, ranking); //this will pop the headsup
+ addNotification(notification, ranking); //this will pop the headsup
} else {
if (DEBUG) Log.d(TAG, "rebuilding update in place for key: " + key);
removeNotificationViews(key, ranking);
@@ -1665,12 +1639,10 @@ public abstract class BaseStatusBar extends SystemUI implements
mWindowManager.removeViewImmediate(mSearchPanelView);
}
mContext.unregisterReceiver(mBroadcastReceiver);
- if (USE_NOTIFICATION_LISTENER) {
- try {
- mNotificationListener.unregisterAsSystemService();
- } catch (RemoteException e) {
- // Ignore.
- }
+ try {
+ mNotificationListener.unregisterAsSystemService();
+ } catch (RemoteException e) {
+ // Ignore.
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index aaeadb6..2b61f09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -41,23 +41,20 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int OP_REMOVE_ICON = 2;
private static final int MSG_ICON = 1 << MSG_SHIFT;
- private static final int MSG_ADD_NOTIFICATION = 2 << MSG_SHIFT;
- private static final int MSG_UPDATE_NOTIFICATION = 3 << MSG_SHIFT;
- private static final int MSG_REMOVE_NOTIFICATION = 4 << MSG_SHIFT;
- private static final int MSG_DISABLE = 5 << MSG_SHIFT;
- private static final int MSG_EXPAND_NOTIFICATIONS = 6 << MSG_SHIFT;
- private static final int MSG_COLLAPSE_PANELS = 7 << MSG_SHIFT;
- private static final int MSG_EXPAND_SETTINGS = 8 << MSG_SHIFT;
- private static final int MSG_SET_SYSTEMUI_VISIBILITY = 9 << MSG_SHIFT;
- private static final int MSG_TOP_APP_WINDOW_CHANGED = 10 << MSG_SHIFT;
- private static final int MSG_SHOW_IME_BUTTON = 11 << MSG_SHIFT;
- private static final int MSG_SET_HARD_KEYBOARD_STATUS = 12 << MSG_SHIFT;
- private static final int MSG_TOGGLE_RECENT_APPS = 13 << MSG_SHIFT;
- private static final int MSG_PRELOAD_RECENT_APPS = 14 << MSG_SHIFT;
- private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
- private static final int MSG_SET_WINDOW_STATE = 16 << MSG_SHIFT;
- private static final int MSG_SHOW_RECENT_APPS = 17 << MSG_SHIFT;
- private static final int MSG_HIDE_RECENT_APPS = 18 << MSG_SHIFT;
+ private static final int MSG_DISABLE = 2 << MSG_SHIFT;
+ private static final int MSG_EXPAND_NOTIFICATIONS = 3 << MSG_SHIFT;
+ private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
+ private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
+ private static final int MSG_SET_SYSTEMUI_VISIBILITY = 6 << MSG_SHIFT;
+ private static final int MSG_TOP_APP_WINDOW_CHANGED = 7 << MSG_SHIFT;
+ private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
+ private static final int MSG_SET_HARD_KEYBOARD_STATUS = 9 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_RECENT_APPS = 10 << MSG_SHIFT;
+ private static final int MSG_PRELOAD_RECENT_APPS = 11 << MSG_SHIFT;
+ private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 12 << MSG_SHIFT;
+ private static final int MSG_SET_WINDOW_STATE = 13 << MSG_SHIFT;
+ private static final int MSG_SHOW_RECENT_APPS = 14 << MSG_SHIFT;
+ private static final int MSG_HIDE_RECENT_APPS = 15 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -80,9 +77,6 @@ public class CommandQueue extends IStatusBar.Stub {
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon);
public void removeIcon(String slot, int index, int viewIndex);
- public void addNotification(StatusBarNotification notification);
- public void updateNotification(StatusBarNotification notification);
- public void removeNotification(String key);
public void disable(int state);
public void animateExpandNotificationsPanel();
public void animateCollapsePanels(int flags);
@@ -123,26 +117,6 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- @Override
- public void addNotification(StatusBarNotification notification) {
- synchronized (mList) {
- mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, notification).sendToTarget();
- }
- }
-
- @Override
- public void updateNotification(StatusBarNotification notification) {
- synchronized (mList) {
- mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, notification).sendToTarget();
- }
- }
-
- public void removeNotification(String key) {
- synchronized (mList) {
- mHandler.obtainMessage(MSG_REMOVE_NOTIFICATION, 0, 0, key).sendToTarget();
- }
- }
-
public void disable(int state) {
synchronized (mList) {
mHandler.removeMessages(MSG_DISABLE);
@@ -279,18 +253,6 @@ public class CommandQueue extends IStatusBar.Stub {
}
break;
}
- case MSG_ADD_NOTIFICATION: {
- mCallbacks.addNotification((StatusBarNotification) msg.obj);
- break;
- }
- case MSG_UPDATE_NOTIFICATION: {
- mCallbacks.updateNotification((StatusBarNotification) msg.obj);
- break;
- }
- case MSG_REMOVE_NOTIFICATION: {
- mCallbacks.removeNotification((String) msg.obj);
- break;
- }
case MSG_DISABLE:
mCallbacks.disable(msg.arg1);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 5bad602..5981898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -212,13 +212,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
return mShowingPublic ? mRowMinHeight : mMaxExpandHeight;
}
- /**
- * @return the potential height this view could expand in addition.
- */
- public int getExpandPotential() {
- return getIntrinsicHeight() - getActualHeight();
- }
-
@Override
public boolean isContentExpandable() {
NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index ac2537c..4d4a8ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -223,6 +223,8 @@ public abstract class ExpandableView extends FrameLayout {
public abstract void performAddAnimation(long delay);
+ public abstract void setScrimAmount(float scrimAmount);
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
deleted file mode 100644
index bfa74fa..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.systemui.statusbar;
-
-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.NotificationListenerService.RankingMap;
-import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-
-public class InterceptedNotifications {
- private static final String TAG = "InterceptedNotifications";
- 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;
-
- public InterceptedNotifications(Context context, PhoneStatusBar bar) {
- mContext = context;
- mBar = bar;
- }
-
- public void releaseIntercepted() {
- final int n = mIntercepted.size();
- for (int i = 0; i < n; i++) {
- final StatusBarNotification sbn = mIntercepted.valueAt(i);
- mReleased.add(sbn.getKey());
- mBar.displayNotification(sbn, null);
- }
- mIntercepted.clear();
- updateSyntheticNotification();
- }
-
- public boolean tryIntercept(StatusBarNotification notification, RankingMap rankingMap) {
- if (rankingMap == null) return false;
- if (shouldDisplayIntercepted()) return false;
- if (mReleased.contains(notification.getKey())) return false;
- Ranking ranking = rankingMap.getRanking(notification.getKey());
- if (!ranking.isInterceptedByDoNotDisturb()) return false;
- mIntercepted.put(notification.getKey(), notification);
- updateSyntheticNotification();
- return true;
- }
-
- public void retryIntercepts(RankingMap ranking) {
- if (ranking == null) return;
-
- final int N = mIntercepted.size();
- final ArraySet<String> removed = new ArraySet<String>(N);
- for (int i = 0; i < N; i++) {
- final StatusBarNotification sbn = mIntercepted.valueAt(i);
- if (!tryIntercept(sbn, ranking)) {
- removed.add(sbn.getKey());
- mBar.displayNotification(sbn, ranking);
- }
- }
- if (!removed.isEmpty()) {
- mIntercepted.removeAll(removed);
- updateSyntheticNotification();
- }
- }
-
- public void remove(String key) {
- if (mIntercepted.remove(key) != null) {
- updateSyntheticNotification();
- }
- mReleased.remove(key);
- }
-
- public boolean isSyntheticEntry(Entry ent) {
- return ent.key.equals(mSynKey);
- }
-
- private boolean shouldDisplayIntercepted() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS, 0) != 0;
- }
-
- private void updateSyntheticNotification() {
- if (mIntercepted.isEmpty()) {
- if (mSynKey != null) {
- mBar.removeNotificationInternal(mSynKey, null);
- mSynKey = null;
- }
- return;
- }
- final Notification n = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_notify_zen)
- .setContentTitle(mContext.getResources().getQuantityString(
- R.plurals.zen_mode_notification_title,
- mIntercepted.size(), mIntercepted.size()))
- .setContentText(mContext.getString(R.string.zen_mode_notification_text))
- .setOngoing(true)
- .build();
- final StatusBarNotification sbn = new StatusBarNotification(mContext.getPackageName(),
- mContext.getBasePackageName(),
- TAG.hashCode(), TAG, Process.myUid(), Process.myPid(), 0, n,
- mBar.getCurrentUserHandle());
- if (mSynKey == null) {
- mSynKey = sbn.getKey();
- mBar.displayNotification(sbn, null);
- } else {
- mBar.updateNotificationInternal(sbn, null);
- }
- final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
- entry.row.setOnClickListener(mSynClickListener);
- }
-
- private final View.OnClickListener mSynClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- releaseIntercepted();
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 5cde979..f919501 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -17,12 +17,16 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.View;
-
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
+
import com.android.systemui.R;
/**
@@ -32,6 +36,8 @@ import com.android.systemui.R;
*/
public class NotificationContentView extends FrameLayout {
+ private static final long ANIMATION_DURATION_LENGTH = 170;
+
private final Rect mClipBounds = new Rect();
private View mContractedChild;
@@ -41,10 +47,17 @@ public class NotificationContentView extends FrameLayout {
private int mClipTopAmount;
private int mActualHeight;
+ private final Interpolator mLinearInterpolator = new LinearInterpolator();
+
+ private boolean mContractedVisible = true;
+
+ private Paint mFadePaint = new Paint();
+
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
mActualHeight = mSmallHeight;
+ mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
}
@Override
@@ -60,7 +73,7 @@ public class NotificationContentView extends FrameLayout {
sanitizeContractedLayoutParams(child);
addView(child);
mContractedChild = child;
- selectLayout();
+ selectLayout(false /* animate */, true /* force */);
}
public void setExpandedChild(View child) {
@@ -69,12 +82,12 @@ public class NotificationContentView extends FrameLayout {
}
addView(child);
mExpandedChild = child;
- selectLayout();
+ selectLayout(false /* animate */, true /* force */);
}
public void setActualHeight(int actualHeight) {
mActualHeight = actualHeight;
- selectLayout();
+ selectLayout(true /* animate */, false /* force */);
updateClipping();
}
@@ -104,26 +117,60 @@ public class NotificationContentView extends FrameLayout {
contractedChild.setLayoutParams(lp);
}
- private void selectLayout() {
- if (mActualHeight <= mSmallHeight || mExpandedChild == null) {
- if (mContractedChild != null && mContractedChild.getVisibility() != View.VISIBLE) {
- mContractedChild.setVisibility(View.VISIBLE);
- }
- if (mExpandedChild != null && mExpandedChild.getVisibility() != View.INVISIBLE) {
- mExpandedChild.setVisibility(View.INVISIBLE);
- }
- } else {
- if (mExpandedChild.getVisibility() != View.VISIBLE) {
- mExpandedChild.setVisibility(View.VISIBLE);
- }
- if (mContractedChild != null && mContractedChild.getVisibility() != View.INVISIBLE) {
- mContractedChild.setVisibility(View.INVISIBLE);
+ private void selectLayout(boolean animate, boolean force) {
+ if (mContractedChild == null) {
+ return;
+ }
+ boolean showContractedChild = showContractedChild();
+ if (showContractedChild != mContractedVisible || force) {
+ if (animate && mExpandedChild != null) {
+ runSwitchAnimation(showContractedChild);
+ } else if (mExpandedChild != null) {
+ mContractedChild.setVisibility(showContractedChild ? View.VISIBLE : View.INVISIBLE);
+ mContractedChild.setAlpha(showContractedChild ? 1f : 0f);
+ mExpandedChild.setVisibility(showContractedChild ? View.INVISIBLE : View.VISIBLE);
+ mExpandedChild.setAlpha(showContractedChild ? 0f : 1f);
}
}
+ mContractedVisible = showContractedChild;
+ }
+
+ private void runSwitchAnimation(final boolean showContractedChild) {
+ mContractedChild.setVisibility(View.VISIBLE);
+ mExpandedChild.setVisibility(View.VISIBLE);
+ mContractedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
+ mExpandedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ mContractedChild.animate()
+ .alpha(showContractedChild ? 1f : 0f)
+ .setDuration(ANIMATION_DURATION_LENGTH)
+ .setInterpolator(mLinearInterpolator);
+ mExpandedChild.animate()
+ .alpha(showContractedChild ? 0f : 1f)
+ .setDuration(ANIMATION_DURATION_LENGTH)
+ .setInterpolator(mLinearInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
+ mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
+ setLayerType(LAYER_TYPE_NONE, null);
+ mContractedChild.setVisibility(showContractedChild
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ mExpandedChild.setVisibility(showContractedChild
+ ? View.INVISIBLE
+ : View.VISIBLE);
+ }
+ });
+ }
+
+ private boolean showContractedChild() {
+ return mActualHeight <= mSmallHeight || mExpandedChild == null;
}
public void notifyContentUpdated() {
- selectLayout();
+ selectLayout(false /* animate */, true /* force */);
}
public boolean isContentExpandable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
new file mode 100644
index 0000000..440b2c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
@@ -0,0 +1,79 @@
+/*
+ * 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.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.keyguard.R;
+
+/**
+ * A view that can be used for both the dimmed and normal background of an notification.
+ */
+public class NotificationScrimView extends View {
+
+ private Drawable mBackground;
+ private int mClipTopAmount;
+ private int mActualHeight;
+
+ public NotificationScrimView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mBackground = getResources().getDrawable(R.drawable.notification_scrim);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ draw(canvas, mBackground);
+ }
+
+ private void draw(Canvas canvas, Drawable drawable) {
+ if (drawable != null) {
+ drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
+ drawable.draw(canvas);
+ }
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || who == mBackground;
+ }
+
+ public void setActualHeight(int actualHeight) {
+ mActualHeight = actualHeight;
+ invalidate();
+ }
+
+ public int getActualHeight() {
+ return mActualHeight;
+ }
+
+ public void setClipTopAmount(int clipTopAmount) {
+ mClipTopAmount = clipTopAmount;
+ invalidate();
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+
+ // Prevents this view from creating a layer when alpha is animating.
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index f80f0fd..650abaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -121,4 +121,9 @@ public class SpeedBumpView extends ExpandableView {
public void performAddAnimation(long delay) {
performVisibilityAnimation(true);
}
+
+ @Override
+ public void setScrimAmount(float scrimAmount) {
+ // We don't need to scrim the speedbumps
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 97aa993..63698e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -58,6 +58,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private ImageView mCameraImageView;
private ImageView mPhoneImageView;
private ImageView mLockIcon;
+ private View mIndicationText;
private ActivityStarter mActivityStarter;
private UnlockMethodCache mUnlockMethodCache;
@@ -87,6 +88,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mCameraImageView = (ImageView) findViewById(R.id.camera_button);
mPhoneImageView = (ImageView) findViewById(R.id.phone_button);
mLockIcon = (ImageView) findViewById(R.id.lock_icon);
+ mIndicationText = findViewById(R.id.keyguard_indication_text);
watchForCameraPolicyChanges();
watchForAccessibilityChanges();
updateCameraVisibility();
@@ -231,6 +233,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
return mLockIcon;
}
+ public View getIndicationView() {
+ return mIndicationText;
+ }
+
@Override
public void onMethodSecureChanged(boolean methodSecure) {
updateTrust();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 6a83a5e..319096d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone;
import android.content.res.Resources;
import android.graphics.Path;
+import android.view.animation.AccelerateInterpolator;
import android.view.animation.PathInterpolator;
import com.android.systemui.R;
@@ -31,6 +32,10 @@ public class KeyguardClockPositionAlgorithm {
private static final float CLOCK_RUBBERBAND_FACTOR_MIN = 0.08f;
private static final float CLOCK_RUBBERBAND_FACTOR_MAX = 0.8f;
+ private static final float CLOCK_SCALE_FADE_START = 0.95f;
+ private static final float CLOCK_SCALE_FADE_END = 0.75f;
+ private static final float CLOCK_SCALE_FADE_END_NO_NOTIFS = 0.5f;
+
private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN = 1.4f;
private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX = 3.2f;
@@ -61,6 +66,8 @@ public class KeyguardClockPositionAlgorithm {
sSlowDownInterpolator = new PathInterpolator(path);
}
+ private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator();
+
/**
* Refreshes the dimension values.
*/
@@ -87,18 +94,29 @@ public class KeyguardClockPositionAlgorithm {
}
public void run(Result result) {
- int y = getClockY() - mKeyguardStatusHeight/2;
+ int y = getClockY() - mKeyguardStatusHeight / 2;
float clockAdjustment = getClockYExpansionAdjustment();
float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier();
result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier);
int clockNotificationsPadding = getClockNotificationsPadding()
+ result.stackScrollerPaddingAdjustment;
int padding = y + clockNotificationsPadding;
- y += clockAdjustment;
result.clockY = y;
result.stackScrollerPadding = mKeyguardStatusHeight + padding;
- result.clockAlpha = getClockAlpha(result.stackScrollerPadding
- - (y + mKeyguardStatusHeight));
+ result.clockScale = getClockScale(result.stackScrollerPadding,
+ result.clockY,
+ y + getClockNotificationsPadding() + mKeyguardStatusHeight);
+ result.clockAlpha = getClockAlpha(result.clockScale);
+ }
+
+ private float getClockScale(int notificationPadding, int clockY, int startPadding) {
+ float scaleMultiplier = getNotificationAmountT() == 0 ? 6.0f : 5.0f;
+ float scaleEnd = clockY - mKeyguardStatusHeight * scaleMultiplier;
+ float distanceToScaleEnd = notificationPadding - scaleEnd;
+ float progress = distanceToScaleEnd / (startPadding - scaleEnd);
+ progress = Math.max(0.0f, Math.min(progress, 1.0f));
+ progress = mAccelerateInterpolator.getInterpolation(progress);
+ return progress;
}
private int getClockNotificationsPadding() {
@@ -144,11 +162,12 @@ public class KeyguardClockPositionAlgorithm {
+ t * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX;
}
- private float getClockAlpha(int clockNotificationPadding) {
- float t = getNotificationAmountT();
- t = (float) Math.pow(t, 0.3f);
- float multiplier = 1 + 2 * (1 - t);
- float alpha = 1 + (float) clockNotificationPadding * multiplier / mKeyguardStatusHeight * 3;
+ private float getClockAlpha(float scale) {
+ float fadeEnd = getNotificationAmountT() == 0.0f
+ ? CLOCK_SCALE_FADE_END_NO_NOTIFS
+ : CLOCK_SCALE_FADE_END;
+ float alpha = (scale - fadeEnd)
+ / (CLOCK_SCALE_FADE_START - fadeEnd);
return Math.max(0, Math.min(1, alpha));
}
@@ -168,6 +187,11 @@ public class KeyguardClockPositionAlgorithm {
public int clockY;
/**
+ * The scale of the Clock
+ */
+ public float clockScale;
+
+ /**
* The alpha value of the clock.
*/
public float clockAlpha;
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 dde95bf..a6ce5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -32,6 +32,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableView;
@@ -48,6 +49,11 @@ public class NotificationPanelView extends PanelView implements
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardPageSwipeHelper.Callback {
+ // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
+ // changed.
+ private static final int CAP_HEIGHT = 1456;
+ private static final int FONT_HEIGHT = 2163;
+
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
private KeyguardPageSwipeHelper mPageSwiper;
@@ -56,7 +62,7 @@ public class NotificationPanelView extends PanelView implements
private View mQsPanel;
private View mKeyguardStatusView;
private ObservableScrollView mScrollView;
- private View mStackScrollerContainer;
+ private TextView mClockView;
private NotificationStackScrollLayout mNotificationStackScroller;
private int mNotificationTopPadding;
@@ -105,9 +111,11 @@ public class NotificationPanelView extends PanelView implements
new KeyguardClockPositionAlgorithm.Result();
private boolean mIsSwipedHorizontally;
private boolean mIsExpanding;
- private KeyguardBottomAreaView mKeyguardBottomArea;
+
private boolean mBlockTouches;
private ArrayList<View> mSwipeTranslationViews = new ArrayList<>();
+ private int mNotificationScrimWaitDistance;
+ private boolean mOnNotificationsOnDown;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -135,9 +143,9 @@ public class NotificationPanelView extends PanelView implements
mHeader.getBackgroundView().setOnClickListener(this);
mHeader.setOverlayParent(this);
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);
+ mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
mScrollView.setListener(this);
mNotificationStackScroller = (NotificationStackScrollLayout)
@@ -169,12 +177,19 @@ public class NotificationPanelView extends PanelView implements
getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance);
mUnlockMoveDistance = getResources().getDimensionPixelOffset(R.dimen.unlock_move_distance);
mClockPositionAlgorithm.loadDimens(getResources());
+ mNotificationScrimWaitDistance =
+ getResources().getDimensionPixelSize(R.dimen.notification_scrim_wait_distance);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+ // Update Clock Pivot
+ mKeyguardStatusView.setPivotX(getWidth() / 2);
+ mKeyguardStatusView.setPivotY(
+ (FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize());
+
// Calculate quick setting heights.
mQsMinExpansionHeight = mHeader.getCollapsedHeight() + mQsPeekHeight;
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
@@ -197,7 +212,7 @@ public class NotificationPanelView extends PanelView implements
* showing.
*/
private void positionClockAndNotifications() {
- boolean animateClock = mNotificationStackScroller.isAddOrRemoveAnimationPending();
+ boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
int bottom = mStackScrollerOverscrolling
@@ -215,17 +230,17 @@ public class NotificationPanelView extends PanelView implements
getHeight(),
mKeyguardStatusView.getHeight());
mClockPositionAlgorithm.run(mClockPositionResult);
- if (animateClock || mClockAnimator != null) {
+ if (animate || mClockAnimator != null) {
startClockAnimation(mClockPositionResult.clockY);
} else {
mKeyguardStatusView.setY(mClockPositionResult.clockY);
}
- applyClockAlpha(mClockPositionResult.clockAlpha);
+ updateClock(mClockPositionResult.clockAlpha, mClockPositionResult.clockScale);
stackScrollerPadding = mClockPositionResult.stackScrollerPadding;
mTopPaddingAdjustment = mClockPositionResult.stackScrollerPaddingAdjustment;
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
- requestScrollerTopPaddingUpdate(animateClock);
+ requestScrollerTopPaddingUpdate(animate);
}
private void startClockAnimation(int y) {
@@ -258,13 +273,10 @@ public class NotificationPanelView extends PanelView implements
});
}
- private void applyClockAlpha(float alpha) {
- if (alpha != 1.0f) {
- mKeyguardStatusView.setLayerType(LAYER_TYPE_HARDWARE, null);
- } else {
- mKeyguardStatusView.setLayerType(LAYER_TYPE_NONE, null);
- }
+ private void updateClock(float alpha, float scale) {
mKeyguardStatusView.setAlpha(alpha);
+ mKeyguardStatusView.setScaleX(scale);
+ mKeyguardStatusView.setScaleY(scale);
}
public void animateToFullShade() {
@@ -344,6 +356,7 @@ public class NotificationPanelView extends PanelView implements
mInitialTouchX = x;
initVelocityTracker();
trackMovement(event);
+ mOnNotificationsOnDown = isOnNotifications(x, y);
if (shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
getParent().requestDisallowInterceptTouchEvent(true);
}
@@ -391,6 +404,8 @@ public class NotificationPanelView extends PanelView implements
if (mQsTracking) {
flingQsWithCurrentVelocity();
mQsTracking = false;
+ } else if (mQsFullyExpanded && mOnNotificationsOnDown) {
+ flingSettings(0 /* vel */, false /* expand */);
}
mIntercepting = false;
break;
@@ -398,6 +413,10 @@ public class NotificationPanelView extends PanelView implements
return !mQsExpanded && super.onInterceptTouchEvent(event);
}
+ private boolean isOnNotifications(float x, float y) {
+ return mNotificationStackScroller.getChildAtPosition(x, y) != null;
+ }
+
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
@@ -577,9 +596,17 @@ public class NotificationPanelView extends PanelView implements
mHeader.setExpansion(height - mQsPeekHeight);
setQsTranslation(height);
requestScrollerTopPaddingUpdate(false /* animate */);
+ updateNotificationScrim(height);
mStatusBar.userActivity();
}
+ private void updateNotificationScrim(float height) {
+ int startDistance = mQsMinExpansionHeight + mNotificationScrimWaitDistance;
+ float progress = (height - startDistance) / (mQsMaxExpansionHeight - startDistance);
+ progress = Math.max(0.0f, Math.min(progress, 1.0f));
+ mNotificationStackScroller.setScrimAlpha(progress);
+ }
+
private void setQsTranslation(float height) {
mQsContainer.setY(height - mQsContainer.getHeight());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 1f3098d..12aa004 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -62,6 +62,7 @@ public abstract class PanelView extends FrameLayout {
protected int mTouchSlop;
protected boolean mHintAnimationRunning;
private boolean mOverExpandedBeforeFling;
+ private float mOriginalIndicationY;
private ValueAnimator mHeightAnimator;
private ObjectAnimator mPeekAnimator;
@@ -82,6 +83,7 @@ public abstract class PanelView extends FrameLayout {
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mBounceInterpolator;
+ protected KeyguardBottomAreaView mKeyguardBottomArea;
protected void onExpandingFinished() {
mBar.onExpandingFinished();
@@ -652,6 +654,22 @@ public abstract class PanelView extends FrameLayout {
});
animator.start();
mHeightAnimator = animator;
+ mOriginalIndicationY = mKeyguardBottomArea.getIndicationView().getY();
+ mKeyguardBottomArea.getIndicationView().animate()
+ .y(mOriginalIndicationY - mHintDistance)
+ .setDuration(250)
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardBottomArea.getIndicationView().animate()
+ .y(mOriginalIndicationY)
+ .setDuration(450)
+ .setInterpolator(mBounceInterpolator)
+ .start();
+ }
+ })
+ .start();
}
/**
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 c11a9ac..00951b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -35,6 +35,7 @@ import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
@@ -64,6 +65,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.provider.Settings.SettingNotFoundException;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
@@ -82,7 +84,6 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
@@ -109,7 +110,6 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.GestureRecorder;
-import com.android.systemui.statusbar.InterceptedNotifications;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
@@ -123,6 +123,7 @@ import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastControllerImpl;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -211,6 +212,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ZenModeController mZenModeController;
CastControllerImpl mCastController;
VolumeComponent mVolumeComponent;
+ KeyguardUserSwitcher mKeyguardUserSwitcher;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -260,6 +262,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
boolean mLeaveOpenOnKeyguardHide;
KeyguardIndicationController mKeyguardIndicationController;
+ private boolean mKeyguardFadingAway;
+ private long mKeyguardFadingAwayDelay;
+ private long mKeyguardFadingAwayDuration;
+
int mKeyguardMaxNotificationCount;
View mDateTimeView;
@@ -267,7 +273,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private TextView mCarrierLabel;
private boolean mCarrierLabelVisible = false;
private int mCarrierLabelHeight;
- private TextView mEmergencyCallLabel;
private int mStatusBarHeaderHeight;
private boolean mShowCarrierInPanel = false;
@@ -393,14 +398,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}};
private Runnable mOnFlipRunnable;
- private InterceptedNotifications mIntercepted;
private VelocityTracker mSettingsTracker;
private float mSettingsDownY;
private boolean mSettingsStarted;
private boolean mSettingsCancelled;
private boolean mSettingsClosing;
private boolean mVisible;
+ private boolean mWaitingForKeyguardExit;
+ private Interpolator mLinearOutSlowIn;
private Interpolator mAlphaOut = new PathInterpolator(0f, 0.4f, 1f, 1f);
private Interpolator mAlphaIn = new PathInterpolator(0f, 0f, 0.8f, 1f);
@@ -502,19 +508,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
};
@Override
- public void setZenMode(int mode) {
- super.setZenMode(mode);
- if (!isDeviceProvisioned()) return;
- final boolean zen = mode != Settings.Global.ZEN_MODE_OFF;
- if (!zen) {
- mIntercepted.releaseIntercepted();
- }
- if (mIconPolicy != null) {
- mIconPolicy.setZenMode(zen);
- }
- }
-
- @Override
protected void setShowLockscreenNotifications(boolean show) {
super.setShowLockscreenNotifications(show);
updateStackScrollerState();
@@ -525,7 +518,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
updateDisplaySize();
- mIntercepted = new InterceptedNotifications(mContext, this);
super.start(); // calls createAndAddWindows()
addNavigationBar();
@@ -714,26 +706,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
final SignalClusterView signalCluster =
(SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
+ mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
+ (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mHeader);
mNetworkController.addSignalCluster(signalCluster);
signalCluster.setNetworkController(mNetworkController);
-
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
- mEmergencyCallLabel =
- (TextView) mStatusBarWindow.findViewById(R.id.emergency_calls_only);
- // TODO: Uncomment when correctly positioned
-// if (mEmergencyCallLabel != null) {
-// mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
-// mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
-// public void onClick(View v) { }});
-// mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-// @Override
-// public void onLayoutChange(View v, int left, int top, int right, int bottom,
-// int oldLeft, int oldTop, int oldRight, int oldBottom) {
-// updateCarrierLabelVisibility(false);
-// }});
-// }
+ mNetworkController.addEmergencyLabelView(mHeader);
}
mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
@@ -759,6 +739,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// updateCarrierLabelVisibility(false);
}
+ mBatteryController.setStatusBarHeaderView(mHeader);
+
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
@@ -906,6 +888,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
};
+ private View.OnLongClickListener mLockToAppClickListener = new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ toggleLockedApp();
+ return true;
+ }
+ };
+
private int mShowSearchHoldoff = 0;
private Runnable mShowSearchPanel = new Runnable() {
public void run() {
@@ -949,6 +939,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
+ mNavigationBarView.getRecentsButton().setLongClickable(true);
+ mNavigationBarView.getRecentsButton().setOnLongClickListener(mLockToAppClickListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
updateSearchPanel();
}
@@ -1064,18 +1056,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
- public void addNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
+ public void addNotification(StatusBarNotification notification, RankingMap ranking) {
if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
- if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification, ranking)) {
- // Forward the ranking so we can sort the new notification.
- mNotificationData.updateRanking(ranking);
- return;
- }
- mIntercepted.remove(notification.getKey());
- displayNotification(notification, ranking);
- }
-
- public void displayNotification(StatusBarNotification notification, RankingMap ranking) {
if (mUseHeadsUp && shouldInterrupt(notification)) {
if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
Entry interruptionCandidate = new Entry(notification, null);
@@ -1157,21 +1139,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
- public void updateNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
- super.updateNotificationInternal(notification, ranking);
- // if we're here, then the notification is already in the shade
- mIntercepted.remove(notification.getKey());
- }
-
- @Override
- protected void updateRankingInternal(RankingMap ranking) {
+ protected void updateNotificationRanking(RankingMap ranking) {
mNotificationData.updateRanking(ranking);
- mIntercepted.retryIntercepts(ranking);
updateNotifications();
}
@Override
- public void removeNotificationInternal(String key, RankingMap ranking) {
+ public void removeNotification(String key, RankingMap ranking) {
if (ENABLE_HEADS_UP && mHeadsUpNotificationView.getEntry() != null
&& key.equals(mHeadsUpNotificationView.getEntry().notification.getKey())) {
mHeadsUpNotificationView.clear();
@@ -1194,7 +1168,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
animateCollapsePanels();
}
}
- mIntercepted.remove(key);
setAreThereNotifications();
}
@@ -1350,9 +1323,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// in "public" mode (atop a secure keyguard), secret notifs are totally hidden
continue;
}
- if (mIntercepted.isSyntheticEntry(ent)) {
- continue;
- }
toShow.add(ent.icon);
}
@@ -1387,7 +1357,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mCarrierLabelHeight));
}
- final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
+ // Emergency calls only is shown in the expanded header now.
+ final boolean emergencyCallsShownElsewhere = true;
final boolean makeVisible =
!(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
&& mStackScroller.getHeight() < (mNotificationPanel.getHeight()
@@ -1465,7 +1436,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private int adjustDisableFlags(int state) {
- if (mExpandedVisible) {
+ if (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit) {
state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
state |= StatusBarManager.DISABLE_SYSTEM_INFO;
}
@@ -1513,19 +1484,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
mSystemIconArea.animate().cancel();
if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
- mSystemIconArea.animate()
- .alpha(0f)
- .withLayer()
- .setDuration(160)
- .setInterpolator(mAlphaIn)
- .setListener(mMakeIconsInvisible);
+ animateStatusBarHide(mSystemIconArea);
} else {
- mSystemIconArea.setVisibility(View.VISIBLE);
- mSystemIconArea.animate()
- .alpha(1f)
- .withLayer()
- .setInterpolator(mAlphaOut)
- .setDuration(320);
+ animateStatusBarShow(mSystemIconArea);
}
}
@@ -1558,25 +1519,48 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mTicking) {
haltTicker();
}
-
- mNotificationIcons.animate()
- .alpha(0f)
- .withLayer()
- .setDuration(160)
- .setInterpolator(mAlphaIn)
- .setListener(mMakeIconsInvisible)
- .start();
+ animateStatusBarHide(mNotificationIcons);
} else {
- mNotificationIcons.setVisibility(View.VISIBLE);
- mNotificationIcons.animate()
- .alpha(1f)
- .withLayer()
- .setInterpolator(mAlphaOut)
- .setDuration(320);
+ animateStatusBarShow(mNotificationIcons);
}
}
}
+ /**
+ * Animates {@code v}, a view that is part of the status bar, out.
+ */
+ private void animateStatusBarHide(View v) {
+ v.animate()
+ .alpha(0f)
+ .withLayer()
+ .setDuration(160)
+ .setInterpolator(mAlphaIn)
+ .setStartDelay(0)
+ .setListener(mMakeIconsInvisible)
+ .start();
+ }
+
+ /**
+ * Animates {@code v}, a view that is part of the status bar, in.
+ */
+ private void animateStatusBarShow(View v) {
+ v.setVisibility(View.VISIBLE);
+ v.animate()
+ .alpha(1f)
+ .withLayer()
+ .setInterpolator(mAlphaOut)
+ .setDuration(320)
+ .setStartDelay(0);
+
+ // Synchronize the motion with the Keyguard fading if necessary.
+ if (mKeyguardFadingAway) {
+ v.animate()
+ .setDuration(mKeyguardFadingAwayDuration)
+ .setInterpolator(mLinearOutSlowIn)
+ .setStartDelay(mKeyguardFadingAwayDelay);
+ }
+ }
+
@Override
protected BaseStatusBar.H createHandler() {
return new PhoneStatusBar.H();
@@ -1678,6 +1662,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStatusBarWindowManager.setStatusBarExpanded(true);
visibilityChanged(true);
+ mWaitingForKeyguardExit = false;
disable(mDisabledUnmodified);
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
@@ -1718,7 +1703,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (mStatusBarWindow != null) {
-
// release focus immediately to kick off focus change transition
mStatusBarWindowManager.setStatusBarFocusable(false);
@@ -1872,8 +1856,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
- disable(mDisabledUnmodified);
showBouncer();
+ disable(mDisabledUnmodified);
}
public boolean interceptTouchEvent(MotionEvent event) {
@@ -1960,6 +1944,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Integer.toHexString(oldVal), Integer.toHexString(newVal),
Integer.toHexString(diff)));
if (diff != 0) {
+ // we never set the recents bit via this method, so save the prior state to prevent
+ // clobbering the bit below
+ final boolean wasRecentsVisible = (mSystemUiVisibility & View.RECENT_APPS_VISIBLE) > 0;
+
mSystemUiVisibility = newVal;
// update low profile
@@ -2014,6 +2002,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
}
+ // restore the recents bit
+ if (wasRecentsVisible) {
+ mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
+ }
+
// send updated sysui visibility to window manager
notifyUiVisibilityChanged(mSystemUiVisibility);
}
@@ -2578,6 +2571,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mQSPanel != null) mQSPanel.updateResources();
loadDimens();
+ mLinearOutSlowIn = AnimationUtils.loadInterpolator(
+ mContext, android.R.interpolator.linear_out_slow_in);
}
protected void loadDimens() {
@@ -2905,6 +2900,27 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
updateKeyguardState();
}
+ /**
+ * Notifies the status bar the Keyguard is fading away with the specified timings.
+ *
+ * @param delay the animation delay in miliseconds
+ * @param fadeoutDuration the duration of the exit animation, in milliseconds
+ */
+ public void setKeyguardFadingAway(long delay, long fadeoutDuration) {
+ mKeyguardFadingAway = true;
+ mKeyguardFadingAwayDelay = delay;
+ mKeyguardFadingAwayDuration = fadeoutDuration;
+ mWaitingForKeyguardExit = false;
+ disable(mDisabledUnmodified);
+ }
+
+ /**
+ * Notifies that the Keyguard fading away animation is done.
+ */
+ public void finishKeyguardFadingAway() {
+ mKeyguardFadingAway = false;
+ }
+
private void updatePublicMode() {
setLockscreenPublicMode(
(mStatusBarKeyguardViewManager.isShowing() ||
@@ -2917,9 +2933,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardStatusView.setVisibility(View.VISIBLE);
mKeyguardIndicationController.setVisible(true);
mNotificationPanel.resetViews();
+ mKeyguardUserSwitcher.setKeyguard(true);
} else {
mKeyguardStatusView.setVisibility(View.GONE);
mKeyguardIndicationController.setVisible(false);
+ mKeyguardUserSwitcher.setKeyguard(false);
}
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
mKeyguardBottomArea.setVisibility(View.VISIBLE);
@@ -2979,6 +2997,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void showBouncer() {
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+ mWaitingForKeyguardExit = true;
mStatusBarKeyguardViewManager.dismiss();
}
}
@@ -3129,6 +3148,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mSystemIconArea.addView(mSystemIcons, 0);
}
+ @Override
+ public void setBouncerShowing(boolean bouncerShowing) {
+ super.setBouncerShowing(bouncerShowing);
+ disable(mDisabledUnmodified);
+ }
+
public void onScreenTurnedOff() {
mStackScroller.setAnimationsEnabled(false);
}
@@ -3137,6 +3162,28 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller.setAnimationsEnabled(true);
}
+ public void toggleLockedApp() {
+ Log.d(TAG, "Trying to toggle lock-to-app");
+ try {
+ IActivityManager activityManager = ActivityManagerNative.getDefault();
+ if (activityManager.isInLockTaskMode()) {
+ activityManager.stopLockTaskModeOnCurrent();
+ } else {
+ try {
+ boolean lockToAppEnabled = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.LOCK_TO_APP_ENABLED) != 0;
+ if (lockToAppEnabled) {
+ activityManager.startLockTaskModeOnCurrent();
+ }
+ } catch (SettingNotFoundException e) {
+ // No setting, not enabled.
+ }
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Unable to toggle Lock-to-app", e);
+ }
+ }
+
private final Runnable mUserActivity = new Runnable() {
@Override
public void run() {
@@ -3145,4 +3192,41 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
};
+
+ // Recents
+
+ @Override
+ protected void showRecents(boolean triggeredFromAltTab) {
+ // Set the recents visibility flag
+ mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
+ notifyUiVisibilityChanged(mSystemUiVisibility);
+ super.showRecents(triggeredFromAltTab);
+ }
+
+ @Override
+ protected void hideRecents(boolean triggeredFromAltTab) {
+ // Unset the recents visibility flag
+ mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
+ notifyUiVisibilityChanged(mSystemUiVisibility);
+ super.hideRecents(triggeredFromAltTab);
+ }
+
+ @Override
+ protected void toggleRecents() {
+ // Toggle the recents visibility flag
+ mSystemUiVisibility ^= View.RECENT_APPS_VISIBLE;
+ notifyUiVisibilityChanged(mSystemUiVisibility);
+ super.toggleRecents();
+ }
+
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ // Update the recents visibility flag
+ if (visible) {
+ mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
+ } else {
+ mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
+ }
+ notifyUiVisibilityChanged(mSystemUiVisibility);
+ }
}
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 7837769..fc10a08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -26,6 +26,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
@@ -57,6 +58,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private View mSignalCluster;
private View mSettingsButton;
private View mBrightnessContainer;
+ private View mEmergencyCallsOnly;
+ private TextView mChargingInfo;
+
+ private boolean mShowEmergencyCallsOnly;
+ private boolean mShowChargingInfo;
+ private boolean mKeyguardUserSwitcherShowing;
private int mCollapsedHeight;
private int mExpandedHeight;
@@ -66,6 +73,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private int mNormalWidth;
private int mPadding;
private int mMultiUserExpandedMargin;
+ private int mSystemIconsSwitcherHiddenExpandedMargin;
private ActivityStarter mActivityStarter;
private BrightnessController mBrightnessController;
@@ -93,6 +101,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
+ mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
+ mChargingInfo = (TextView) findViewById(R.id.header_charging_info);
loadDimens();
updateVisibilities();
addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@@ -117,7 +127,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
mMultiUserExpandedMargin =
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
-
+ mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
+ R.dimen.system_icons_switcher_hidden_expanded_margin);
}
public void setActivityStarter(ActivityStarter activityStarter) {
@@ -204,13 +215,40 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
if (mSignalCluster != null) {
mSignalCluster.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
}
+ mEmergencyCallsOnly.setVisibility(mExpanded && !mOverscrolled && mShowEmergencyCallsOnly
+ ? VISIBLE : GONE);
+ mChargingInfo.setVisibility(mExpanded && !mOverscrolled && mShowChargingInfo
+ && !mShowEmergencyCallsOnly ? VISIBLE : GONE);
+ mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing
+ ? VISIBLE : GONE);
}
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsContainer.getLayoutParams();
- lp.addRule(RelativeLayout.START_OF, mExpanded
- ? mSettingsButton.getId()
- : mMultiUserSwitch.getId());
+ boolean systemIconsAboveClock = mExpanded && !mOverscrolled
+ && mShowChargingInfo && !mShowEmergencyCallsOnly;
+ lp.setMarginEnd(0);
+ if (systemIconsAboveClock) {
+ lp.addRule(ALIGN_PARENT_START);
+ lp.removeRule(START_OF);
+ } else {
+ lp.addRule(RelativeLayout.START_OF, mExpanded
+ ? mSettingsButton.getId()
+ : mMultiUserSwitch.getId());
+ lp.removeRule(ALIGN_PARENT_START);
+ if (mMultiUserSwitch.getVisibility() == GONE) {
+ lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin);
+ }
+ }
+ mSystemIconsContainer.setLayoutParams(lp);
+
+ RelativeLayout.LayoutParams clockLp = (LayoutParams) mDateTime.getLayoutParams();
+ if (systemIconsAboveClock) {
+ clockLp.addRule(BELOW, mChargingInfo.getId());
+ } else {
+ clockLp.addRule(BELOW, mEmergencyCallsOnly.getId());
+ }
+ mDateTime.setLayoutParams(clockLp);
}
private void updateBrightnessControllerState() {
@@ -338,4 +376,31 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
public boolean shouldDelayChildPressedState() {
return true;
}
+
+ public void setShowEmergencyCallsOnly(boolean show) {
+ mShowEmergencyCallsOnly = show;
+ if (mExpanded) {
+ updateVisibilities();
+ updateSystemIconsLayoutParams();
+ }
+ }
+
+ public void setShowChargingInfo(boolean showChargingInfo) {
+ mShowChargingInfo = showChargingInfo;
+ if (mExpanded) {
+ updateVisibilities();
+ updateSystemIconsLayoutParams();
+ }
+ }
+
+ public void setChargingInfo(CharSequence chargingInfo) {
+ mChargingInfo.setText(chargingInfo);
+ }
+
+ public void setKeyguardUserSwitcherShowing(boolean showing) {
+ // STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?!
+ mKeyguardUserSwitcherShowing = showing;
+ updateVisibilities();
+ updateSystemIconsLayoutParams();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 09e4d94..a36f3d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -190,19 +190,23 @@ public class StatusBarKeyguardViewManager {
*/
public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
- mPhoneStatusBar.hideKeyguard();
- mStatusBarWindowManager.setKeyguardFadingAway(true);
- mStatusBarWindowManager.setKeyguardShowing(false);
+
long uptimeMillis = SystemClock.uptimeMillis();
long delay = startTime - uptimeMillis;
if (delay < 0) {
delay = 0;
}
+
+ mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
+ mPhoneStatusBar.hideKeyguard();
+ mStatusBarWindowManager.setKeyguardFadingAway(true);
+ mStatusBarWindowManager.setKeyguardShowing(false);
mBouncer.animateHide(delay, fadeoutDuration);
mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
@Override
public void run() {
mStatusBarWindowManager.setKeyguardFadingAway(false);
+ mPhoneStatusBar.finishKeyguardFadingAway();
}
});
mViewMediatorCallback.keyguardGone();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
new file mode 100644
index 0000000..6f2642a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -0,0 +1,219 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import com.android.systemui.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * A view that displays a user image cropped to a circle with a frame.
+ */
+public class UserAvatarView extends View {
+
+ private int mActiveFrameColor;
+ private int mFrameColor;
+ private float mFrameWidth;
+ private Bitmap mBitmap;
+ private Drawable mDrawable;
+
+ private final Paint mFramePaint = new Paint();
+ private final Paint mBitmapPaint = new Paint();
+ private final Matrix mDrawMatrix = new Matrix();
+
+ private float mScale = 1;
+
+ public UserAvatarView(Context context, AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes);
+ final int N = a.getIndexCount();
+ for (int i = 0; i < N; i++) {
+ int attr = a.getIndex(i);
+ switch (attr) {
+ case R.styleable.UserAvatarView_frameWidth:
+ setFrameWidth(a.getDimension(attr, 0));
+ break;
+ case R.styleable.UserAvatarView_activeFrameColor:
+ setActiveFrameColor(a.getColor(attr, 0));
+ break;
+ case R.styleable.UserAvatarView_frameColor:
+ setFrameColor(a.getColor(attr, 0));
+ break;
+ }
+ }
+ a.recycle();
+
+ mFramePaint.setAntiAlias(true);
+ mFramePaint.setStyle(Paint.Style.STROKE);
+ mBitmapPaint.setAntiAlias(true);
+ }
+
+ public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public UserAvatarView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UserAvatarView(Context context) {
+ this(context, null);
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ setDrawable(null);
+ mBitmap = bitmap;
+ if (mBitmap != null) {
+ mBitmapPaint.setShader(new BitmapShader(
+ bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
+ } else {
+ mBitmapPaint.setShader(null);
+ }
+ configureBounds();
+ invalidate();
+ }
+
+ public void setFrameColor(int frameColor) {
+ mFrameColor = frameColor;
+ invalidate();
+ }
+
+ public void setActiveFrameColor(int activeFrameColor) {
+ mActiveFrameColor = activeFrameColor;
+ invalidate();
+ }
+
+ public void setFrameWidth(float frameWidth) {
+ mFrameWidth = frameWidth;
+ invalidate();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ configureBounds();
+ }
+
+ public void configureBounds() {
+ int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
+ int vheight = getHeight() - mPaddingTop - mPaddingBottom;
+
+ int dwidth;
+ int dheight;
+ if (mBitmap != null) {
+ dwidth = mBitmap.getWidth();
+ dheight = mBitmap.getHeight();
+ } else if (mDrawable != null) {
+ dwidth = mDrawable.getIntrinsicWidth();
+ dheight = mDrawable.getIntrinsicHeight();
+ mDrawable.setBounds(0, 0, dwidth, dheight);
+ vwidth -= 2 * (mFrameWidth - 1);
+ vheight -= 2 * (mFrameWidth - 1);
+ } else {
+ return;
+ }
+
+ float scale;
+ float dx;
+ float dy;
+
+ scale = Math.min((float) vwidth / (float) dwidth,
+ (float) vheight / (float) dheight);
+
+ dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
+ dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
+
+ mDrawMatrix.setScale(scale, scale);
+ mDrawMatrix.postTranslate(dx, dy);
+ mScale = scale;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int frameColor = isActivated() ? mActiveFrameColor : mFrameColor;
+ float halfW = getWidth() / 2f;
+ float halfH = getHeight() / 2f;
+ float halfSW = Math.min(halfH, halfW);
+ if (mBitmap != null && mScale > 0) {
+ int saveCount = canvas.getSaveCount();
+ canvas.save();
+ canvas.translate(mPaddingLeft, mPaddingTop);
+ canvas.concat(mDrawMatrix);
+ float halfBW = mBitmap.getWidth() / 2f;
+ float halfBH = mBitmap.getHeight() / 2f;
+ float halfBSW = Math.min(halfBH, halfBW);
+ canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint);
+ canvas.restoreToCount(saveCount);
+ } else if (mDrawable != null && mScale > 0) {
+ int saveCount = canvas.getSaveCount();
+ canvas.save();
+ canvas.translate(mPaddingLeft, mPaddingTop);
+ canvas.translate(mFrameWidth - 1, mFrameWidth - 1);
+ canvas.concat(mDrawMatrix);
+ mDrawable.draw(canvas);
+ canvas.restoreToCount(saveCount);
+ }
+ if (frameColor != 0) {
+ mFramePaint.setColor(frameColor);
+ mFramePaint.setStrokeWidth(mFrameWidth);
+ canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint);
+ }
+ }
+
+ public void setDrawable(Drawable d) {
+ if (mDrawable != null) {
+ mDrawable.setCallback(null);
+ unscheduleDrawable(mDrawable);
+ }
+ mDrawable = d;
+ if (d != null) {
+ d.setCallback(this);
+ if (d.isStateful()) {
+ d.setState(getDrawableState());
+ }
+ d.setLayoutDirection(getLayoutDirection());
+ configureBounds();
+ }
+ if (d != null) {
+ mBitmap = null;
+ }
+ configureBounds();
+ invalidate();
+ }
+
+ @Override
+ public void invalidateDrawable(Drawable dr) {
+ if (dr == mDrawable) {
+ invalidate();
+ } else {
+ super.invalidateDrawable(dr);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 6db9bc3..4cf66a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,26 +16,49 @@
package com.android.systemui.statusbar.policy;
+import com.android.internal.app.IBatteryStats;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarHeaderView;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.format.Formatter;
+import android.util.Log;
import java.util.ArrayList;
public class BatteryController extends BroadcastReceiver {
private static final String TAG = "StatusBar.BatteryController";
-
private ArrayList<BatteryStateChangeCallback> mChangeCallbacks =
new ArrayList<BatteryStateChangeCallback>();
+ private Context mContext;
+ private StatusBarHeaderView mStatusBarHeaderView;
+ private IBatteryStats mBatteryInfo;
+
+ private int mLevel;
+ private boolean mPluggedIn;
+ private boolean mCharging;
+ private boolean mCharged;
+
+
public interface BatteryStateChangeCallback {
- public void onBatteryLevelChanged(int level, boolean pluggedIn);
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
}
public BatteryController(Context context) {
+ mContext = context;
+
+ mBatteryInfo = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
context.registerReceiver(this, filter);
@@ -45,24 +68,59 @@ public class BatteryController extends BroadcastReceiver {
mChangeCallbacks.add(cb);
}
+ public void setStatusBarHeaderView(StatusBarHeaderView statusBarHeaderView) {
+ mStatusBarHeaderView = statusBarHeaderView;
+ updateStatusBarHeaderView();
+ }
+
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+ mLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+ mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
+ mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
+ mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
- boolean plugged = false;
- switch (status) {
- case BatteryManager.BATTERY_STATUS_CHARGING:
- case BatteryManager.BATTERY_STATUS_FULL:
- plugged = true;
- break;
+ updateStatusBarHeaderView();
+ for (BatteryStateChangeCallback cb : mChangeCallbacks) {
+ cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
}
+ }
+ }
- for (BatteryStateChangeCallback cb : mChangeCallbacks) {
- cb.onBatteryLevelChanged(level, plugged);
+ private void updateStatusBarHeaderView() {
+ if (mStatusBarHeaderView != null) {
+ mStatusBarHeaderView.setShowChargingInfo(mPluggedIn);
+ mStatusBarHeaderView.setChargingInfo(computeChargingInfo());
+ }
+ }
+
+ private String computeChargingInfo() {
+ if (!mPluggedIn || !mCharged && !mCharging) {
+ return mContext.getResources().getString(R.string.expanded_header_battery_not_charging);
+ }
+
+ if (mCharged) {
+ return mContext.getResources().getString(R.string.expanded_header_battery_charged);
+ }
+
+ // Try fetching charging time from battery stats.
+ try {
+ long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
+ if (chargingTimeRemaining > 0) {
+ String chargingTimeFormatted =
+ Formatter.formatShortElapsedTime(mContext, chargingTimeRemaining);
+ return mContext.getResources().getString(
+ R.string.expanded_header_battery_charging_with_time, chargingTimeFormatted);
}
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IBatteryStats: ", e);
}
+
+ // Fall back to simple charging label.
+ return mContext.getResources().getString(R.string.expanded_header_battery_charging);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index cadb44a..f978833 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -29,8 +30,6 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
-import libcore.icu.ICU;
-
public class DateView extends TextView {
private static final String TAG = "DateView";
@@ -87,7 +86,7 @@ public class DateView extends TextView {
if (mDateFormat == null) {
final String dateFormat = getContext().getString(R.string.system_ui_date_pattern);
final Locale l = Locale.getDefault();
- final String fmt = ICU.getBestDateTimePattern(dateFormat, l.toString());
+ final String fmt = DateFormat.getBestDateTimePattern(l, dateFormat);
mDateFormat = new SimpleDateFormat(fmt, l);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 330b599..0134fe8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -63,6 +63,7 @@ public class KeyButtonView extends ImageView {
// Just an old-fashioned ImageView
performLongClick();
}
+ setPressed(false);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
new file mode 100644
index 0000000..c90750c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -0,0 +1,209 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarHeaderView;
+import com.android.systemui.statusbar.phone.UserAvatarView;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+import android.view.WindowManagerGlobal;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the user switcher on the Keyguard.
+ */
+public class KeyguardUserSwitcher implements View.OnClickListener {
+
+ private static final String TAG = "KeyguardUserSwitcher";
+
+ private final Context mContext;
+ private final ViewGroup mUserSwitcher;
+ private final UserManager mUserManager;
+ private final StatusBarHeaderView mHeader;
+
+ public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
+ StatusBarHeaderView header) {
+ mContext = context;
+ if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher)) {
+ mUserSwitcher = (ViewGroup) userSwitcher.inflate();
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mHeader = header;
+ refresh();
+ } else {
+ mUserSwitcher = null;
+ mUserManager = null;
+ mHeader = null;
+ }
+ }
+
+ public void setKeyguard(boolean keyguard) {
+ if (mUserSwitcher != null) {
+ // TODO: Cache showUserSwitcherOnKeyguard().
+ if (keyguard && showUserSwitcherOnKeyguard()) {
+ show();
+ refresh();
+ } else {
+ hide();
+ }
+ }
+ }
+
+ /**
+ * @return true if the user switcher should be shown on the lock screen.
+ * @see android.os.UserManager#isUserSwitcherEnabled()
+ */
+ private boolean showUserSwitcherOnKeyguard() {
+ // TODO: Set isEdu. The edu provisioning process can add settings to Settings.Global.
+ boolean isEdu = false;
+ if (isEdu) {
+ return true;
+ }
+ List<UserInfo> users = mUserManager.getUsers(true /* excludeDying */);
+ int N = users.size();
+ int switchableUsers = 0;
+ for (int i = 0; i < N; i++) {
+ if (users.get(i).supportsSwitchTo()) {
+ switchableUsers++;
+ }
+ }
+ return switchableUsers > 1;
+ }
+
+ public void show() {
+ if (mUserSwitcher != null) {
+ // TODO: animate
+ mUserSwitcher.setVisibility(View.VISIBLE);
+ mHeader.setKeyguardUserSwitcherShowing(true);
+ }
+ }
+
+ private void hide() {
+ if (mUserSwitcher != null) {
+ // TODO: animate
+ mUserSwitcher.setVisibility(View.GONE);
+ mHeader.setKeyguardUserSwitcherShowing(false);
+ }
+ }
+
+ private void refresh() {
+ if (mUserSwitcher != null) {
+ new AsyncTask<Void, Void, ArrayList<UserData>>() {
+ @Override
+ protected ArrayList<UserData> doInBackground(Void... params) {
+ return loadUsers();
+ }
+
+ @Override
+ protected void onPostExecute(ArrayList<UserData> userInfos) {
+ bind(userInfos);
+ }
+ }.execute((Void[]) null);
+ }
+ }
+
+ private void bind(ArrayList<UserData> userList) {
+ mUserSwitcher.removeAllViews();
+ int N = userList.size();
+ for (int i = 0; i < N; i++) {
+ mUserSwitcher.addView(inflateUser(userList.get(i)));
+ }
+ // TODO: add Guest
+ // TODO: add (+) button
+ }
+
+ private View inflateUser(UserData user) {
+ View v = LayoutInflater.from(mUserSwitcher.getContext()).inflate(
+ R.layout.keyguard_user_switcher_item, mUserSwitcher, false);
+ TextView name = (TextView) v.findViewById(R.id.name);
+ UserAvatarView picture = (UserAvatarView) v.findViewById(R.id.picture);
+ name.setText(user.userInfo.name);
+ picture.setActivated(user.isCurrent);
+ if (user.userInfo.isGuest()) {
+ picture.setDrawable(mContext.getResources().getDrawable(R.drawable.ic_account_circle));
+ } else {
+ picture.setBitmap(user.userIcon);
+ }
+ v.setOnClickListener(this);
+ v.setTag(user.userInfo);
+ // TODO: mark which user is current for accessibility.
+ return v;
+ }
+
+ @Override
+ public void onClick(View v) {
+ switchUser(((UserInfo)v.getTag()).id);
+ }
+
+ // TODO: Factor out logic below and share with QS implementation.
+
+ private ArrayList<UserData> loadUsers() {
+ ArrayList<UserInfo> users = (ArrayList<UserInfo>) mUserManager
+ .getUsers(true /* excludeDying */);
+ int N = users.size();
+ ArrayList<UserData> result = new ArrayList<>(N);
+ int currentUser = -1;
+ try {
+ currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couln't get current user.", e);
+ }
+ for (int i = 0; i < N; i++) {
+ UserInfo user = users.get(i);
+ if (user.supportsSwitchTo()) {
+ boolean isCurrent = user.id == currentUser;
+ result.add(new UserData(user, mUserManager.getUserIcon(user.id), isCurrent));
+ }
+ }
+ return result;
+ }
+
+ private void switchUser(int userId) {
+ try {
+ WindowManagerGlobal.getWindowManagerService().lockNow(null);
+ ActivityManagerNative.getDefault().switchUser(userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't switch user.", e);
+ }
+ }
+
+ private static class UserData {
+ final UserInfo userInfo;
+ final Bitmap userIcon;
+ final boolean isCurrent;
+
+ UserData(UserInfo userInfo, Bitmap userIcon, boolean isCurrent) {
+ this.userInfo = userInfo;
+ this.userIcon = userIcon;
+ this.isCurrent = isCurrent;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 254a0e8..4e54e41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -47,6 +47,7 @@ import com.android.internal.telephony.cdma.EriInfo;
import com.android.internal.util.AsyncChannel;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarHeaderView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -144,7 +145,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>();
ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>();
ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
- ArrayList<TextView> mEmergencyLabelViews = new ArrayList<TextView>();
+ ArrayList<StatusBarHeaderView> mEmergencyViews = new ArrayList<>();
ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
new ArrayList<NetworkSignalChangedCallback>();
@@ -262,8 +263,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
mWifiLabelViews.add(v);
}
- public void addEmergencyLabelView(TextView v) {
- mEmergencyLabelViews.add(v);
+ public void addEmergencyLabelView(StatusBarHeaderView v) {
+ mEmergencyViews.add(v);
}
public void addSignalCluster(SignalCluster cluster) {
@@ -1254,15 +1255,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
// e-call label
- N = mEmergencyLabelViews.size();
+ N = mEmergencyViews.size();
for (int i=0; i<N; i++) {
- TextView v = mEmergencyLabelViews.get(i);
- if (!emergencyOnly) {
- v.setVisibility(View.GONE);
- } else {
- v.setText(mobileLabel); // comes from the telephony stack
- v.setVisibility(View.VISIBLE);
- }
+ StatusBarHeaderView v = mEmergencyViews.get(i);
+ v.setShowEmergencyCallsOnly(emergencyOnly);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 6d92b05..fcc951e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -32,6 +32,7 @@ public class AmbientState {
private float mOverScrollTopAmount;
private float mOverScrollBottomAmount;
private int mSpeedBumpIndex = -1;
+ private float mScrimAmount;
public int getScrollY() {
return mScrollY;
@@ -85,6 +86,14 @@ public class AmbientState {
}
}
+ public void setScrimAmount(float scrimAmount) {
+ mScrimAmount = scrimAmount;
+ }
+
+ public float getScrimAmount() {
+ return mScrimAmount;
+ }
+
public float getOverScrollAmount(boolean top) {
return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4e1b686..f6e9aef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -541,8 +541,9 @@ public class NotificationStackScrollLayout extends ViewGroup
if (slidingChild.getVisibility() == GONE) {
continue;
}
- float top = slidingChild.getTranslationY();
- float bottom = top + slidingChild.getActualHeight();
+ float childTop = slidingChild.getTranslationY();
+ float top = childTop + slidingChild.getClipTopAmount();
+ float bottom = childTop + slidingChild.getActualHeight();
int left = slidingChild.getLeft();
int right = slidingChild.getRight();
@@ -762,11 +763,12 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
}
-
- mActivePointerId = INVALID_POINTER;
- endDrag();
}
+
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
}
+
break;
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged && getChildCount() > 0) {
@@ -968,7 +970,7 @@ public class NotificationStackScrollLayout extends ViewGroup
* @param animate Should an animation be performed.
*/
public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
- setOverScrollAmount(numPixels * getRubberBandFactor(), onTop, animate, true);
+ setOverScrollAmount(numPixels * getRubberBandFactor(onTop), onTop, animate, true);
}
/**
@@ -1004,7 +1006,7 @@ public class NotificationStackScrollLayout extends ViewGroup
if (animate) {
mStateAnimator.animateOverScrollToAmount(amount, onTop);
} else {
- setOverScrolledPixels(amount / getRubberBandFactor(), onTop);
+ setOverScrolledPixels(amount / getRubberBandFactor(onTop), onTop);
mAmbientState.setOverScrollAmount(amount, onTop);
if (onTop) {
notifyOverscrollTopListener(amount);
@@ -1226,13 +1228,14 @@ public class NotificationStackScrollLayout extends ViewGroup
mOwnScrollY -= (int) topAmount;
mDontReportNextOverScroll = true;
setOverScrollAmount(0, true, false);
- mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor()
+ mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
* mOverflingDistance + topAmount;
} else if (velocityY > 0 && bottomAmount > 0) {
mOwnScrollY += bottomAmount;
setOverScrollAmount(0, false, false);
- mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor()
- * mOverflingDistance + bottomAmount;
+ mMaxOverScroll = Math.abs(velocityY) / 1000f
+ * getRubberBandFactor(false /* onTop */) * mOverflingDistance
+ + bottomAmount;
} else {
// it will be set once we reach the boundary
mMaxOverScroll = 0.0f;
@@ -1274,7 +1277,10 @@ public class NotificationStackScrollLayout extends ViewGroup
return Math.max(desiredPadding, mIntrinsicPadding);
}
- private float getRubberBandFactor() {
+ private float getRubberBandFactor(boolean onTop) {
+ if (!onTop) {
+ return RUBBER_BAND_FACTOR_NORMAL;
+ }
if (mExpandedInThisMotion) {
return RUBBER_BAND_FACTOR_AFTER_EXPAND;
} else if (mIsExpansionChanging) {
@@ -1840,6 +1846,11 @@ public class NotificationStackScrollLayout extends ViewGroup
return true;
}
+ public void setScrimAlpha(float progress) {
+ mAmbientState.setScrimAmount(progress);
+ requestChildrenUpdate();
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index cbad9dc..9a4b798 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -154,6 +154,17 @@ public class StackScrollAlgorithm {
handleDraggedViews(ambientState, resultState, algorithmState);
updateDimmedActivated(ambientState, resultState, algorithmState);
updateClipping(resultState, algorithmState);
+ updateScrimAmount(resultState, algorithmState, ambientState.getScrimAmount());
+ }
+
+ private void updateScrimAmount(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState, float scrimAmount) {
+ int childCount = algorithmState.visibleChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ View child = algorithmState.visibleChildren.get(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ childViewState.scrimAmount = scrimAmount;
+ }
}
private void updateClipping(StackScrollState resultState,
@@ -587,6 +598,7 @@ public class StackScrollAlgorithm {
algorithmState.itemsInTopStack += algorithmState.partialInTop;
newSize = Math.max(mCollapsedSize, newSize);
if (i == 0) {
+ algorithmState.itemsInTopStack = 1.0f;
childViewState.height = (int) newSize;
}
algorithmState.lastTopStackIndex = i;
@@ -617,6 +629,20 @@ public class StackScrollAlgorithm {
if (i < algorithmState.itemsInTopStack) {
float stackIndex = algorithmState.itemsInTopStack - i;
stackIndex = Math.min(stackIndex, MAX_ITEMS_IN_TOP_STACK + 2);
+ if (i == 0 && algorithmState.itemsInTopStack < 2.0f) {
+
+ // We only have the top item and an additional item in the top stack,
+ // Interpolate the index from 0 to 2 while the second item is
+ // translating in.
+ stackIndex -= 1.0f;
+ if (algorithmState.scrollY > mCollapsedSize) {
+
+ // Since there is a shadow treshhold, we cant just interpolate from 0 to
+ // 2 but we interpolate from 0.1f to 2.0f when scrolled in. The jump in
+ // height will not be noticable since we have padding in between.
+ stackIndex = 0.1f + stackIndex * 1.9f;
+ }
+ }
childViewState.zTranslation = mZBasicHeight
+ stackIndex * mZDistanceBetweenElements;
} else if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 1ad4acc..02f2cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -148,6 +148,9 @@ public class StackScrollState {
// apply dimming
child.setDimmed(state.dimmed, false /* animate */);
+ // apply scrimming
+ child.setScrimAmount(state.scrimAmount);
+
float oldClipTopAmount = child.getClipTopAmount();
if (oldClipTopAmount != state.clipTopAmount) {
child.setClipTopAmount(state.clipTopAmount);
@@ -223,6 +226,12 @@ public class StackScrollState {
boolean dimmed;
/**
+ * A value between 0 and 1 indicating how much the view should be scrimmed.
+ * 1 means that the notifications will be darkened as much as possible.
+ */
+ float scrimAmount;
+
+ /**
* The amount which the view should be clipped from the top. This is calculated to
* perceive consistent shadows.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 225398a..0006dad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -176,6 +176,9 @@ public class StackStateAnimator {
// start dimmed animation
child.setDimmed(viewState.dimmed, mAnimationFilter.animateDimmed);
+ // apply scrimming
+ child.setScrimAmount(viewState.scrimAmount);
+
if (wasAdded) {
child.performAddAnimation(delay);
}
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 9260aac..e354166 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -47,27 +47,15 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
- public void addNotification(StatusBarNotification notification) {
+ public void addNotification(StatusBarNotification notification, RankingMap ranking) {
}
@Override
- public void addNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
+ protected void updateNotificationRanking(RankingMap ranking) {
}
@Override
- protected void updateRankingInternal(RankingMap ranking) {
- }
-
- @Override
- public void updateNotification(StatusBarNotification notification) {
- }
-
- @Override
- public void removeNotificationInternal(String key, RankingMap ranking) {
- }
-
- @Override
- public void removeNotification(String key) {
+ public void removeNotification(String key, RankingMap ranking) {
}
@Override