diff options
Diffstat (limited to 'packages')
129 files changed, 2786 insertions, 1760 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java index 5e565bf..7ea51b9 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java @@ -97,7 +97,6 @@ public class PickFragment extends Fragment { CharSequence displayName) { if (mContainer != null) { if (pickTarget != null) { - mContainer.setVisibility(View.VISIBLE); final Locale locale = getResources().getConfiguration().locale; switch (action) { case BaseActivity.State.ACTION_OPEN_TREE: @@ -112,7 +111,9 @@ public class PickFragment extends Fragment { default: throw new IllegalArgumentException("Illegal action for PickFragment."); } - + } + if (pickTarget != null && pickTarget.isCreateSupported()) { + mContainer.setVisibility(View.VISIBLE); } else { mContainer.setVisibility(View.GONE); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index a02fb4a..50c9f2d 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -783,21 +783,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private void startListeningForFingerprint() { if (DEBUG) Log.v(TAG, "startListeningForFingerprint()"); - final int userId; - try { - userId = ActivityManagerNative.getDefault().getCurrentUser().id; - } catch (RemoteException e) { - Log.e(TAG, "Failed to get current user id: ", e); - return; - } + int userId = ActivityManager.getCurrentUser(); if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId) - && mFpm.getEnrolledFingerprints().size() > 0) { + && mFpm.getEnrolledFingerprints(userId).size() > 0) { if (mFingerprintCancelSignal != null) { mFingerprintCancelSignal.cancel(); } mFingerprintCancelSignal = new CancellationSignal(); - mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, - ActivityManager.getCurrentUser()); + mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId); setFingerprintRunningDetectionRunning(true); } } diff --git a/packages/SystemUI/res/anim/heads_up_enter.xml b/packages/SystemUI/res/anim/heads_up_enter.xml deleted file mode 100644 index 59eef42..0000000 --- a/packages/SystemUI/res/anim/heads_up_enter.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android" - > - <translate - android:interpolator="@android:interpolator/overshoot" - android:fromYDelta="-50%" android:toYDelta="0" - android:duration="@android:integer/config_shortAnimTime" /> - <alpha - android:interpolator="@android:interpolator/decelerate_quad" - android:fromAlpha="0.0" android:toAlpha="1.0" - android:duration="@android:integer/config_shortAnimTime" /> -</set> diff --git a/packages/SystemUI/res/anim/heads_up_exit.xml b/packages/SystemUI/res/anim/heads_up_exit.xml deleted file mode 100644 index 2cad8f6..0000000 --- a/packages/SystemUI/res/anim/heads_up_exit.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<set xmlns:android="http://schemas.android.com/apk/res/android" - > - <translate - android:interpolator="@android:interpolator/overshoot" - android:fromYDelta="0" android:toYDelta="-50%" - android:duration="@android:integer/config_shortAnimTime" /> - <alpha - android:interpolator="@android:interpolator/accelerate_quad" - android:fromAlpha="1.0" android:toAlpha="0.0" - android:duration="@android:integer/config_shortAnimTime" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml new file mode 100644 index 0000000..57b61da --- /dev/null +++ b/packages/SystemUI/res/anim/ic_qs_signal_blink_1.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="#FFFFFFFF"/> + <keyframe + android:fraction="0.32" + android:value="#FFFFFFFF"/> + <keyframe + android:fraction="0.33" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="1.0" + android:value="#4DFFFFFF"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml new file mode 100644 index 0000000..09694c3 --- /dev/null +++ b/packages/SystemUI/res/anim/ic_qs_signal_blink_2.xml @@ -0,0 +1,44 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="0.32" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="0.33" + android:value="#FFFFFFFF"/> + <keyframe + android:fraction="0.66" + android:value="#FFFFFFFF"/> + <keyframe + android:fraction="0.67" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="1.0" + android:value="#4DFFFFFF"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml b/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml new file mode 100644 index 0000000..2270e3f --- /dev/null +++ b/packages/SystemUI/res/anim/ic_qs_signal_blink_3.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="0.66" + android:value="#4DFFFFFF"/> + <keyframe + android:fraction="0.67" + android:value="#FFFFFFFF"/> + <keyframe + android:fraction="1.0" + android:value="#FFFFFFFF"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_1.xml b/packages/SystemUI/res/anim/ic_signal_blink_1.xml new file mode 100644 index 0000000..ab1905a --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_blink_1.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.32" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.33" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="1.0" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_2.xml b/packages/SystemUI/res/anim/ic_signal_blink_2.xml new file mode 100644 index 0000000..1b7ace2 --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_blink_2.xml @@ -0,0 +1,44 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.32" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.33" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.66" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.67" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="1.0" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_3.xml b/packages/SystemUI/res/anim/ic_signal_blink_3.xml new file mode 100644 index 0000000..cee831c --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_blink_3.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.66" + android:value="@color/light_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.67" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="1.0" + android:value="@color/light_mode_icon_color_dual_tone_fill"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_dark_blink_1.xml b/packages/SystemUI/res/anim/ic_signal_dark_blink_1.xml new file mode 100644 index 0000000..9d398fa --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_dark_blink_1.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.32" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.33" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="1.0" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_dark_blink_2.xml b/packages/SystemUI/res/anim/ic_signal_dark_blink_2.xml new file mode 100644 index 0000000..c6e213d --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_dark_blink_2.xml @@ -0,0 +1,44 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.32" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.33" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.66" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="0.67" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="1.0" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_dark_blink_3.xml b/packages/SystemUI/res/anim/ic_signal_dark_blink_3.xml new file mode 100644 index 0000000..dce148c --- /dev/null +++ b/packages/SystemUI/res/anim/ic_signal_dark_blink_3.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2015 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. +--> +<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/linear_interpolator" + android:duration="@integer/carrier_network_change_anim_time" + android:repeatCount="-1"> + + <propertyValuesHolder + android:propertyName="fillColor" + android:valueType="colorType"> + <keyframe + android:fraction="0.0" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.66" + android:value="@color/dark_mode_icon_color_dual_tone_background"/> + <keyframe + android:fraction="0.67" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + <keyframe + android:fraction="1.0" + android:value="@color/dark_mode_icon_color_dual_tone_fill"/> + </propertyValuesHolder> + +</objectAnimator> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml new file mode 100644 index 0000000..96e2fd4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml @@ -0,0 +1,36 @@ +<!-- + Copyright (C) 2015 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" + android:width="32dp" + android:height="32dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:name="dot1" + android:fillColor="#FFFFFFFF" + android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:name="dot2" + android:fillColor="#4DFFFFFF" + android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:name="dot3" + android:fillColor="#4DFFFFFF" + android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:fillColor="#4DFFFFFF" + android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml new file mode 100644 index 0000000..2186aa8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml @@ -0,0 +1,27 @@ +<!-- + Copyright (C) 2015 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. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_qs_signal_carrier_network_change" > + <target + android:name="dot1" + android:animation="@anim/ic_qs_signal_blink_1"/> + <target + android:name="dot2" + android:animation="@anim/ic_qs_signal_blink_2"/> + <target + android:name="dot3" + android:animation="@anim/ic_qs_signal_blink_3"/> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml new file mode 100644 index 0000000..f69ffe4 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml @@ -0,0 +1,36 @@ +<!-- + Copyright (C) 2015 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" + android:width="17dp" + android:height="17dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:name="dot1" + android:fillColor="?attr/fillColor" + android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:name="dot2" + android:fillColor="?attr/backgroundColor" + android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:name="dot3" + android:fillColor="?attr/backgroundColor" + android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> + <path + android:fillColor="?attr/backgroundColor" + android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml new file mode 100644 index 0000000..275f037 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml @@ -0,0 +1,27 @@ +<!-- + Copyright (C) 2015 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. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/stat_sys_signal_carrier_network_change" > + <target + android:name="dot1" + android:animation="@anim/ic_signal_blink_1"/> + <target + android:name="dot2" + android:animation="@anim/ic_signal_blink_2"/> + <target + android:name="dot3" + android:animation="@anim/ic_signal_blink_3"/> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_dark_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/stat_sys_signal_dark_carrier_network_change_animation.xml new file mode 100644 index 0000000..ff49d4c --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_signal_dark_carrier_network_change_animation.xml @@ -0,0 +1,27 @@ +<!-- + Copyright (C) 2015 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. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/stat_sys_signal_carrier_network_change" > + <target + android:name="dot1" + android:animation="@anim/ic_signal_dark_blink_1"/> + <target + android:name="dot2" + android:animation="@anim/ic_signal_dark_blink_2"/> + <target + android:name="dot3" + android:animation="@anim/ic_signal_dark_blink_3"/> +</animated-vector> diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml deleted file mode 100644 index 650ee5d..0000000 --- a/packages/SystemUI/res/layout/heads_up.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?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. ---> -<!-- extends FrameLayout --> -<com.android.systemui.statusbar.policy.HeadsUpNotificationView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="match_parent" - android:layout_width="match_parent" - android:background="@drawable/heads_up_scrim"> - - <FrameLayout - android:layout_width="@dimen/notification_panel_width" - android:layout_height="wrap_content" - android:layout_gravity="@integer/notification_panel_layout_gravity" - android:paddingStart="@dimen/notification_side_padding" - android:paddingEnd="@dimen/notification_side_padding" - android:elevation="8dp" - android:id="@+id/content_holder" /> - -</com.android.systemui.statusbar.policy.HeadsUpNotificationView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 532e1b7..539aabf 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -46,6 +46,13 @@ android:layout_height="match_parent" android:importantForAccessibility="no" /> + <com.android.systemui.statusbar.AlphaOptimizedView + android:id="@+id/heads_up_scrim" + android:layout_width="match_parent" + android:layout_height="@dimen/heads_up_scrim_height" + android:background="@drawable/heads_up_scrim" + android:importantForAccessibility="no"/> + <include layout="@layout/status_bar" android:layout_width="match_parent" android:layout_height="@dimen/status_bar_height" /> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index bba8a6d..1f13404 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Weier"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen-kenmerk"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 06e9fb2..a631b90 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ከልክል"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index ac86dbd..dfaf408 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -403,7 +403,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رفض"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 64e5afa..6bd9969 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Отказване"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml index dd83d59..8f057e4 100644 --- a/packages/SystemUI/res/values-bn-rBD/strings.xml +++ b/packages/SystemUI/res/values-bn-rBD/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"প্রত্যাখ্যান করুন"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index eda024d..706086a 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denega"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 7abcc11..de7c62a 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -403,7 +403,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmítnout"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 3d0a0b0..99fc264 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afvis"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index f77da12..eb0ea2c 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ablehnen"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index e1e8ba3..e4c85c1 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 9e76616..aadd011 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -167,8 +167,7 @@ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Lock screen."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"Settings"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Overview."</string> - <!-- no translation found for accessibility_desc_confirm (3446792278337969766) --> - <skip /> + <string name="accessibility_desc_confirm" msgid="3446792278337969766">"Confirm"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi turned off."</string> @@ -303,10 +302,8 @@ <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string> - <!-- no translation found for zen_priority_introduction (7253045784560169993) --> - <skip /> - <!-- no translation found for zen_priority_customize_button (7948043278226955063) --> - <skip /> + <string name="zen_priority_introduction" msgid="7253045784560169993">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers that you specify."</string> + <string name="zen_priority_customize_button" msgid="7948043278226955063">"Customise"</string> <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string> <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string> <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string> @@ -342,12 +339,9 @@ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Yes, continue"</string> - <!-- no translation found for guest_notification_title (1585278533840603063) --> - <skip /> - <!-- no translation found for guest_notification_text (7513706222848825467) --> - <skip /> - <!-- no translation found for guest_notification_remove_action (8820670703892101990) --> - <skip /> + <string name="guest_notification_title" msgid="1585278533840603063">"Guest user"</string> + <string name="guest_notification_text" msgid="7513706222848825467">"Remove guest to delete apps and data"</string> + <string name="guest_notification_remove_action" msgid="8820670703892101990">"REMOVE GUEST"</string> <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string> <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string> @@ -399,7 +393,5 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> - <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> - <skip /> + <string name="managed_profile_foreground_toast" msgid="3199278359979281097">"You are in the Work profile"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 9e76616..aadd011 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -167,8 +167,7 @@ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Lock screen."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"Settings"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Overview."</string> - <!-- no translation found for accessibility_desc_confirm (3446792278337969766) --> - <skip /> + <string name="accessibility_desc_confirm" msgid="3446792278337969766">"Confirm"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi turned off."</string> @@ -303,10 +302,8 @@ <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string> - <!-- no translation found for zen_priority_introduction (7253045784560169993) --> - <skip /> - <!-- no translation found for zen_priority_customize_button (7948043278226955063) --> - <skip /> + <string name="zen_priority_introduction" msgid="7253045784560169993">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers that you specify."</string> + <string name="zen_priority_customize_button" msgid="7948043278226955063">"Customise"</string> <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string> <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string> <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string> @@ -342,12 +339,9 @@ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Yes, continue"</string> - <!-- no translation found for guest_notification_title (1585278533840603063) --> - <skip /> - <!-- no translation found for guest_notification_text (7513706222848825467) --> - <skip /> - <!-- no translation found for guest_notification_remove_action (8820670703892101990) --> - <skip /> + <string name="guest_notification_title" msgid="1585278533840603063">"Guest user"</string> + <string name="guest_notification_text" msgid="7513706222848825467">"Remove guest to delete apps and data"</string> + <string name="guest_notification_remove_action" msgid="8820670703892101990">"REMOVE GUEST"</string> <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string> <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string> @@ -399,7 +393,5 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> - <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> - <skip /> + <string name="managed_profile_foreground_toast" msgid="3199278359979281097">"You are in the Work profile"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 9e76616..aadd011 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -167,8 +167,7 @@ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Lock screen."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"Settings"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Overview."</string> - <!-- no translation found for accessibility_desc_confirm (3446792278337969766) --> - <skip /> + <string name="accessibility_desc_confirm" msgid="3446792278337969766">"Confirm"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wi-Fi turned off."</string> @@ -303,10 +302,8 @@ <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string> - <!-- no translation found for zen_priority_introduction (7253045784560169993) --> - <skip /> - <!-- no translation found for zen_priority_customize_button (7948043278226955063) --> - <skip /> + <string name="zen_priority_introduction" msgid="7253045784560169993">"You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events and callers that you specify."</string> + <string name="zen_priority_customize_button" msgid="7948043278226955063">"Customise"</string> <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string> <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string> <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string> @@ -342,12 +339,9 @@ <string name="guest_wipe_session_message" msgid="8476238178270112811">"Do you want to continue your session?"</string> <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Start again"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Yes, continue"</string> - <!-- no translation found for guest_notification_title (1585278533840603063) --> - <skip /> - <!-- no translation found for guest_notification_text (7513706222848825467) --> - <skip /> - <!-- no translation found for guest_notification_remove_action (8820670703892101990) --> - <skip /> + <string name="guest_notification_title" msgid="1585278533840603063">"Guest user"</string> + <string name="guest_notification_text" msgid="7513706222848825467">"Remove guest to delete apps and data"</string> + <string name="guest_notification_remove_action" msgid="8820670703892101990">"REMOVE GUEST"</string> <string name="user_add_user_title" msgid="4553596395824132638">"Add new user?"</string> <string name="user_add_user_message_short" msgid="2161624834066214559">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string> @@ -399,7 +393,5 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> - <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> - <skip /> + <string name="managed_profile_foreground_toast" msgid="3199278359979281097">"You are in the Work profile"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 40400f3..e754925 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index cb061a5..c131176 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml index 7fffec7..387fe82 100644 --- a/packages/SystemUI/res/values-et-rEE/strings.xml +++ b/packages/SystemUI/res/values-et-rEE/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Keela"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml index 94dd6b1..d8c1789 100644 --- a/packages/SystemUI/res/values-eu-rES/strings.xml +++ b/packages/SystemUI/res/values-eu-rES/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ukatu"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 0260d3a..7594ad9 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رد کردن"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترلکننده اصلی، لمس کنید."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 156bbb7..a131701 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Estä"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index de5b7aa..9d10e48 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index ed17e4af..2788a87 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml index 89d5fc3..a4786df 100644 --- a/packages/SystemUI/res/values-gl-rES/strings.xml +++ b/packages/SystemUI/res/values-gl-rES/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denegar"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 08fbe69..7d6f51b 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार करें"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल वॉल्यूम को फिर से लाने के लिए स्पर्श करें."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 85bb634..7ea2336 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -400,7 +400,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odbij"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 0773849..f674327 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Elutasítás"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml index 3ffc030..c3d0f6d 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Մերժել"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index edee7c6..f53cecc 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml index 660834e..8000344 100644 --- a/packages/SystemUI/res/values-is-rIS/strings.xml +++ b/packages/SystemUI/res/values-is-rIS/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Hafna"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index a7ac816..a0ceb62 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Nega"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 837bba7..b02ff0a 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"דחה"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index e01fe53..f8f767b 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"許可しない"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml index a41c9f5..4377663 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"უარყოფა"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml index 0beea99..c4141e1 100644 --- a/packages/SystemUI/res/values-kk-rKZ/strings.xml +++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Өшіру"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index ba84a54..8087373 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"បដិសេធ"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml index 76b5707..fe138ce 100644 --- a/packages/SystemUI/res/values-kn-rIN/strings.xml +++ b/packages/SystemUI/res/values-kn-rIN/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ನಿರಾಕರಿಸು"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 32f751f..c525095 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"거부"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"원본을 복원하려면 터치하세요."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml index 8e2defd..eca5b2c 100644 --- a/packages/SystemUI/res/values-ky-rKG/strings.xml +++ b/packages/SystemUI/res/values-ky-rKG/strings.xml @@ -424,7 +424,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Жок"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index d7bb83b..8ce9eda 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ປະຕິເສດ"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນໜ້າຕ່າງລະດັບສຽງ"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"ສໍາຜັດເພື່ອກູ້ຄືນຕົ້ນສະບັບ."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 2ac4636..7e211cd 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Atmesti"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index a184664..c692791 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -400,7 +400,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neatļaut"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml index e288451..b13a58a 100644 --- a/packages/SystemUI/res/values-mk-rMK/strings.xml +++ b/packages/SystemUI/res/values-mk-rMK/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml index 3bc27a1..e0d3eaf 100644 --- a/packages/SystemUI/res/values-ml-rIN/strings.xml +++ b/packages/SystemUI/res/values-ml-rIN/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"നിരസിക്കുക"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"ആദ്യത്തേത് പുനഃസ്ഥാപിക്കാൻ സ്പർശിക്കുക."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml index 367de5d..b68af61 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings.xml @@ -397,7 +397,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Татгалзах"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Анхны хувилбарыг эргүүлэн хадгалахыг хүсвэл хүрнэ үү."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml index eb8c6ad..c9dd37e 100644 --- a/packages/SystemUI/res/values-mr-rIN/strings.xml +++ b/packages/SystemUI/res/values-mr-rIN/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"नकार द्या"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index 1b1fded..f5624a0 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:rentetan/nama_ciri_mod_zen"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml index 52c4298..f0aa3b1 100644 --- a/packages/SystemUI/res/values-my-rMM/strings.xml +++ b/packages/SystemUI/res/values-my-rMM/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ငြင်းပယ်သည်"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 2168f14..ef64990 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ikke tillat"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml index 11e19e7..1561177 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार गर्नुहोस्"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुनर्स्थापना गर्न छुनुहोस्।"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*Android: स्ट्रिङ/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 06ed986..24ace95 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afwijzen"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index ffeff1e..02c1d74 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmów"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 23413be..2b802c0 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Recusar"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index caf85cc..8d82942 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 509ae92..06d9ac2 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -400,7 +400,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzați"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 1c584fe..b6c506f 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -403,7 +403,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Нет"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml index 9643102..1e1d981 100644 --- a/packages/SystemUI/res/values-si-rLK/strings.xml +++ b/packages/SystemUI/res/values-si-rLK/strings.xml @@ -167,8 +167,7 @@ <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"අගුළු තිරය."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"සැකසීම්"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"දළ විශ්ලේෂණය."</string> - <!-- no translation found for accessibility_desc_confirm (3446792278337969766) --> - <skip /> + <string name="accessibility_desc_confirm" msgid="3446792278337969766">"තහවුරු කරන්න"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"පරිශීලකයා <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi අක්රියයි."</string> @@ -303,10 +302,8 @@ <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> <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"අතුරු බිඳීම් නැත. අඩුම තරමේ අනතුරු ඇඟවීමක්වත් නැත."</string> - <!-- no translation found for zen_priority_introduction (7253045784560169993) --> - <skip /> - <!-- no translation found for zen_priority_customize_button (7948043278226955063) --> - <skip /> + <string name="zen_priority_introduction" msgid="7253045784560169993">"සීනු, සිහි කැඳවීම්, සිදුවීම් සහ ඔබ සඳහන් කරන අමතන්නන් හැර වෙනත් ශබ්ද සහ කම්පන වලින් ඔබව බාධා නොකරයි."</string> + <string name="zen_priority_customize_button" msgid="7948043278226955063">"අභිරුචිකරණය"</string> <string name="zen_no_interruptions" msgid="7970973750143632592">"අතුරු බිදුම් නැත"</string> <string name="zen_important_interruptions" msgid="3477041776609757628">"ප්රමුඛ අතුරු බිඳීම් පමණයි"</string> <string name="zen_alarms" msgid="5055668280767657759">"ඇඟවීම් පමණි"</string> @@ -342,12 +339,9 @@ <string name="guest_wipe_session_message" msgid="8476238178270112811">"ඔබගේ සැසිය දිගටම කරගෙන යෑමට ඔබට අවශ්යද?"</string> <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"යළි මුල සිට අරඹන්න"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"ඔව්, දිගටම කරගෙන යන්න"</string> - <!-- no translation found for guest_notification_title (1585278533840603063) --> - <skip /> - <!-- no translation found for guest_notification_text (7513706222848825467) --> - <skip /> - <!-- no translation found for guest_notification_remove_action (8820670703892101990) --> - <skip /> + <string name="guest_notification_title" msgid="1585278533840603063">"ආගන්තුක පරිශිලකයා"</string> + <string name="guest_notification_text" msgid="7513706222848825467">"යෙදුම් සහ දත්ත ඉවත් කිරීමට ආගන්තුකයා ඉවත් කරන්න"</string> + <string name="guest_notification_remove_action" msgid="8820670703892101990">"ආගන්තුකයා ඉවත් කරන්නද?"</string> <string name="user_add_user_title" msgid="4553596395824132638">"අලුත් පරිශීලකයෙක් එකතු කරන්නද?"</string> <string name="user_add_user_message_short" msgid="2161624834066214559">"ඔබ අලුත් පරිශීලකයෙක් එකතු කරන විට, එම පුද්ගලයා ඔහුගේ වැඩ කරන ඉඩ සකසා ගත යුතුය.\n\nසියළුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යාවත්කාලීන කළ හැක."</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"බැටරිය සුරකින්නා සක්රීයයි"</string> @@ -399,7 +393,5 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ප්රතික්ෂේප කරන්න"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්ත්වය නැවත ප්රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> - <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> - <skip /> + <string name="managed_profile_foreground_toast" msgid="3199278359979281097">"ඔබ කාර්යාල පැතිකඩේ සිටියි"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index d826901..72e30b5 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -403,7 +403,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmietnuť"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index a7eca4d..2c8e221 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Zavrni"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index edb1166..a51f8ad 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -400,7 +400,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index ee03be4..ccf94eb 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neka"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 2ac3926..c01d0ac 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Kataa"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml index a8177de..2632a81 100644 --- a/packages/SystemUI/res/values-ta-rIN/strings.xml +++ b/packages/SystemUI/res/values-ta-rIN/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"நிராகரி"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml index 009eddb..8fe687e 100644 --- a/packages/SystemUI/res/values-te-rIN/strings.xml +++ b/packages/SystemUI/res/values-te-rIN/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"తిరస్కరించు"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index bd0f58e..48b0a38 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ปฏิเสธ"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index b8858af..9c5daa8 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tanggihan"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 1b0d11f..7c44bf1 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Reddet"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinali geri yüklemek için dokunun."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index c5ebd3a..76ed716 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Відхилити"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml index c01a197..608c6d3 100644 --- a/packages/SystemUI/res/values-ur-rPK/strings.xml +++ b/packages/SystemUI/res/values-ur-rPK/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"مسترد کریں"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"اصل کو بحال کرنے کیلئے ٹچ کریں۔"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml index 37e9542..63af257 100644 --- a/packages/SystemUI/res/values-uz-rUZ/strings.xml +++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rad etish"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 3c2d0ef..a434168 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Từ chối"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 32e7735..4e3c265 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒绝"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"触摸即可恢复原始设置。"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index bf8dfb2..d6be63f 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index f9b33ca..ddab028 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -401,7 +401,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸這裡即可恢復原始設定。"</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 9a32c4b..e91577d 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -399,7 +399,6 @@ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Phika"</string> <string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string> <string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string> - <string name="volume_zen_switch_text" msgid="8149183012610587643">"@*android:string/zen_mode_feature_name"</string> <!-- no translation found for managed_profile_foreground_toast (3199278359979281097) --> <skip /> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 2e9e9f7..88bf58a 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -147,7 +147,7 @@ <integer name="heads_up_default_snooze_length_ms">60000</integer> <!-- Minimum display time for a heads up notification, in milliseconds. --> - <integer name="heads_up_notification_minimum_time">3000</integer> + <integer name="heads_up_notification_minimum_time">2000</integer> <!-- milliseconds before the heads up notification accepts touches. --> <integer name="heads_up_sensitivity_delay">700</integer> @@ -293,5 +293,8 @@ <!-- Enable the default volume dialog --> <bool name="enable_volume_ui">true</bool> + + <!-- Duration of the full carrier network change icon animation. --> + <integer name="carrier_network_change_anim_time">3000</integer> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b6ff1ce..9e084a0 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -330,7 +330,7 @@ keyguard_clock_height_fraction_* for the difference between min and max.--> <dimen name="keyguard_clock_notifications_margin_min">24dp</dimen> <dimen name="keyguard_clock_notifications_margin_max">36dp</dimen> - <dimen name="heads_up_window_height">250dp</dimen> + <dimen name="heads_up_scrim_height">250dp</dimen> <!-- The minimum amount the user needs to swipe to go to the camera / phone. --> <dimen name="keyguard_min_swipe_amount">110dp</dimen> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 3fc75d2..6d84727 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -37,6 +37,8 @@ <item type="id" name="doze_saved_filter_tag"/> <item type="id" name="qs_icon_tag"/> <item type="id" name="scrim"/> + <item type="id" name="hun_scrim_alpha_start"/> + <item type="id" name="hun_scrim_alpha_end"/> <item type="id" name="notification_power"/> <item type="id" name="notification_screenshot"/> <item type="id" name="notification_hidden"/> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ae134c6..67a0bc6 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -359,6 +359,9 @@ <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_airplane_mode">Airplane mode.</string> + <!-- Content description of the carrier network changing icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_carrier_network_change_mode">Carrier network changing.</string> + <!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string> @@ -998,7 +1001,7 @@ <string name="volumeui_notification_text">Touch to restore the original.</string> <!-- Volume dialog zen toggle switch title --> - <string name="volume_zen_switch_text">@*android:string/zen_mode_feature_name</string> + <string name="volume_zen_switch_text" translatable="false">@*android:string/zen_mode_feature_name</string> <!-- Toast shown when user unlocks screen and managed profile activity is in the foreground --> <string name="managed_profile_foreground_toast">You are in the Work profile</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 974cc48..87f9ca2 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -205,11 +205,6 @@ <style name="Animation.StatusBar"> </style> - <style name="Animation.StatusBar.HeadsUp"> - <item name="android:windowEnterAnimation">@anim/heads_up_enter</item> - <item name="android:windowExitAnimation">@anim/heads_up_exit</item> - </style> - <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault"> <item name="android:colorPrimary">@color/system_primary_color</item> <item name="android:colorControlActivated">@color/system_accent_color</item> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index bc7f745..fece07f 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -322,6 +322,10 @@ public class ExpandHelper implements Gefingerpoken { isInside(mScrollAdapter.getHostView(), x, y) && mScrollAdapter.isScrolledToTop(); mResizedView = findView(x, y); + if (mResizedView != null && !mCallback.canChildBeExpanded(mResizedView)) { + mResizedView = null; + mWatchingForPull = false; + } mInitialTouchY = ev.getY(); break; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 065d62e..97a4c55 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -867,6 +867,12 @@ public class KeyguardViewMediator extends SystemUI { */ private void handleSetOccluded(boolean isOccluded) { synchronized (KeyguardViewMediator.this) { + if (mHiding && isOccluded) { + // We're in the process of going away but WindowManager wants to show a + // SHOW_WHEN_LOCKED activity instead. + startKeyguardExitAnimation(0, 0); + } + if (mOccluded != isOccluded) { mOccluded = isOccluded; mStatusBarKeyguardViewManager.setOccluded(isOccluded); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index 1790a4e..5a84db5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -18,6 +18,7 @@ package com.android.systemui.qs; import android.content.Context; import android.content.Intent; +import android.graphics.drawable.Animatable; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; @@ -325,7 +326,7 @@ public abstract class QSTile<TState extends State> implements Listenable { public static class ResourceIcon extends Icon { private static final SparseArray<Icon> ICONS = new SparseArray<Icon>(); - private final int mResId; + protected final int mResId; private ResourceIcon(int resId) { mResId = resId; @@ -342,7 +343,11 @@ public abstract class QSTile<TState extends State> implements Listenable { @Override public Drawable getDrawable(Context context) { - return context.getDrawable(mResId); + Drawable d = context.getDrawable(mResId); + if (d instanceof Animatable) { + ((Animatable) d).start(); + } + return d; } @Override @@ -370,7 +375,7 @@ public abstract class QSTile<TState extends State> implements Listenable { @Override public Drawable getDrawable(Context context) { // workaround: get a clean state for every new AVD - final AnimatedVectorDrawable d = (AnimatedVectorDrawable) super.getDrawable(context) + final AnimatedVectorDrawable d = (AnimatedVectorDrawable) context.getDrawable(mResId) .getConstantState().newDrawable(); d.start(); if (mAllowAnimation) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index ec83ca7..af9d3a5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -38,6 +38,7 @@ import android.widget.TextView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; +import com.android.systemui.qs.QSTile.AnimationIcon; import com.android.systemui.qs.QSTile.State; import java.util.Objects; @@ -315,8 +316,9 @@ public class QSTileView extends ViewGroup { iv.setImageDrawable(d); iv.setTag(R.id.qs_icon_tag, state.icon); if (d instanceof Animatable) { - if (!iv.isShown()) { - ((Animatable) d).stop(); // skip directly to end state + Animatable a = (Animatable) d; + if (state.icon instanceof AnimationIcon && !iv.isShown()) { + a.stop(); // skip directly to end state } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index ee607a7..9f86475 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -96,7 +96,7 @@ import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.phone.NavigationBarView; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.policy.HeadsUpNotificationView; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.PreviewInflater; import com.android.systemui.statusbar.policy.RemoteInputView; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; @@ -130,9 +130,6 @@ public abstract class BaseStatusBar extends SystemUI implements protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023; protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024; protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025; - protected static final int MSG_SHOW_HEADS_UP = 1028; - protected static final int MSG_HIDE_HEADS_UP = 1029; - protected static final int MSG_ESCALATE_HEADS_UP = 1030; protected static final boolean ENABLE_HEADS_UP = true; // scores above this threshold should be displayed in heads up mode. @@ -158,8 +155,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected NotificationGroupManager mGroupManager = new NotificationGroupManager(); // for heads up notifications - protected HeadsUpNotificationView mHeadsUpNotificationView; - protected int mHeadsUpNotificationDecay; + protected HeadsUpManager mHeadsUpManager; protected int mCurrentUserId = 0; final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>(); @@ -446,9 +442,8 @@ public abstract class BaseStatusBar extends SystemUI implements @Override public void run() { processForRemoteInput(sbn.getNotification()); - Notification n = sbn.getNotification(); - boolean isUpdate = mNotificationData.get(sbn.getKey()) != null - || isHeadsUp(sbn.getKey()); + String key = sbn.getKey(); + boolean isUpdate = mNotificationData.get(key) != null; // In case we don't allow child notifications, we ignore children of // notifications that have a summary, since we're not going to show them @@ -462,7 +457,7 @@ public abstract class BaseStatusBar extends SystemUI implements // Remove existing notification to avoid stale data. if (isUpdate) { - removeNotification(sbn.getKey(), rankingMap); + removeNotification(key, rankingMap); } else { mNotificationData.updateRanking(rankingMap); } @@ -693,13 +688,11 @@ public abstract class BaseStatusBar extends SystemUI implements } private void setHeadsUpUser(int newUserId) { - if (mHeadsUpNotificationView != null) { - mHeadsUpNotificationView.setUser(newUserId); - } + mHeadsUpManager.setUser(newUserId); } public boolean isHeadsUp(String key) { - return mHeadsUpNotificationView != null && mHeadsUpNotificationView.isShowing(key); + return mHeadsUpManager.isHeadsUp(key); } @Override // NotificationData.Environment @@ -758,8 +751,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected View updateNotificationVetoButton(View row, StatusBarNotification n) { View vetoButton = row.findViewById(R.id.veto); - if (n.isClearable() || (mHeadsUpNotificationView.getEntry() != null - && mHeadsUpNotificationView.getEntry().row == row)) { + if (n.isClearable()) { final String _pkg = n.getPackageName(); final String _tag = n.getTag(); final int _id = n.getId(); @@ -1002,9 +994,6 @@ public abstract class BaseStatusBar extends SystemUI implements } } - public void onHeadsUpDismissed() { - } - @Override public void showRecentApps(boolean triggeredFromAltTab) { int msg = MSG_SHOW_RECENT_APPS; @@ -1141,13 +1130,10 @@ public abstract class BaseStatusBar extends SystemUI implements // Do nothing } - public abstract void scheduleHeadsUpDecay(long delay); - - public abstract void scheduleHeadsUpOpen(); - - public abstract void scheduleHeadsUpClose(); - - public abstract void scheduleHeadsUpEscalation(); + /** + * if the interrupting notification had a fullscreen intent, fire it now. + */ + public abstract void escalateHeadsUp(); /** * Save the current "public" (locked and secure) state of the lockscreen. @@ -1238,15 +1224,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected void workAroundBadLayerDrawableOpacity(View v) { } - protected boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) { - return inflateViews(entry, parent, false); - } - - protected boolean inflateViewsForHeadsUp(NotificationData.Entry entry, ViewGroup parent) { - return inflateViews(entry, parent, true); - } - - private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent, boolean isHeadsUp) { + protected boolean inflateViews(Entry entry, ViewGroup parent) { PackageManager pmUser = getPackageManagerForUser( entry.notification.getUser().getIdentifier()); @@ -1254,12 +1232,7 @@ public abstract class BaseStatusBar extends SystemUI implements final StatusBarNotification sbn = entry.notification; RemoteViews contentView = sbn.getNotification().contentView; RemoteViews bigContentView = sbn.getNotification().bigContentView; - - if (isHeadsUp) { - maxHeight = - mContext.getResources().getDimensionPixelSize(R.dimen.notification_mid_height); - bigContentView = sbn.getNotification().headsUpContentView; - } + RemoteViews headsUpContentView = sbn.getNotification().headsUpContentView; if (contentView == null) { return false; @@ -1284,7 +1257,6 @@ public abstract class BaseStatusBar extends SystemUI implements hasUserChangedExpansion = row.hasUserChangedExpansion(); userExpanded = row.isUserExpanded(); userLocked = row.isUserLocked(); - entry.row.setHeadsUp(isHeadsUp); entry.reset(); if (hasUserChangedExpansion) { row.setUserExpanded(userExpanded); @@ -1307,10 +1279,8 @@ public abstract class BaseStatusBar extends SystemUI implements // NB: the large icon is now handled entirely by the template // bind the click event to the content area - NotificationContentView expanded = - (NotificationContentView) row.findViewById(R.id.expanded); - NotificationContentView expandedPublic = - (NotificationContentView) row.findViewById(R.id.expandedPublic); + NotificationContentView contentContainer = row.getPrivateLayout(); + NotificationContentView contentContainerPublic = row.getPublicLayout(); row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); if (ENABLE_REMOTE_INPUT) { @@ -1328,11 +1298,16 @@ public abstract class BaseStatusBar extends SystemUI implements // set up the adaptive layout View contentViewLocal = null; View bigContentViewLocal = null; + View headsUpContentViewLocal = null; try { - contentViewLocal = contentView.apply(mContext, expanded, + contentViewLocal = contentView.apply(mContext, contentContainer, mOnClickHandler); if (bigContentView != null) { - bigContentViewLocal = bigContentView.apply(mContext, expanded, + bigContentViewLocal = bigContentView.apply(mContext, contentContainer, + mOnClickHandler); + } + if (headsUpContentView != null) { + headsUpContentViewLocal = headsUpContentView.apply(mContext, contentContainer, mOnClickHandler); } } @@ -1344,23 +1319,27 @@ public abstract class BaseStatusBar extends SystemUI implements if (contentViewLocal != null) { contentViewLocal.setIsRootNamespace(true); - expanded.setContractedChild(contentViewLocal); + contentContainer.setContractedChild(contentViewLocal); } if (bigContentViewLocal != null) { bigContentViewLocal.setIsRootNamespace(true); - expanded.setExpandedChild(bigContentViewLocal); + contentContainer.setExpandedChild(bigContentViewLocal); + } + if (headsUpContentViewLocal != null) { + headsUpContentViewLocal.setIsRootNamespace(true); + contentContainer.setHeadsUpChild(headsUpContentViewLocal); } // now the public version View publicViewLocal = null; if (publicNotification != null) { try { - publicViewLocal = publicNotification.contentView.apply(mContext, expandedPublic, + publicViewLocal = publicNotification.contentView.apply(mContext, contentContainerPublic, mOnClickHandler); if (publicViewLocal != null) { publicViewLocal.setIsRootNamespace(true); - expandedPublic.setContractedChild(publicViewLocal); + contentContainerPublic.setContractedChild(publicViewLocal); } } catch (RuntimeException e) { @@ -1382,9 +1361,9 @@ public abstract class BaseStatusBar extends SystemUI implements // Add a basic notification template publicViewLocal = LayoutInflater.from(mContext).inflate( R.layout.notification_public_default, - expandedPublic, false); + contentContainerPublic, false); publicViewLocal.setIsRootNamespace(true); - expandedPublic.setContractedChild(publicViewLocal); + contentContainerPublic.setContractedChild(publicViewLocal); final TextView title = (TextView) publicViewLocal.findViewById(R.id.title); try { @@ -1520,13 +1499,8 @@ public abstract class BaseStatusBar extends SystemUI implements stripped.contentView = null; stripped.extras.putBoolean("android.rebuild.bigView", true); stripped.bigContentView = null; - - // Don't create the HUN input view for now because input doesn't work there yet. - // TODO: Enable once HUNs can take remote input correctly. - if (false) { - stripped.extras.putBoolean("android.rebuild.hudView", true); - stripped.headsUpContentView = null; - } + stripped.extras.putBoolean("android.rebuild.hudView", true); + stripped.headsUpContentView = null; Notification rebuilt = Notification.Builder.rebuild(mContext, stripped); @@ -1558,16 +1532,23 @@ public abstract class BaseStatusBar extends SystemUI implements } // See if we have somewhere to put that remote input - ViewGroup actionContainer = null; - if (remoteInput != null && entry.expandedBig != null) { - View actionContainerCandidate = entry.expandedBig - .findViewById(com.android.internal.R.id.actions); - if (actionContainerCandidate instanceof ViewGroup) { - actionContainer = (ViewGroup) actionContainerCandidate; + if (remoteInput != null) { + if (entry.expandedBig != null) { + inflateRemoteInput(entry.expandedBig, remoteInput, actions); + } + View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild(); + if (headsUpChild != null) { + inflateRemoteInput(headsUpChild, remoteInput, actions); } } - if (actionContainer != null) { + } + + private void inflateRemoteInput(View view, RemoteInput remoteInput, + Notification.Action[] actions) { + View actionContainerCandidate = view.findViewById(com.android.internal.R.id.actions); + if (actionContainerCandidate instanceof ViewGroup) { + ViewGroup actionContainer = (ViewGroup) actionContainerCandidate; actionContainer.removeAllViews(); actionContainer.addView( RemoteInputView.inflate(mContext, actionContainer, actions[0], remoteInput)); @@ -1597,12 +1578,12 @@ public abstract class BaseStatusBar extends SystemUI implements mCurrentUserId); dismissKeyguardThenExecute(new OnDismissAction() { public boolean onDismiss() { - if (mNotificationKey.equals(mHeadsUpNotificationView.getKey())) { + if (mHeadsUpManager.isHeadsUp(mNotificationKey)) { // Release the HUN notification to the shade. // // In most cases, when FLAG_AUTO_CANCEL is set, the notification will // become canceled shortly by NoMan, but we can't assume that. - mHeadsUpNotificationView.releaseImmediately(); + mHeadsUpManager.releaseImmediately(mNotificationKey); } new Thread() { @Override @@ -1889,90 +1870,28 @@ public abstract class BaseStatusBar extends SystemUI implements if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); final String key = notification.getKey(); - boolean wasHeadsUp = isHeadsUp(key); - Entry oldEntry; - if (wasHeadsUp) { - oldEntry = mHeadsUpNotificationView.getEntry(); - } else { - oldEntry = mNotificationData.get(key); - } - if (oldEntry == null) { + Entry entry = mNotificationData.get(key); + if (entry == null) { return; } - final StatusBarNotification oldNotification = oldEntry.notification; - - // XXX: modify when we do something more intelligent with the two content views - final RemoteViews oldContentView = oldNotification.getNotification().contentView; Notification n = notification.getNotification(); - final RemoteViews contentView = n.contentView; - final RemoteViews oldBigContentView = oldNotification.getNotification().bigContentView; - final RemoteViews bigContentView = n.bigContentView; - final RemoteViews oldHeadsUpContentView = oldNotification.getNotification().headsUpContentView; - final RemoteViews headsUpContentView = n.headsUpContentView; - final Notification oldPublicNotification = oldNotification.getNotification().publicVersion; - final RemoteViews oldPublicContentView = oldPublicNotification != null - ? oldPublicNotification.contentView : null; - final Notification publicNotification = n.publicVersion; - final RemoteViews publicContentView = publicNotification != null - ? publicNotification.contentView : null; - if (DEBUG) { - Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when - + " ongoing=" + oldNotification.isOngoing() - + " expanded=" + oldEntry.expanded - + " contentView=" + oldContentView - + " bigContentView=" + oldBigContentView - + " publicView=" + oldPublicContentView - + " rowParent=" + oldEntry.row.getParent()); - Log.d(TAG, "new notification: when=" + n.when - + " ongoing=" + oldNotification.isOngoing() - + " contentView=" + contentView - + " bigContentView=" + bigContentView - + " publicView=" + publicContentView); - } - - // Can we just reapply the RemoteViews in place? - - // 1U is never null - boolean contentsUnchanged = oldEntry.expanded != null - && contentView.getPackage() != null - && oldContentView.getPackage() != null - && oldContentView.getPackage().equals(contentView.getPackage()) - && oldContentView.getLayoutId() == contentView.getLayoutId(); - // large view may be null - boolean bigContentsUnchanged = - (oldEntry.getBigContentView() == null && bigContentView == null) - || ((oldEntry.getBigContentView() != null && bigContentView != null) - && bigContentView.getPackage() != null - && oldBigContentView.getPackage() != null - && oldBigContentView.getPackage().equals(bigContentView.getPackage()) - && oldBigContentView.getLayoutId() == bigContentView.getLayoutId()); - boolean headsUpContentsUnchanged = - (oldHeadsUpContentView == null && headsUpContentView == null) - || ((oldHeadsUpContentView != null && headsUpContentView != null) - && headsUpContentView.getPackage() != null - && oldHeadsUpContentView.getPackage() != null - && oldHeadsUpContentView.getPackage().equals(headsUpContentView.getPackage()) - && oldHeadsUpContentView.getLayoutId() == headsUpContentView.getLayoutId()); - boolean publicUnchanged = - (oldPublicContentView == null && publicContentView == null) - || ((oldPublicContentView != null && publicContentView != null) - && publicContentView.getPackage() != null - && oldPublicContentView.getPackage() != null - && oldPublicContentView.getPackage().equals(publicContentView.getPackage()) - && oldPublicContentView.getLayoutId() == publicContentView.getLayoutId()); - + logUpdate(entry, n); + } + boolean applyInPlace = shouldApplyInPlace(entry, n); final boolean shouldInterrupt = shouldInterrupt(notification); - final boolean alertAgain = shouldInterrupt && alertAgain(oldEntry, n); + final boolean alertAgain = alertAgain(entry, n); + + entry.notification = notification; + mGroupManager.onEntryUpdated(entry, entry.notification); + boolean updateSuccessful = false; - if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged - && publicUnchanged) { + if (applyInPlace) { + // We can just reapply the notifications in place if (DEBUG) Log.d(TAG, "reusing notification for key: " + key); - oldEntry.notification = notification; - mGroupManager.onEntryUpdated(oldEntry, oldNotification); try { - if (oldEntry.icon != null) { + if (entry.icon != null) { // Update the icon final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(), notification.getUser(), @@ -1980,88 +1899,39 @@ public abstract class BaseStatusBar extends SystemUI implements n.iconLevel, n.number, n.tickerText); - oldEntry.icon.setNotification(n); - if (!oldEntry.icon.set(ic)) { + entry.icon.setNotification(n); + if (!entry.icon.set(ic)) { handleNotificationError(notification, "Couldn't update icon: " + ic); return; } } - - if (wasHeadsUp) { - // Release may hang on to the views for a bit, so we should always update them. - updateHeadsUpViews(oldEntry, notification); - mHeadsUpNotificationView.updateNotification(oldEntry, alertAgain); - if (!shouldInterrupt) { - // we updated the notification above, so release to build a new shade entry - mHeadsUpNotificationView.release(); - return; - } - } else { - if (shouldInterrupt && alertAgain) { - mStackScroller.setRemoveAnimationEnabled(false); - removeNotificationViews(key, ranking); - mStackScroller.setRemoveAnimationEnabled(true); - addNotification(notification, ranking, oldEntry); //this will pop the headsup - } else { - updateNotificationViews(oldEntry, notification); - } - } - mNotificationData.updateRanking(ranking); - updateNotifications(); + updateNotificationViews(entry, notification); updateSuccessful = true; } catch (RuntimeException e) { // It failed to add cleanly. Log, and remove the view from the panel. - Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e); + Log.w(TAG, "Couldn't reapply views for package " + n.contentView.getPackage(), e); } } if (!updateSuccessful) { if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key); - if (wasHeadsUp) { - if (DEBUG) Log.d(TAG, "rebuilding heads up for key: " + key); - ViewGroup holder = mHeadsUpNotificationView.getHolder(); - if (inflateViewsForHeadsUp(oldEntry, holder)) { - mHeadsUpNotificationView.updateNotification(oldEntry, alertAgain); - } else { - Log.w(TAG, "Couldn't create new updated headsup for package " - + contentView.getPackage()); - } - if (!shouldInterrupt) { - if (DEBUG) Log.d(TAG, "releasing heads up for key: " + key); - oldEntry.notification = notification; - mGroupManager.onEntryUpdated(oldEntry, oldNotification); - mHeadsUpNotificationView.release(); - return; - } - } else { - if (shouldInterrupt && alertAgain) { - if (DEBUG) Log.d(TAG, "reposting to invoke heads up for key: " + key); - mStackScroller.setRemoveAnimationEnabled(false); - removeNotificationViews(key, ranking); - mStackScroller.setRemoveAnimationEnabled(true); - addNotification(notification, ranking, oldEntry); //this will pop the headsup - } else { - if (DEBUG) Log.d(TAG, "rebuilding update in place for key: " + key); - oldEntry.notification = notification; - mGroupManager.onEntryUpdated(oldEntry, oldNotification); - final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(), - notification.getUser(), - n.icon, - n.iconLevel, - n.number, - n.tickerText); - oldEntry.icon.setNotification(n); - oldEntry.icon.set(ic); - inflateViews(oldEntry, mStackScroller, wasHeadsUp); - mNotificationData.updateRanking(ranking); - updateNotifications(); - } - } + final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(), + notification.getUser(), + n.icon, + n.iconLevel, + n.number, + n.tickerText); + entry.icon.setNotification(n); + entry.icon.set(ic); + inflateViews(entry, mStackScroller); } + updateHeadsUp(key, entry, shouldInterrupt, alertAgain); + mNotificationData.updateRanking(ranking); + updateNotifications(); // Update the veto button accordingly (and as a result, whether this row is // swipe-dismissable) - updateNotificationVetoButton(oldEntry.row, notification); + updateNotificationVetoButton(entry.row, notification); // Is this for you? boolean isForCurrentUser = isNotificationForCurrentProfiles(notification); @@ -2071,22 +1941,91 @@ public abstract class BaseStatusBar extends SystemUI implements setAreThereNotifications(); } - private void updateNotificationViews(NotificationData.Entry entry, - StatusBarNotification notification) { - updateNotificationViews(entry, notification, false); + private void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt, + boolean alertAgain) { + final boolean wasHeadsUp = isHeadsUp(key); + if (wasHeadsUp) { + mHeadsUpManager.updateNotification(entry, alertAgain); + if (!shouldInterrupt) { + // We don't want this to be interrupting anymore, lets remove it + mHeadsUpManager.removeNotification(key); + } + } else if (shouldInterrupt && alertAgain) { + // This notification was updated to be a heads-up, show it! + mHeadsUpManager.showNotification(entry); + } } - private void updateHeadsUpViews(NotificationData.Entry entry, - StatusBarNotification notification) { - updateNotificationViews(entry, notification, true); + private void logUpdate(Entry oldEntry, Notification n) { + StatusBarNotification oldNotification = oldEntry.notification; + Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when + + " ongoing=" + oldNotification.isOngoing() + + " expanded=" + oldEntry.expanded + + " contentView=" + oldNotification.getNotification().contentView + + " bigContentView=" + oldNotification.getNotification().bigContentView + + " publicView=" + oldNotification.getNotification().publicVersion + + " rowParent=" + oldEntry.row.getParent()); + Log.d(TAG, "new notification: when=" + n.when + + " ongoing=" + oldNotification.isOngoing() + + " contentView=" + n.contentView + + " bigContentView=" + n.bigContentView + + " publicView=" + n.publicVersion); } - private void updateNotificationViews(NotificationData.Entry entry, - StatusBarNotification notification, boolean isHeadsUp) { + /** + * @return whether we can just reapply the RemoteViews in place when it is updated + */ + private boolean shouldApplyInPlace(Entry entry, Notification n) { + StatusBarNotification oldNotification = entry.notification; + // XXX: modify when we do something more intelligent with the two content views + final RemoteViews oldContentView = oldNotification.getNotification().contentView; + final RemoteViews contentView = n.contentView; + final RemoteViews oldBigContentView = oldNotification.getNotification().bigContentView; + final RemoteViews bigContentView = n.bigContentView; + final RemoteViews oldHeadsUpContentView + = oldNotification.getNotification().headsUpContentView; + final RemoteViews headsUpContentView = n.headsUpContentView; + final Notification oldPublicNotification = oldNotification.getNotification().publicVersion; + final RemoteViews oldPublicContentView = oldPublicNotification != null + ? oldPublicNotification.contentView : null; + final Notification publicNotification = n.publicVersion; + final RemoteViews publicContentView = publicNotification != null + ? publicNotification.contentView : null; + boolean contentsUnchanged = entry.expanded != null + && contentView.getPackage() != null + && oldContentView.getPackage() != null + && oldContentView.getPackage().equals(contentView.getPackage()) + && oldContentView.getLayoutId() == contentView.getLayoutId(); + // large view may be null + boolean bigContentsUnchanged = + (entry.getBigContentView() == null && bigContentView == null) + || ((entry.getBigContentView() != null && bigContentView != null) + && bigContentView.getPackage() != null + && oldBigContentView.getPackage() != null + && oldBigContentView.getPackage().equals(bigContentView.getPackage()) + && oldBigContentView.getLayoutId() == bigContentView.getLayoutId()); + boolean headsUpContentsUnchanged = + (oldHeadsUpContentView == null && headsUpContentView == null) + || ((oldHeadsUpContentView != null && headsUpContentView != null) + && headsUpContentView.getPackage() != null + && oldHeadsUpContentView.getPackage() != null + && oldHeadsUpContentView.getPackage().equals(headsUpContentView.getPackage()) + && oldHeadsUpContentView.getLayoutId() == headsUpContentView.getLayoutId()); + boolean publicUnchanged = + (oldPublicContentView == null && publicContentView == null) + || ((oldPublicContentView != null && publicContentView != null) + && publicContentView.getPackage() != null + && oldPublicContentView.getPackage() != null + && oldPublicContentView.getPackage().equals(publicContentView.getPackage()) + && oldPublicContentView.getLayoutId() == publicContentView.getLayoutId()); + return contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged + && publicUnchanged; + } + + private void updateNotificationViews(Entry entry, StatusBarNotification notification) { final RemoteViews contentView = notification.getNotification().contentView; - final RemoteViews bigContentView = isHeadsUp - ? notification.getNotification().headsUpContentView - : notification.getNotification().bigContentView; + final RemoteViews bigContentView = notification.getNotification().bigContentView; + final RemoteViews headsUpContentView = notification.getNotification().headsUpContentView; final Notification publicVersion = notification.getNotification().publicVersion; final RemoteViews publicContentView = publicVersion != null ? publicVersion.contentView : null; @@ -2097,6 +2036,10 @@ public abstract class BaseStatusBar extends SystemUI implements bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler); } + View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild(); + if (headsUpContentView != null && headsUpChild != null) { + headsUpContentView.reapply(mContext, headsUpChild, mOnClickHandler); + } if (publicContentView != null && entry.getPublicContentView() != null) { publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler); } @@ -2115,10 +2058,8 @@ public abstract class BaseStatusBar extends SystemUI implements applyRemoteInput(entry); } - protected void notifyHeadsUpScreenOn(boolean screenOn) { - if (!screenOn) { - scheduleHeadsUpEscalation(); - } + protected void notifyHeadsUpScreenOff() { + escalateHeadsUp(); } private boolean alertAgain(Entry oldEntry, Notification newNotification) { @@ -2134,7 +2075,7 @@ public abstract class BaseStatusBar extends SystemUI implements return false; } - if (mHeadsUpNotificationView.isSnoozed(sbn.getPackageName())) { + if (mHeadsUpManager.isSnoozed(sbn.getPackageName())) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 06a174e..33a07d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -78,13 +78,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private NotificationContentView mPublicLayout; private NotificationContentView mPrivateLayout; private int mMaxExpandHeight; + private int mHeadsUpHeight; private View mVetoButton; private boolean mClearable; private ExpansionLogger mLogger; private String mLoggingKey; private boolean mWasReset; - private NotificationGuts mGuts; + private NotificationGuts mGuts; private StatusBarNotification mStatusBarNotification; private boolean mIsHeadsUp; private View mExpandButton; @@ -108,6 +109,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { !mChildrenExpanded); } }; + private boolean mInShade; + + public NotificationContentView getPrivateLayout() { + return mPrivateLayout; + } + + public NotificationContentView getPublicLayout() { + return mPublicLayout; + } public void setIconAnimationRunning(boolean running) { setIconAnimationRunning(running, mPublicLayout); @@ -118,8 +128,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (layout != null) { View contractedChild = layout.getContractedChild(); View expandedChild = layout.getExpandedChild(); + View headsUpChild = layout.getHeadsUpChild(); setIconAnimationRunningForChild(running, contractedChild); setIconAnimationRunningForChild(running, expandedChild); + setIconAnimationRunningForChild(running, headsUpChild); } } @@ -164,8 +176,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return mStatusBarNotification; } + public boolean isHeadsUp() { + return mIsHeadsUp; + } + public void setHeadsUp(boolean isHeadsUp) { + int intrinsicBefore = getIntrinsicHeight(); mIsHeadsUp = isHeadsUp; + mPrivateLayout.setHeadsUp(isHeadsUp); + if (intrinsicBefore != getIntrinsicHeight()) { + notifyHeightChanged(false /* needsAnimation */); + } } public void setGroupManager(NotificationGroupManager groupManager) { @@ -263,6 +284,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return realActualHeight; } + public void setInShade(boolean inShade) { + mInShade = inShade; + } + + public boolean isInShade() { + return mInShade; + } + + public int getHeadsUpHeight() { + return mHeadsUpHeight; + } + public interface ExpansionLogger { public void logNotificationExpansion(String key, boolean userAction, boolean expanded); } @@ -299,6 +332,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { resetActualHeight(); } mMaxExpandHeight = 0; + mHeadsUpHeight = 0; mWasReset = true; onHeightReset(); requestLayout(); @@ -536,7 +570,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { } boolean inExpansionState = isExpanded(); int maxContentHeight; - if ((!inExpansionState && !mChildrenExpanded) || mShowingPublicForIntrinsicHeight) { + if (mIsHeadsUp) { + if (inExpansionState) { + maxContentHeight = Math.max(mMaxExpandHeight, mHeadsUpHeight); + } else { + maxContentHeight = Math.max(mRowMinHeight, mHeadsUpHeight); + } + } else if ((!inExpansionState && !mChildrenExpanded) || mShowingPublicForIntrinsicHeight) { maxContentHeight = mRowMinHeight; } else if (mChildrenExpanded) { maxContentHeight = mChildrenContainer.getIntrinsicHeight(); @@ -583,7 +623,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset; - updateMaxExpandHeight(); + updateMaxHeights(); if (updateExpandHeight) { applyExpansionToLayout(); } @@ -599,9 +639,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return super.isChildInvisible(child) || isInvisibleChildContainer; } - private void updateMaxExpandHeight() { + private void updateMaxHeights() { int intrinsicBefore = getIntrinsicHeight(); - mMaxExpandHeight = mPrivateLayout.getMaxHeight(); + View expandedChild = mPrivateLayout.getExpandedChild(); + if (expandedChild == null) { + expandedChild = mPrivateLayout.getContractedChild(); + } + mMaxExpandHeight = expandedChild.getHeight(); + View headsUpChild = mPrivateLayout.getHeadsUpChild(); + if (headsUpChild == null) { + headsUpChild = mPrivateLayout.getContractedChild(); + } + mHeadsUpHeight = headsUpChild.getHeight(); if (intrinsicBefore != getIntrinsicHeight()) { notifyHeightChanged(false /* needsAnimation */); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 7ae0d6d..e632cc8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -118,6 +118,7 @@ public abstract class ExpandableView extends FrameLayout { setContentHeight(initialHeight); } } + updateClipping(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 745e75d..964d75f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -23,10 +23,12 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; +import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; + import com.android.systemui.R; /** @@ -37,23 +39,28 @@ import com.android.systemui.R; public class NotificationContentView extends FrameLayout { private static final long ANIMATION_DURATION_LENGTH = 170; + private static final int CONTRACTED = 1; + private static final int EXPANDED = 2; + private static final int HEADSUP = 3; private final Rect mClipBounds = new Rect(); private View mContractedChild; private View mExpandedChild; + private View mHeadsUpChild; private NotificationViewWrapper mContractedWrapper; - private int mSmallHeight; + private final int mSmallHeight; + private final int mHeadsUpHeight; private int mClipTopAmount; + private int mContentHeight; private final Interpolator mLinearInterpolator = new LinearInterpolator(); + private int mVisibleView = CONTRACTED; - private boolean mContractedVisible = true; private boolean mDark; - private final Paint mFadePaint = new Paint(); private boolean mAnimate; private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener @@ -65,14 +72,62 @@ public class NotificationContentView extends FrameLayout { return true; } }; + private boolean mIsHeadsUp; public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); + mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height); + mHeadsUpHeight = getResources().getDimensionPixelSize(R.dimen.notification_mid_height); reset(true); } @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY; + boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST; + int maxSize = Integer.MAX_VALUE; + if (hasFixedHeight || isHeightLimited) { + maxSize = MeasureSpec.getSize(heightMeasureSpec); + } + int maxChildHeight = 0; + if (mContractedChild != null) { + int size = Math.min(maxSize, mSmallHeight); + mContractedChild.measure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST)); + maxChildHeight = Math.max(maxChildHeight, mContractedChild.getMeasuredHeight()); + } + if (mExpandedChild != null) { + int size = maxSize; + ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams(); + if (layoutParams.height >= 0) { + // An actual height is set + size = Math.min(maxSize, layoutParams.height); + } + int spec = size == Integer.MAX_VALUE ? + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) : + MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); + mExpandedChild.measure(widthMeasureSpec, spec); + maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight()); + } + if (mHeadsUpChild != null) { + int size = Math.min(maxSize, mHeadsUpHeight); + ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams(); + if (layoutParams.height >= 0) { + // An actual height is set + size = Math.min(maxSize, layoutParams.height); + } + mHeadsUpChild.measure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST)); + maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight()); + } + int ownHeight = Math.min(maxChildHeight, maxSize); + int width = MeasureSpec.getSize(widthMeasureSpec); + setMeasuredDimension(width, ownHeight); + } + + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); updateClipping(); @@ -91,11 +146,14 @@ public class NotificationContentView extends FrameLayout { if (mExpandedChild != null) { mExpandedChild.animate().cancel(); } + if (mHeadsUpChild != null) { + mHeadsUpChild.animate().cancel(); + } removeAllViews(); mContractedChild = null; mExpandedChild = null; - mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height); - mContractedVisible = true; + mHeadsUpChild = null; + mVisibleView = CONTRACTED; if (resetActualHeight) { mContentHeight = mSmallHeight; } @@ -109,12 +167,15 @@ public class NotificationContentView extends FrameLayout { return mExpandedChild; } + public View getHeadsUpChild() { + return mHeadsUpChild; + } + public void setContractedChild(View child) { if (mContractedChild != null) { mContractedChild.animate().cancel(); removeView(mContractedChild); } - sanitizeContractedLayoutParams(child); addView(child); mContractedChild = child; mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child); @@ -132,6 +193,16 @@ public class NotificationContentView extends FrameLayout { selectLayout(false /* animate */, true /* force */); } + public void setHeadsUpChild(View child) { + if (mHeadsUpChild != null) { + mHeadsUpChild.animate().cancel(); + removeView(mHeadsUpChild); + } + addView(child); + mHeadsUpChild = child; + selectLayout(false /* animate */, true /* force */); + } + @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); @@ -166,9 +237,12 @@ public class NotificationContentView extends FrameLayout { } public int getMaxHeight() { - - // The maximum height is just the laid out height. - return getHeight(); + if (mIsHeadsUp && mHeadsUpChild != null) { + return mHeadsUpChild.getHeight(); + } else if (mExpandedChild != null) { + return mExpandedChild.getHeight(); + } + return mSmallHeight; } public int getMinHeight() { @@ -185,62 +259,91 @@ public class NotificationContentView extends FrameLayout { setClipBounds(mClipBounds); } - private void sanitizeContractedLayoutParams(View contractedChild) { - LayoutParams lp = (LayoutParams) contractedChild.getLayoutParams(); - lp.height = mSmallHeight; - contractedChild.setLayoutParams(lp); - } - private void selectLayout(boolean animate, boolean force) { if (mContractedChild == null) { return; } - boolean showContractedChild = showContractedChild(); - if (showContractedChild != mContractedVisible || force) { + int visibleView = calculateVisibleView(); + if (visibleView != mVisibleView || 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); + runSwitchAnimation(visibleView); + } else { + updateViewVisibilities(visibleView); } + mVisibleView = visibleView; } - 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); + private void updateViewVisibilities(int visibleView) { + boolean contractedVisible = visibleView == CONTRACTED; + mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE); + mContractedChild.setAlpha(contractedVisible ? 1f : 0f); + mContractedChild.setLayerType(LAYER_TYPE_NONE, null); + if (mExpandedChild != null) { + boolean expandedVisible = visibleView == EXPANDED; + mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE); + mExpandedChild.setAlpha(expandedVisible ? 1f : 0f); + mExpandedChild.setLayerType(LAYER_TYPE_NONE, null); + } + if (mHeadsUpChild != null) { + boolean headsUpVisible = visibleView == HEADSUP; + mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE); + mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f); + mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null); + } + setLayerType(LAYER_TYPE_NONE, null); + } + + private void runSwitchAnimation(int visibleView) { + View shownView = getViewFromFlag(visibleView); + View hiddenView = getViewFromFlag(mVisibleView); + shownView.setVisibility(View.VISIBLE); + hiddenView.setVisibility(View.VISIBLE); + shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint); + hiddenView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint); setLayerType(LAYER_TYPE_HARDWARE, null); - mContractedChild.animate() - .alpha(showContractedChild ? 1f : 0f) + hiddenView.animate() + .alpha(0f) .setDuration(ANIMATION_DURATION_LENGTH) - .setInterpolator(mLinearInterpolator); - mExpandedChild.animate() - .alpha(showContractedChild ? 0f : 1f) + .setInterpolator(mLinearInterpolator) + .withEndAction(null); // In case we have multiple changes in one frame. + shownView.animate() + .alpha(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); + updateViewVisibilities(mVisibleView); } }); } - private boolean showContractedChild() { - return mContentHeight <= mSmallHeight || mExpandedChild == null; + private View getViewFromFlag(int visibleView) { + switch (visibleView) { + case EXPANDED: + return mExpandedChild; + case HEADSUP: + return mHeadsUpChild; + } + return mContractedChild; + } + + private int calculateVisibleView() { + boolean noExpandedChild = mExpandedChild == null; + if (mIsHeadsUp && mHeadsUpChild != null) { + if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) { + return HEADSUP; + } else { + return EXPANDED; + } + } else { + if (mContentHeight <= mSmallHeight || noExpandedChild) { + return CONTRACTED; + } else { + return EXPANDED; + } + } } public void notifyContentUpdated() { @@ -261,6 +364,11 @@ public class NotificationContentView extends FrameLayout { mContractedWrapper.setDark(dark, fade, delay); } + public void setHeadsUp(boolean headsUp) { + mIsHeadsUp = headsUp; + selectLayout(false /* animate */, true /* force */); + } + @Override public boolean hasOverlappingRendering() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 912f414..429889d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -25,6 +25,7 @@ import android.util.ArrayMap; import android.view.View; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.policy.HeadsUpManager; import java.io.PrintWriter; import java.util.ArrayList; @@ -37,6 +38,7 @@ import java.util.Comparator; public class NotificationData { private final Environment mEnvironment; + private HeadsUpManager mHeadsUpManager; public static final class Entry { public String key; @@ -98,43 +100,47 @@ public class NotificationData { private RankingMap mRankingMap; private final Ranking mTmpRanking = new Ranking(); + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + } + private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() { private final Ranking mRankingA = new Ranking(); private final Ranking mRankingB = new Ranking(); @Override public int compare(Entry a, Entry b) { - // Upsort current media notification. String mediaNotification = mEnvironment.getCurrentMediaNotificationKey(); boolean aMedia = a.key.equals(mediaNotification); boolean bMedia = b.key.equals(mediaNotification); - if (aMedia != bMedia) { - return aMedia ? -1 : 1; - } final StatusBarNotification na = a.notification; final StatusBarNotification nb = b.notification; - // Upsort PRIORITY_MAX system notifications boolean aSystemMax = na.getNotification().priority >= Notification.PRIORITY_MAX && isSystemNotification(na); boolean bSystemMax = nb.getNotification().priority >= Notification.PRIORITY_MAX && isSystemNotification(nb); - if (aSystemMax != bSystemMax) { - return aSystemMax ? -1 : 1; - } + int d = nb.getScore() - na.getScore(); - // RankingMap as received from NoMan. - if (mRankingMap != null) { + boolean isHeadsUp = a.row.isHeadsUp(); + if (isHeadsUp != b.row.isHeadsUp()) { + return isHeadsUp ? -1 : 1; + } else if (isHeadsUp) { + // Provide consistent ranking with headsUpManager + return mHeadsUpManager.compare(a, b); + } else if (aMedia != bMedia) { + // Upsort current media notification. + return aMedia ? -1 : 1; + } else if (aSystemMax != bSystemMax) { + // Upsort PRIORITY_MAX system notifications + return aSystemMax ? -1 : 1; + } else if (mRankingMap != null) { + // RankingMap as received from NoMan mRankingMap.getRanking(a.key, mRankingA); mRankingMap.getRanking(b.key, mRankingB); return mRankingA.getRank() - mRankingB.getRank(); - } - - int d = nb.getScore() - na.getScore(); - if (a.interruption != b.interruption) { - return a.interruption ? -1 : 1; - } else if (d != 0) { + } if (d != 0) { return d; } else { return (int) (nb.getNotification().when - na.getNotification().when); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index a82afcf..b2bb021 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -20,6 +20,8 @@ import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.PorterDuff; +import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; import android.telephony.SubscriptionInfo; import android.util.AttributeSet; import android.util.Log; @@ -165,12 +167,13 @@ public class SignalClusterView } @Override - public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean isTypeIconWide, - int subId) { + public void setMobileDataIndicators(boolean visible, int strengthIcon, int darkStrengthIcon, + int typeIcon, String contentDescription, String typeContentDescription, + boolean isTypeIconWide, int subId) { PhoneState state = getOrInflateState(subId); state.mMobileVisible = visible; state.mMobileStrengthId = strengthIcon; + state.mMobileDarkStrengthId = darkStrengthIcon; state.mMobileTypeId = typeIcon; state.mMobileDescription = contentDescription; state.mMobileTypeDescription = typeContentDescription; @@ -360,7 +363,7 @@ public class SignalClusterView private class PhoneState { private final int mSubId; private boolean mMobileVisible = false; - private int mMobileStrengthId = 0, mMobileTypeId = 0; + private int mMobileStrengthId = 0, mMobileDarkStrengthId = 0, mMobileTypeId = 0; private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; @@ -384,7 +387,23 @@ public class SignalClusterView public boolean apply(boolean isSecondaryIcon) { if (mMobileVisible && !mIsAirplaneMode) { mMobile.setImageResource(mMobileStrengthId); + Drawable mobileDrawable = mMobile.getDrawable(); + if (mobileDrawable instanceof Animatable) { + Animatable ad = (Animatable) mobileDrawable; + if (!ad.isRunning()) { + ad.start(); + } + } + mMobileDark.setImageResource(mMobileStrengthId); + Drawable mobileDarkDrawable = mMobileDark.getDrawable(); + if (mobileDarkDrawable instanceof Animatable) { + Animatable ad = (Animatable) mobileDarkDrawable; + if (!ad.isRunning()) { + ad.start(); + } + } + mMobileType.setImageResource(mMobileTypeId); mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); @@ -401,8 +420,9 @@ public class SignalClusterView mMobileDark.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0); - if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d", - (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); + if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d dark=%d typ=%d", + (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, + mMobileDarkStrengthId, mMobileTypeId)); mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java new file mode 100644 index 0000000..3997807 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2015 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 android.content.Context; +import android.view.MotionEvent; +import android.view.ViewConfiguration; + +import com.android.systemui.Gefingerpoken; +import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.ExpandableView; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; + +/** + * A Helper class to handle touches on the heads-up views + */ +public class HeadsUpTouchHelper implements Gefingerpoken { + + private HeadsUpManager mHeadsUpManager; + private NotificationStackScrollLayout mStackScroller; + private int mTrackingPointer; + private float mTouchSlop; + private float mInitialTouchX; + private float mInitialTouchY; + private boolean mMotionOnHeadsUpView; + private boolean mTrackingHeadsUp; + private boolean mCollapseSnoozes; + private NotificationPanelView mPanel; + private ExpandableNotificationRow mPickedChild; + + public boolean isTrackingHeadsUp() { + return mTrackingHeadsUp; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (!mMotionOnHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) { + return false; + } + int pointerIndex = event.findPointerIndex(mTrackingPointer); + if (pointerIndex < 0) { + pointerIndex = 0; + mTrackingPointer = event.getPointerId(pointerIndex); + } + final float x = event.getX(pointerIndex); + final float y = event.getY(pointerIndex); + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mInitialTouchY = y; + mInitialTouchX = x; + setTrackingHeadsUp(false); + ExpandableView child = mStackScroller.getChildAtPosition(x, y); + mMotionOnHeadsUpView = false; + if (child instanceof ExpandableNotificationRow) { + mPickedChild = (ExpandableNotificationRow) child; + mMotionOnHeadsUpView = mPickedChild.isHeadsUp() && !mPickedChild.isInShade(); + } + break; + case MotionEvent.ACTION_POINTER_UP: + final int upPointer = event.getPointerId(event.getActionIndex()); + if (mTrackingPointer == upPointer) { + // gesture is ongoing, find a new pointer to track + final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; + mTrackingPointer = event.getPointerId(newIndex); + mInitialTouchX = event.getX(newIndex); + mInitialTouchY = event.getY(newIndex); + } + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)) { + setTrackingHeadsUp(true); + mCollapseSnoozes = h < 0; + mInitialTouchX = x; + mInitialTouchY = y; + int expandedHeight = mPickedChild.getActualHeight(); + mPanel.startExpandMotion(x, y, true /* startTracking */, expandedHeight); + return true; + } + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (mPickedChild != null && mMotionOnHeadsUpView) { + if (mHeadsUpManager.shouldSwallowClick( + mPickedChild.getStatusBarNotification().getKey())) { + endMotion(); + return true; + } + } + endMotion(); + break; + } + return false; + } + + private void setTrackingHeadsUp(boolean tracking) { + mTrackingHeadsUp = tracking; + mHeadsUpManager.setTrackingHeadsUp(tracking); + mPanel.setTrackingHeadsUp(tracking); + } + + public void notifyFling(boolean collapse) { + if (collapse && mCollapseSnoozes) { + mHeadsUpManager.snooze(); + } + mCollapseSnoozes = false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!mTrackingHeadsUp) { + return false; + } + switch (event.getActionMasked()) { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + endMotion(); + setTrackingHeadsUp(false); + break; + } + return true; + } + + private void endMotion() { + mTrackingPointer = -1; + mPickedChild = null; + mMotionOnHeadsUpView = false; + } + + public ExpandableView getPickedChild() { + return mPickedChild; + } + + public void bind(HeadsUpManager headsUpManager, NotificationStackScrollLayout stackScroller, + NotificationPanelView notificationPanelView) { + mHeadsUpManager = headsUpManager; + mStackScroller = stackScroller; + mPanel = notificationPanelView; + Context context = stackScroller.getContext(); + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = configuration.getScaledTouchSlop(); + } +} 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 02b6c19..c266467 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.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewTreeObserver; +import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -39,16 +40,19 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.keyguard.KeyguardStatusView; -import com.android.systemui.EventLogTags; import com.android.systemui.EventLogConstants; +import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.qs.QSContainer; import com.android.systemui.qs.QSPanel; +import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.StackStateAnimator; @@ -56,7 +60,8 @@ import com.android.systemui.statusbar.stack.StackStateAnimator; public class NotificationPanelView extends PanelView implements ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener, View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener, - KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener { + KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener, + HeadsUpManager.OnHeadsUpChangedListener { private static final boolean DEBUG = false; @@ -81,7 +86,7 @@ public class NotificationPanelView extends PanelView implements private TextView mClockView; private View mReserveNotificationSpace; private View mQsNavbarScrim; - private View mNotificationContainerParent; + private NotificationsQuickSettingsContainer mNotificationContainerParent; private NotificationStackScrollLayout mNotificationStackScroller; private int mNotificationTopPadding; private boolean mAnimateNextTopPaddingChange; @@ -177,6 +182,17 @@ public class NotificationPanelView extends PanelView implements private float mKeyguardStatusBarAnimateAlpha = 1f; private int mOldLayoutDirection; + private HeadsUpTouchHelper mHeadsUpTouchHelper = new HeadsUpTouchHelper(); + private boolean mPinnedHeadsUpExist; + private boolean mExpansionIsFromHeadsUp; + private int mBottomBarHeight; + private boolean mExpandingFromHeadsUp; + private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() { + @Override + public void run() { + notifyBarPanelExpansionChanged(); + } + }; public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -201,7 +217,8 @@ public class NotificationPanelView extends PanelView implements mScrollView.setListener(this); mScrollView.setFocusable(false); mReserveNotificationSpace = findViewById(R.id.reserve_notification_space); - mNotificationContainerParent = findViewById(R.id.notification_container_parent); + mNotificationContainerParent = (NotificationsQuickSettingsContainer) + findViewById(R.id.notification_container_parent); mNotificationStackScroller = (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller); mNotificationStackScroller.setOnHeightChangedListener(this); @@ -317,6 +334,7 @@ public class NotificationPanelView extends PanelView implements if (mQsSizeChangeAnimator == null) { mQsContainer.setHeightOverride(mQsContainer.getDesiredHeight()); } + updateMaxHeadsUpTranslation(); } @Override @@ -493,22 +511,39 @@ public class NotificationPanelView extends PanelView implements } @Override + protected void flingToHeight(float vel, boolean expand, float target) { + mHeadsUpTouchHelper.notifyFling(!expand); + super.flingToHeight(vel, expand, target); + } + + @Override public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { event.getText().add(getKeyguardOrLockScreenString()); mLastAnnouncementWasQuickSettings = false; return true; } - return super.dispatchPopulateAccessibilityEventInternal(event); } @Override - public boolean onInterceptTouchEvent(MotionEvent event) { + public boolean + onInterceptTouchEvent(MotionEvent event) { if (mBlockTouches) { return false; } initDownStates(event); + if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) { + mExpansionIsFromHeadsUp = true; + return true; + } + if (!isShadeCollapsed() && onQsIntercept(event)) { + return true; + } + return super.onInterceptTouchEvent(event); + } + + private boolean onQsIntercept(MotionEvent event) { int pointerIndex = event.findPointerIndex(mTrackingPointer); if (pointerIndex < 0) { pointerIndex = 0; @@ -583,7 +618,7 @@ public class NotificationPanelView extends PanelView implements mIntercepting = false; break; } - return super.onInterceptTouchEvent(event); + return false; } @Override @@ -652,6 +687,15 @@ public class NotificationPanelView extends PanelView implements if (mOnlyAffordanceInThisMotion) { return true; } + mHeadsUpTouchHelper.onTouchEvent(event); + if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQSTouch(event)) { + return true; + } + super.onTouchEvent(event); + return true; + } + + private boolean handleQSTouch(MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded && mQsExpansionEnabled) { @@ -664,7 +708,7 @@ public class NotificationPanelView extends PanelView implements mInitialTouchY = event.getX(); mInitialTouchX = event.getY(); } - if (mExpandedHeight != 0) { + if (!isShadeCollapsed()) { handleQsDown(event); } if (!mQsExpandImmediate && mQsTracking) { @@ -677,7 +721,7 @@ public class NotificationPanelView extends PanelView implements || event.getActionMasked() == MotionEvent.ACTION_UP) { mConflictingQsExpansionGesture = false; } - if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mExpandedHeight == 0 + if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isShadeCollapsed() && mQsExpansionEnabled) { mTwoFingerQsExpandPossible = true; } @@ -691,8 +735,7 @@ public class NotificationPanelView extends PanelView implements // earlier so the state is already up to date when dragging down. setListening(true); } - super.onTouchEvent(event); - return true; + return false; } private boolean isInQsArea(float x, float y) { @@ -834,13 +877,13 @@ public class NotificationPanelView extends PanelView implements setQsExpansion(mQsExpansionHeight); flingSettings(!mQsExpansionEnabled && open ? 0f : velocity, open && mQsExpansionEnabled, new Runnable() { - @Override - public void run() { - mStackScrollerOverscrolling = false; - mQsExpansionFromOverscroll = false; - updateQsState(); - } - }); + @Override + public void run() { + mStackScrollerOverscrolling = false; + mQsExpansionFromOverscroll = false; + updateQsState(); + } + }); } private void onQsExpansionStarted() { @@ -869,6 +912,7 @@ public class NotificationPanelView extends PanelView implements mNotificationStackScroller.setInterceptDelegateEnabled(expanded); mStatusBar.setQsExpanded(expanded); mQsPanel.setExpanded(expanded); + mNotificationContainerParent.setQsExpanded(expanded); } } @@ -1056,7 +1100,7 @@ public class NotificationPanelView extends PanelView implements mKeyguardBottomArea.animate() .alpha(0f) .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay()) - .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2) + .setDuration(mStatusBar.getKeyguardFadingAwayDuration() / 2) .setInterpolator(PhoneStatusBar.ALPHA_OUT) .withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable) .start(); @@ -1132,8 +1176,8 @@ public class NotificationPanelView extends PanelView implements updateEmptyShadeView(); mQsNavbarScrim.setVisibility(mStatusBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling && mQsScrimEnabled - ? View.VISIBLE - : View.INVISIBLE); + ? View.VISIBLE + : View.INVISIBLE); if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) { mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); } @@ -1402,6 +1446,8 @@ public class NotificationPanelView extends PanelView implements updateHeader(); updateUnlockIcon(); updateNotificationTranslucency(); + mHeadsUpManager.setIsExpanded(!isShadeCollapsed()); + mNotificationStackScroller.setShadeExpanded(!isShadeCollapsed()); if (DEBUG) { invalidate(); } @@ -1471,16 +1517,24 @@ public class NotificationPanelView extends PanelView implements } } private void updateNotificationTranslucency() { - float alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight()) - / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize() - - mNotificationStackScroller.getCollapseSecondCardPadding()); - alpha = Math.max(0, Math.min(alpha, 1)); - alpha = (float) Math.pow(alpha, 0.75); - if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null); - } else if (alpha == 1f - && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); + float alpha; + if (mExpandingFromHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) { + alpha = 1f; + if (mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { + mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); + } + } else { + alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight()) + / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize() + - mNotificationStackScroller.getCollapseSecondCardPadding()); + alpha = Math.max(0, Math.min(alpha, 1)); + alpha = (float) Math.pow(alpha, 0.75); + if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) { + mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null); + } else if (alpha == 1f + && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { + mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); + } } mNotificationStackScroller.setAlpha(alpha); } @@ -1544,7 +1598,13 @@ public class NotificationPanelView extends PanelView implements return mExpandedHeight / HEADER_RUBBERBAND_FACTOR - mQsMinExpansionHeight; } } - return Math.min(0, mNotificationStackScroller.getTranslationY()) / HEADER_RUBBERBAND_FACTOR; + float stackTranslation = mNotificationStackScroller.getStackTranslation(); + float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR; + if (mHeadsUpManager.hasPinnedHeadsUp() || mExpansionIsFromHeadsUp) { + translation = mNotificationStackScroller.getTopPadding() + stackTranslation + - mNotificationTopPadding - mQsMinExpansionHeight; + } + return Math.min(0, translation); } /** @@ -1605,15 +1665,19 @@ public class NotificationPanelView extends PanelView implements protected void onExpandingFinished() { super.onExpandingFinished(); mNotificationStackScroller.onExpansionStopped(); + mHeadsUpManager.onExpandingFinished(); mIsExpanding = false; mScrollYOverride = -1; - if (mExpandedHeight == 0f) { + if (isShadeCollapsed()) { setListening(false); } else { setListening(true); } mQsExpandImmediate = false; mTwoFingerQsExpandPossible = false; + mExpansionIsFromHeadsUp = false; + mNotificationStackScroller.setTrackingHeadsUp(mHeadsUpTouchHelper.isTrackingHeadsUp()); + mExpandingFromHeadsUp = mHeadsUpTouchHelper.isTrackingHeadsUp(); } private void setListening(boolean listening) { @@ -1709,6 +1773,17 @@ public class NotificationPanelView extends PanelView implements } @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + mBottomBarHeight = insets.getSystemWindowInsetBottom(); + updateMaxHeadsUpTranslation(); + return insets; + } + + private void updateMaxHeadsUpTranslation() { + mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mBottomBarHeight); + } + + @Override public void onRtlPropertiesChanged(int layoutDirection) { if (layoutDirection != mOldLayoutDirection) { mAfforanceHelper.onRtlPropertiesChanged(); @@ -2066,4 +2141,49 @@ public class NotificationPanelView extends PanelView implements mNotificationStackScroller.getTopPadding(), p); } } + + @Override + public void OnPinnedHeadsUpExistChanged(final boolean exist, boolean changeImmediatly) { + if (exist != mPinnedHeadsUpExist) { + mPinnedHeadsUpExist = exist; + if (exist) { + mHeadsUpExistenceChangedRunnable.run(); + updateNotificationTranslucency(); + } else { + mNotificationStackScroller.performOnAnimationFinished( + mHeadsUpExistenceChangedRunnable); + } + } + } + + @Override + public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { + if (isHeadsUp) { + mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true); + } + } + + @Override + public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { + mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp); + } + + @Override + protected boolean isShadeCollapsed() { + return mExpandedHeight == 0; + } + + @Override + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + super.setHeadsUpManager(headsUpManager); + mHeadsUpTouchHelper.bind(headsUpManager, mNotificationStackScroller, this); + } + + public void setTrackingHeadsUp(boolean tracking) { + if (tracking) { + // otherwise we update the state when the expansion is finished + mNotificationStackScroller.setTrackingHeadsUp(true); + mExpandingFromHeadsUp = true; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index a03c297..cbb71c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -37,6 +37,7 @@ public class NotificationsQuickSettingsContainer extends FrameLayout private View mStackScroller; private View mKeyguardStatusBar; private boolean mInflated; + private boolean mQsExpanded; public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -64,26 +65,29 @@ public class NotificationsQuickSettingsContainer extends FrameLayout boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE; boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE; + View stackQsTop = mQsExpanded ? mStackScroller : mScrollView; + View stackQsBottom = !mQsExpanded ? mStackScroller : mScrollView; // Invert the order of the scroll view and user switcher such that the notifications receive // touches first but the panel gets drawn above. if (child == mScrollView) { - return super.drawChild(canvas, mStackScroller, drawingTime); - } else if (child == mStackScroller) { - return super.drawChild(canvas, - userSwitcherVisible && statusBarVisible ? mUserSwitcher + return super.drawChild(canvas, userSwitcherVisible && statusBarVisible ? mUserSwitcher : statusBarVisible ? mKeyguardStatusBar : userSwitcherVisible ? mUserSwitcher - : mScrollView, + : stackQsBottom, drawingTime); + } else if (child == mStackScroller) { + return super.drawChild(canvas, + userSwitcherVisible && statusBarVisible ? mKeyguardStatusBar + : statusBarVisible || userSwitcherVisible ? stackQsBottom + : stackQsTop, drawingTime); } else if (child == mUserSwitcher) { return super.drawChild(canvas, - userSwitcherVisible && statusBarVisible ? mKeyguardStatusBar - : mScrollView, + userSwitcherVisible && statusBarVisible ? stackQsBottom + : stackQsTop, drawingTime); } else if (child == mKeyguardStatusBar) { return super.drawChild(canvas, - userSwitcherVisible && statusBarVisible ? mScrollView - : mScrollView, + stackQsTop, drawingTime); }else { return super.drawChild(canvas, child, drawingTime); @@ -97,4 +101,11 @@ public class NotificationsQuickSettingsContainer extends FrameLayout mInflated = true; } } + + public void setQsExpanded(boolean expanded) { + if (mQsExpanded != expanded) { + mQsExpanded = expanded; + invalidate(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index c6e1be9..240438a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -157,8 +157,7 @@ public class PanelBar extends FrameLayout { if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); mPanelExpandedFractionSum = 0f; for (PanelView pv : mPanels) { - boolean visible = pv.getExpandedHeight() > 0; - pv.setVisibility(visible ? View.VISIBLE : View.GONE); + pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE); // adjust any other panels that may be partially visible if (expanded) { if (mState == STATE_CLOSED) { @@ -167,7 +166,7 @@ public class PanelBar extends FrameLayout { } fullyClosed = false; final float thisFrac = pv.getExpandedFraction(); - mPanelExpandedFractionSum += (visible ? thisFrac : 0); + mPanelExpandedFractionSum += thisFrac; if (DEBUG) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); if (panel == pv) { if (thisFrac == 1f) fullyOpenedPanel = panel; @@ -196,7 +195,6 @@ public class PanelBar extends FrameLayout { } else { pv.resetViews(); pv.setExpandedFraction(0); // just in case - pv.setVisibility(View.GONE); pv.cancelPeek(); } } 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 4bbf690..ddce9d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -38,6 +38,7 @@ import com.android.systemui.R; import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.policy.HeadsUpManager; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -45,6 +46,7 @@ import java.io.PrintWriter; public abstract class PanelView extends FrameLayout { public static final boolean DEBUG = PanelBar.DEBUG; public static final String TAG = PanelView.class.getSimpleName(); + protected HeadsUpManager mHeadsUpManager; private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); @@ -232,18 +234,15 @@ public abstract class PanelView extends FrameLayout { final float y = event.getY(pointerIndex); if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - mGestureWaitForTouchSlop = mExpandedHeight == 0f; + mGestureWaitForTouchSlop = isShadeCollapsed(); } boolean waitForTouchSlop = hasConflictingGestures() || mGestureWaitForTouchSlop; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - mInitialTouchY = y; - mInitialTouchX = x; - mInitialOffsetOnTouch = mExpandedHeight; - mTouchSlopExceeded = false; + startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); mJustPeeked = false; - mPanelClosedOnDown = mExpandedHeight == 0.0f; + mPanelClosedOnDown = isShadeCollapsed(); mHasLayoutedSinceDown = false; mUpdateFlingOnLayout = false; mMotionAborted = false; @@ -261,7 +260,7 @@ public abstract class PanelView extends FrameLayout { || mPeekPending || mPeekAnimator != null; onTrackingStarted(); } - if (mExpandedHeight == 0) { + if (isShadeCollapsed()) { schedulePeek(); } break; @@ -274,9 +273,7 @@ public abstract class PanelView extends FrameLayout { final float newY = event.getY(newIndex); final float newX = event.getX(newIndex); mTrackingPointer = event.getPointerId(newIndex); - mInitialOffsetOnTouch = mExpandedHeight; - mInitialTouchY = newY; - mInitialTouchX = newX; + startExpandMotion(newX, newY, true /* startTracking */, mExpandedHeight); } break; case MotionEvent.ACTION_POINTER_DOWN: @@ -297,9 +294,7 @@ public abstract class PanelView extends FrameLayout { mTouchSlopExceeded = true; if (waitForTouchSlop && !mTracking) { if (!mJustPeeked && mInitialOffsetOnTouch != 0f) { - mInitialOffsetOnTouch = mExpandedHeight; - mInitialTouchX = x; - mInitialTouchY = y; + startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); h = 0; } cancelHeightAnimator(); @@ -334,6 +329,17 @@ public abstract class PanelView extends FrameLayout { return !waitForTouchSlop || mTracking; } + protected void startExpandMotion(float newX, float newY, boolean startTracking, + float expandedHeight) { + mInitialOffsetOnTouch = expandedHeight; + mInitialTouchY = newY; + mInitialTouchX = newX; + if (startTracking) { + mTouchSlopExceeded = true; + onTrackingStarted(); + } + } + private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) { mTrackingPointer = -1; if ((mTracking && mTouchSlopExceeded) @@ -442,7 +448,7 @@ public abstract class PanelView extends FrameLayout { mTouchSlopExceeded = false; mJustPeeked = false; mMotionAborted = false; - mPanelClosedOnDown = mExpandedHeight == 0.0f; + mPanelClosedOnDown = isShadeCollapsed(); mHasLayoutedSinceDown = false; mUpdateFlingOnLayout = false; mTouchAboveFalsingThreshold = false; @@ -474,12 +480,7 @@ public abstract class PanelView extends FrameLayout { if (scrolledToBottom || mTouchStartedInEmptyArea) { if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) { cancelHeightAnimator(); - mInitialOffsetOnTouch = mExpandedHeight; - mInitialTouchY = y; - mInitialTouchX = x; - mTracking = true; - mTouchSlopExceeded = true; - onTrackingStarted(); + startExpandMotion(x, y, true /* startTracking */, mExpandedHeight); return true; } } @@ -564,7 +565,10 @@ public abstract class PanelView extends FrameLayout { protected void fling(float vel, boolean expand) { cancelPeek(); float target = expand ? getMaxPanelHeight() : 0.0f; + flingToHeight(vel, expand, target); + } + protected void flingToHeight(float vel, boolean expand, float target) { // Hack to make the expand transition look nice when clear all button is visible - we make // the animation only to the last notification, and then jump to the maximum panel height so // clear all just fades in and the decelerating motion is towards the last notification. @@ -644,7 +648,7 @@ public abstract class PanelView extends FrameLayout { mHasLayoutedSinceDown = true; if (mUpdateFlingOnLayout) { abortAnimations(); - fling(mUpdateFlingVelocity, true); + fling(mUpdateFlingVelocity, true /* expands */); mUpdateFlingOnLayout = false; } } @@ -655,7 +659,7 @@ public abstract class PanelView extends FrameLayout { // If the user isn't actively poking us, let's update the height if ((!mTracking || isTrackingBlocked()) && mHeightAnimator == null - && mExpandedHeight > 0 + && !isShadeCollapsed() && currentMaxPanelHeight != mExpandedHeight && !mPeekPending && mPeekAnimator == null @@ -805,7 +809,7 @@ public abstract class PanelView extends FrameLayout { if (mExpanding) { notifyExpandingFinished(); } - setVisibility(VISIBLE); + notifyBarPanelExpansionChanged(); // Wait for window manager to pickup the change, so we know the maximum height of the panel // then. @@ -941,9 +945,9 @@ public abstract class PanelView extends FrameLayout { return animator; } - private void notifyBarPanelExpansionChanged() { + protected void notifyBarPanelExpansionChanged() { mBar.panelExpansionChanged(this, mExpandedFraction, mExpandedFraction > 0f || mPeekPending - || mPeekAnimator != null); + || mPeekAnimator != null || mInstantExpanding || mHeadsUpManager.hasPinnedHeadsUp()); } /** @@ -1014,4 +1018,10 @@ public abstract class PanelView extends FrameLayout { * @return the height of the clear all button, in pixels */ protected abstract int getClearAllHeight(); + + protected abstract boolean isShadeCollapsed(); + + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + } } 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 b0d6178..61e679a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -17,19 +17,6 @@ package com.android.systemui.statusbar.phone; -import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; -import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; -import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; -import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; -import static android.app.StatusBarManager.windowStateToString; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; -import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; @@ -86,13 +73,11 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.view.Display; -import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; -import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewStub; import android.view.WindowManager; @@ -115,13 +100,13 @@ import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.assist.AssistGestureManager; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSPanel; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.statusbar.ActivatableNotificationView; -import com.android.systemui.assist.AssistGestureManager; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.CommandQueue; @@ -137,7 +122,6 @@ import com.android.systemui.statusbar.NotificationOverflowContainer; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.SpeedBumpView; -import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; import com.android.systemui.statusbar.policy.AccessibilityController; @@ -147,7 +131,7 @@ import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.CastControllerImpl; import com.android.systemui.statusbar.policy.FlashlightController; -import com.android.systemui.statusbar.policy.HeadsUpNotificationView; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HotspotControllerImpl; import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.statusbar.policy.KeyguardMonitor; @@ -172,11 +156,27 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.TreeSet; + +import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; +import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; +import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; +import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; +import static android.app.StatusBarManager.windowStateToString; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; public class PhoneStatusBar extends BaseStatusBar implements DemoMode, - DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener { + DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, + HeadsUpManager.OnHeadsUpChangedListener { static final String TAG = "PhoneStatusBar"; public static final boolean DEBUG = BaseStatusBar.DEBUG; public static final boolean SPEW = false; @@ -360,11 +360,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (wasUsing != mUseHeadsUp) { if (!mUseHeadsUp) { Log.d(TAG, "dismissing any existing heads up notification on disable event"); - setHeadsUpVisibility(false); - mHeadsUpNotificationView.releaseImmediately(); - removeHeadsUpView(); - } else { - addHeadsUpView(); + mHeadsUpManager.releaseAllImmediately(); } } } @@ -528,6 +524,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, }; private HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>> mTmpChildOrderMap = new HashMap<>(); + private HashSet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new HashSet<>(); + private RankingMap mLatestRankingMap; @Override public void start() { @@ -598,7 +596,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } return mStatusBarWindow.onTouchEvent(event); - }}); + } + }); mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); mStatusBarView.setBar(this); @@ -615,12 +614,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mNotificationPanel.setBackground(new FastColorDrawable(context.getColor( R.color.notification_panel_solid_background))); } - if (ENABLE_HEADS_UP) { - mHeadsUpNotificationView = - (HeadsUpNotificationView) View.inflate(context, R.layout.heads_up, null); - mHeadsUpNotificationView.setVisibility(View.GONE); - mHeadsUpNotificationView.setBar(this); - } + + mHeadsUpManager = new HeadsUpManager(context, mNotificationPanel.getViewTreeObserver()); + mHeadsUpManager.setBar(this); + mHeadsUpManager.addListener(this); + mHeadsUpManager.addListener(mNotificationPanel); + mNotificationPanel.setHeadsUpManager(mHeadsUpManager); + mNotificationData.setHeadsUpManager(mHeadsUpManager); + if (MULTIUSER_DEBUG) { mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( R.id.header_debug_info); @@ -667,6 +668,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStackScroller.setLongPressListener(getNotificationLongClicker()); mStackScroller.setPhoneStatusBar(this); mStackScroller.setGroupManager(mGroupManager); + mStackScroller.setHeadsUpManager(mHeadsUpManager); mGroupManager.setOnGroupChangeListener(mStackScroller); mKeyguardIconOverflowContainer = @@ -699,7 +701,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front); - mScrimController = new ScrimController(scrimBehind, scrimInFront, mScrimSrcModeEnabled); + View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim); + mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim, + mScrimSrcModeEnabled); + mHeadsUpManager.addListener(mScrimController); + mStackScroller.setScrimController(mScrimController); mScrimController.setBackDropView(mBackdrop); mStatusBarView.setScrimController(mScrimController); mDozeScrimController = new DozeScrimController(mScrimController, context); @@ -1084,32 +1090,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return lp; } - private void addHeadsUpView() { - int headsUpHeight = mContext.getResources() - .getDimensionPixelSize(R.dimen.heads_up_window_height); - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - LayoutParams.MATCH_PARENT, headsUpHeight, - WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, // above the status bar! - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; - lp.gravity = Gravity.TOP; - lp.setTitle("Heads Up"); - lp.packageName = mContext.getPackageName(); - lp.windowAnimations = R.style.Animation_StatusBar_HeadsUp; - - mWindowManager.addView(mHeadsUpNotificationView, lp); - } - - private void removeHeadsUpView() { - mWindowManager.removeView(mHeadsUpNotificationView); - } - public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { mIconController.addSystemIcon(slot, index, viewIndex, icon); } @@ -1131,30 +1111,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void addNotification(StatusBarNotification notification, RankingMap ranking, Entry oldEntry) { if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey()); - if (mUseHeadsUp && shouldInterrupt(notification)) { - if (DEBUG) Log.d(TAG, "launching notification in heads up mode"); - Entry interruptionCandidate = oldEntry; - if (interruptionCandidate == null) { - final StatusBarIconView iconView = createIcon(notification); - if (iconView == null) { - return; - } - interruptionCandidate = new Entry(notification, iconView); - } - ViewGroup holder = mHeadsUpNotificationView.getHolder(); - if (inflateViewsForHeadsUp(interruptionCandidate, holder)) { - // 1. Populate mHeadsUpNotificationView - mHeadsUpNotificationView.showNotification(interruptionCandidate); - - // do not show the notification in the shade, yet. - return; - } - } Entry shadeEntry = createNotificationViews(notification); if (shadeEntry == null) { return; } + if (mUseHeadsUp && shouldInterrupt(notification)) { + mHeadsUpManager.showNotification(shadeEntry); + } if (notification.getNotification().fullScreenIntent != null) { // Stop screensaver if the notification has a full-screen intent. @@ -1175,18 +1139,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, setAreThereNotifications(); } - public void displayNotificationFromHeadsUp(Entry shadeEntry) { - - // The notification comes from the headsup, let's inflate the normal layout again - inflateViews(shadeEntry, mStackScroller); - shadeEntry.setInterruption(); - shadeEntry.row.setHeadsUp(false); - - addNotificationViews(shadeEntry, null); - // Recalculate the position of the sliding windows and the titles. - setAreThereNotifications(); - } - @Override protected void updateNotificationRanking(RankingMap ranking) { mNotificationData.updateRanking(ranking); @@ -1195,10 +1147,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void removeNotification(String key, RankingMap ranking) { - if (ENABLE_HEADS_UP) { - mHeadsUpNotificationView.removeNotification(key); + boolean defferRemoval = false; + if (mHeadsUpManager.isHeadsUp(key)) { + defferRemoval = !mHeadsUpManager.removeNotification(key); + } + if (defferRemoval) { + mLatestRankingMap = ranking; + mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); + return; } - StatusBarNotification old = removeNotificationViews(key, ranking); if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); @@ -1870,6 +1827,45 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, logStateToEventlog(); } + @Override + public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) { + if (exist) { + mStatusBarWindowManager.setHeadsUpShowing(true); + } else { + Runnable endRunnable = new Runnable() { + @Override + public void run() { + if (!mHeadsUpManager.hasPinnedHeadsUp()) { + mStatusBarWindowManager.setHeadsUpShowing(false); + } + } + }; + if (changeImmediatly) { + endRunnable.run(); + } else { + mStackScroller.performOnAnimationFinished(endRunnable); + } + } + } + + @Override + public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { + } + + @Override + public void OnHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { + if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) { + removeNotification(entry.key, mLatestRankingMap); + mHeadsUpEntriesToRemoveOnSwitch.remove(entry); + if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) { + mLatestRankingMap = null; + } + } else { + updateNotificationRanking(null); + } + + } + /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -1886,15 +1882,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, case MSG_CLOSE_PANELS: animateCollapsePanels(); break; - case MSG_SHOW_HEADS_UP: - setHeadsUpVisibility(true); - break; - case MSG_ESCALATE_HEADS_UP: - escalateHeadsUp(); - case MSG_HIDE_HEADS_UP: - mHeadsUpNotificationView.releaseImmediately(); - setHeadsUpVisibility(false); - break; case MSG_LAUNCH_TRANSITION_TIMEOUT: onLaunchTransitionTimeout(); break; @@ -1903,44 +1890,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void scheduleHeadsUpDecay(long delay) { - mHandler.removeMessages(MSG_HIDE_HEADS_UP); - if (mHeadsUpNotificationView.isClearable()) { - mHandler.sendEmptyMessageDelayed(MSG_HIDE_HEADS_UP, delay); - } - } - - @Override - public void scheduleHeadsUpOpen() { - mHandler.removeMessages(MSG_HIDE_HEADS_UP); - mHandler.removeMessages(MSG_SHOW_HEADS_UP); - mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP); - } - - @Override - public void scheduleHeadsUpClose() { - mHandler.removeMessages(MSG_HIDE_HEADS_UP); - if (mHeadsUpNotificationView.getVisibility() != View.GONE) { - mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP); - } - } - - @Override - public void scheduleHeadsUpEscalation() { - mHandler.removeMessages(MSG_HIDE_HEADS_UP); - mHandler.removeMessages(MSG_ESCALATE_HEADS_UP); - mHandler.sendEmptyMessage(MSG_ESCALATE_HEADS_UP); - } - - /** if the interrupting notification had a fullscreen intent, fire it now. */ - private void escalateHeadsUp() { - if (mHeadsUpNotificationView.getEntry() != null) { - final StatusBarNotification sbn = mHeadsUpNotificationView.getEntry().notification; - mHeadsUpNotificationView.releaseImmediately(); + public void escalateHeadsUp() { + TreeSet<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getSortedEntries(); + for (HeadsUpManager.HeadsUpEntry entry : entries) { + final StatusBarNotification sbn = entry.entry.notification; final Notification notification = sbn.getNotification(); if (notification.fullScreenIntent != null) { - if (DEBUG) + if (DEBUG) { Log.d(TAG, "converting a heads up to fullScreen"); + } try { EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, sbn.getKey()); @@ -1949,6 +1907,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } } + mHeadsUpManager.releaseAllImmediately(); } boolean panelsEnabled() { @@ -2081,10 +2040,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/); - // reset things to their proper state - mStackScroller.setVisibility(View.VISIBLE); - mNotificationPanel.setVisibility(View.GONE); - mNotificationPanel.closeQs(); mExpandedVisible = false; @@ -2478,8 +2433,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, pw.println(Settings.Global.zenModeToString(mZenMode)); pw.print(" mUseHeadsUp="); pw.println(mUseHeadsUp); - pw.print(" interrupting package: "); - pw.println(hunStateToString(mHeadsUpNotificationView.getEntry())); dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); if (mNavigationBarView != null) { pw.print(" mNavigationBarWindowState="); @@ -2571,10 +2524,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mSecurityController != null) { mSecurityController.dump(fd, pw, args); } - if (mHeadsUpNotificationView != null) { - mHeadsUpNotificationView.dump(fd, pw, args); + if (mHeadsUpManager != null) { + mHeadsUpManager.dump(fd, pw, args); } else { - pw.println(" mHeadsUpNotificationView: null"); + pw.println(" mHeadsUpManager: null"); } pw.println("SharedPreferences:"); @@ -2672,7 +2625,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mScreenOn = false; notifyNavigationBarScreenOn(false); - notifyHeadsUpScreenOn(false); + notifyHeadsUpScreenOff(); finishBarAnimations(); resetUserExpandedStates(); } @@ -2764,15 +2717,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mUserSetupObserver, mCurrentUserId); } - private void setHeadsUpVisibility(boolean vis) { - if (!ENABLE_HEADS_UP) return; - if (DEBUG) Log.v(TAG, (vis ? "showing" : "hiding") + " heads up window"); - EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_STATUS, - vis ? mHeadsUpNotificationView.getKey() : "", - vis ? 1 : 0); - mHeadsUpNotificationView.setVisibility(vis ? View.VISIBLE : View.GONE); - } - /** * Reload some of our resources when the configuration changes. * @@ -2791,9 +2735,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mNotificationPanel != null) { mNotificationPanel.updateResources(); } - if (mHeadsUpNotificationView != null) { - mHeadsUpNotificationView.updateResources(); - } if (mBrightnessMirrorController != null) { mBrightnessMirrorController.updateResources(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 0e8a794..e701783 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Color; @@ -29,13 +30,18 @@ import android.view.animation.Interpolator; import com.android.systemui.R; import com.android.systemui.statusbar.BackDropView; +import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.ScrimView; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.stack.StackStateAnimator; /** * Controls both the scrim behind the notifications and in front of the notifications (when a * security method gets shown). */ -public class ScrimController implements ViewTreeObserver.OnPreDrawListener { +public class ScrimController implements ViewTreeObserver.OnPreDrawListener, + HeadsUpManager.OnHeadsUpChangedListener { public static final long ANIMATION_DURATION = 220; private static final float SCRIM_BEHIND_ALPHA = 0.62f; @@ -43,10 +49,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f; private static final float SCRIM_IN_FRONT_ALPHA = 0.75f; private static final int TAG_KEY_ANIM = R.id.scrim; + private static final int TAG_HUN_START_ALPHA = R.id.hun_scrim_alpha_start; + private static final int TAG_HUN_END_ALPHA = R.id.hun_scrim_alpha_end; private final ScrimView mScrimBehind; private final ScrimView mScrimInFront; private final UnlockMethodCache mUnlockMethodCache; + private final View mHeadsUpScrim; private boolean mKeyguardShowing; private float mFraction; @@ -70,15 +79,22 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private float mDozeBehindAlpha; private float mCurrentInFrontAlpha; private float mCurrentBehindAlpha; + private float mCurrentHeadsUpAlpha = 1; + private int mAmountOfPinnedHeadsUps; + private float mTopHeadsUpDragAmount; + private View mDraggedHeadsUpView; - public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, boolean scrimSrcEnabled) { + public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim, + boolean scrimSrcEnabled) { mScrimBehind = scrimBehind; mScrimInFront = scrimInFront; + mHeadsUpScrim = headsUpScrim; final Context context = scrimBehind.getContext(); mUnlockMethodCache = UnlockMethodCache.getInstance(context); mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); mScrimSrcEnabled = scrimSrcEnabled; + updateHeadsUpScrim(false); } public void setKeyguardShowing(boolean showing) { @@ -217,7 +233,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } } - private void setScrimColor(ScrimView scrim, float alpha) { + private void setScrimColor(View scrim, float alpha) { Object runningAnim = scrim.getTag(TAG_KEY_ANIM); if (runningAnim instanceof ValueAnimator) { ((ValueAnimator) runningAnim).cancel(); @@ -236,25 +252,34 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } private float getCurrentScrimAlpha(View scrim) { - return scrim == mScrimBehind ? mCurrentBehindAlpha : mCurrentInFrontAlpha; + return scrim == mScrimBehind ? mCurrentBehindAlpha + : scrim == mScrimInFront ? mCurrentInFrontAlpha + : mCurrentHeadsUpAlpha; } private void setCurrentScrimAlpha(View scrim, float alpha) { if (scrim == mScrimBehind) { mCurrentBehindAlpha = alpha; - } else { + } else if (scrim == mScrimInFront) { mCurrentInFrontAlpha = alpha; + } else { + alpha = Math.max(0.0f, Math.min(1.0f, alpha)); + mCurrentHeadsUpAlpha = alpha; } } - private void updateScrimColor(ScrimView scrim) { + private void updateScrimColor(View scrim) { float alpha1 = getCurrentScrimAlpha(scrim); - float alpha2 = getDozeAlpha(scrim); - float alpha = 1 - (1 - alpha1) * (1 - alpha2); - scrim.setScrimColor(Color.argb((int) (alpha * 255), 0, 0, 0)); + if (scrim instanceof ScrimView) { + float alpha2 = getDozeAlpha(scrim); + float alpha = 1 - (1 - alpha1) * (1 - alpha2); + ((ScrimView) scrim).setScrimColor(Color.argb((int) (alpha * 255), 0, 0, 0)); + } else { + scrim.setAlpha(alpha1); + } } - private void startScrimAnimation(final ScrimView scrim, float target) { + private void startScrimAnimation(final View scrim, float target) { float current = getCurrentScrimAlpha(scrim); ValueAnimator anim = ValueAnimator.ofFloat(current, target); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @@ -320,4 +345,84 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { boolean asSrc = mBackDropView.getVisibility() != View.VISIBLE && mScrimSrcEnabled; mScrimBehind.setDrawAsSrc(asSrc); } + + @Override + public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) { + } + + @Override + public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) { + if (isHeadsUp) { + mAmountOfPinnedHeadsUps++; + } else { + mAmountOfPinnedHeadsUps--; + if (headsUp == mDraggedHeadsUpView) { + mDraggedHeadsUpView = null; + mTopHeadsUpDragAmount = 0.0f; + } + } + updateHeadsUpScrim(true); + } + + @Override + public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) { + } + + private void updateHeadsUpScrim(boolean animate) { + float alpha = calculateHeadsUpAlpha(); + ValueAnimator previousAnimator = StackStateAnimator.getChildTag(mHeadsUpScrim, + TAG_KEY_ANIM); + float animEndValue = -1; + if (previousAnimator != null) { + if ((animate || alpha == mCurrentHeadsUpAlpha)) { + // lets cancel any running animators + previousAnimator.cancel(); + } + animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, + TAG_HUN_START_ALPHA); + } + if (alpha != mCurrentHeadsUpAlpha && alpha != animEndValue) { + if (animate) { + startScrimAnimation(mHeadsUpScrim, alpha); + mHeadsUpScrim.setTag(TAG_HUN_START_ALPHA, mCurrentHeadsUpAlpha); + mHeadsUpScrim.setTag(TAG_HUN_END_ALPHA, alpha); + } else { + if (previousAnimator != null) { + float previousStartValue = StackStateAnimator.getChildTag(mHeadsUpScrim, + TAG_HUN_START_ALPHA); + float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, + TAG_HUN_END_ALPHA); + // we need to increase all animation keyframes of the previous animator by the + // relative change to the end value + PropertyValuesHolder[] values = previousAnimator.getValues(); + float relativeDiff = alpha - previousEndValue; + float newStartValue = previousStartValue + relativeDiff; + values[0].setFloatValues(newStartValue, alpha); + mHeadsUpScrim.setTag(TAG_HUN_START_ALPHA, newStartValue); + mHeadsUpScrim.setTag(TAG_HUN_END_ALPHA, alpha); + previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); + } else { + // update the alpha directly + setCurrentScrimAlpha(mHeadsUpScrim, alpha); + updateScrimColor(mHeadsUpScrim); + } + } + } + } + + public void setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount) { + mTopHeadsUpDragAmount = topHeadsUpDragAmount; + mDraggedHeadsUpView = draggedHeadsUpView; + updateHeadsUpScrim(false); + } + + private float calculateHeadsUpAlpha() { + if (mAmountOfPinnedHeadsUps >= 2) { + return 1.0f; + } else if (mAmountOfPinnedHeadsUps == 0) { + return 0.0f; + } else { + return 1.0f - mTopHeadsUpDragAmount; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index 63bbf97..84a9f64 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -130,7 +130,7 @@ public class StatusBarWindowManager { private void applyHeight(State state) { boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded - || state.keyguardFadingAway || state.bouncerShowing; + || state.keyguardFadingAway || state.bouncerShowing || state.headsUpShowing; if (expanded) { mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; } else { @@ -172,11 +172,20 @@ public class StatusBarWindowManager { applyUserActivityTimeout(state); applyInputFeatures(state); applyFitsSystemWindows(state); + applyModalFlag(state); if (mLp.copyFrom(mLpChanged) != 0) { mWindowManager.updateViewLayout(mStatusBarView, mLp); } } + private void applyModalFlag(State state) { + if (state.headsUpShowing) { + mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + } else { + mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + } + } + public void setKeyguardShowing(boolean showing) { mCurrentState.keyguardShowing = showing; apply(mCurrentState); @@ -218,6 +227,11 @@ public class StatusBarWindowManager { apply(mCurrentState); } + public void setHeadsUpShowing(boolean showing) { + mCurrentState.headsUpShowing = showing; + apply(mCurrentState); + } + /** * @param state The {@link StatusBarState} of the status bar. */ @@ -235,6 +249,7 @@ public class StatusBarWindowManager { boolean bouncerShowing; boolean keyguardFadingAway; boolean qsExpanded; + boolean headsUpShowing; /** * The {@link BaseStatusBar} state from the status bar. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java new file mode 100644 index 0000000..920a0a1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2011 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 android.content.Context; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.SystemClock; +import android.provider.Settings; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Pools; +import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; + +import com.android.systemui.R; +import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.phone.PhoneStatusBar; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Stack; +import java.util.TreeSet; + +public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener { + private static final String TAG = "HeadsUpManager"; + private static final boolean DEBUG = false; + private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms"; + + private final int mHeadsUpNotificationDecay; + private final int mMinimumDisplayTime; + + private final int mTouchSensitivityDelay; + private final ArrayMap<String, Long> mSnoozedPackages; + private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>(); + private final int mDefaultSnoozeLengthMs; + private final Handler mHandler = new Handler(); + private final Pools.Pool<HeadsUpEntry> mEntryPool = new Pools.Pool<HeadsUpEntry>() { + + private Stack<HeadsUpEntry> mPoolObjects = new Stack<>(); + + @Override + public HeadsUpEntry acquire() { + if (!mPoolObjects.isEmpty()) { + return mPoolObjects.pop(); + } + return new HeadsUpEntry(); + } + + @Override + public boolean release(HeadsUpEntry instance) { + instance.removeAutoCancelCallbacks(); + mPoolObjects.push(instance); + return true; + } + }; + + + private PhoneStatusBar mBar; + private int mSnoozeLengthMs; + private ContentObserver mSettingsObserver; + private HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>(); + private TreeSet<HeadsUpEntry> mSortedEntries = new TreeSet<>(); + private HashSet<String> mSwipedOutKeys = new HashSet<>(); + private int mUser; + private Clock mClock; + private boolean mReleaseOnExpandFinish; + private boolean mTrackingHeadsUp; + private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); + private boolean mIsExpanded; + private boolean mHasPinnedHeadsUp; + private int[] mTmpTwoArray = new int[2]; + + public HeadsUpManager(final Context context, ViewTreeObserver observer) { + Resources resources = context.getResources(); + mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay); + if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay); + mSnoozedPackages = new ArrayMap<>(); + mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms); + mSnoozeLengthMs = mDefaultSnoozeLengthMs; + mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time); + mHeadsUpNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay); + mClock = new Clock(); + + mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(), + SETTING_HEADS_UP_SNOOZE_LENGTH_MS, mDefaultSnoozeLengthMs); + mSettingsObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + final int packageSnoozeLengthMs = Settings.Global.getInt( + context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1); + if (packageSnoozeLengthMs > -1 && packageSnoozeLengthMs != mSnoozeLengthMs) { + mSnoozeLengthMs = packageSnoozeLengthMs; + if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); + } + } + }; + context.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false, + mSettingsObserver); + if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); + observer.addOnComputeInternalInsetsListener(this); + } + + public void setBar(PhoneStatusBar bar) { + mBar = bar; + } + + public void addListener(OnHeadsUpChangedListener listener) { + mListeners.add(listener); + } + + public PhoneStatusBar getBar() { + return mBar; + } + + /** + * Called when posting a new notification to the heads up. + */ + public void showNotification(NotificationData.Entry headsUp) { + if (DEBUG) Log.v(TAG, "showNotification"); + addHeadsUpEntry(headsUp); + updateNotification(headsUp, true); + headsUp.setInterruption(); + } + + /** + * Called when updating or posting a notification to the heads up. + */ + public void updateNotification(NotificationData.Entry headsUp, boolean alert) { + if (DEBUG) Log.v(TAG, "updateNotification"); + + headsUp.row.setChildrenExpanded(false /* expanded */, false /* animated */); + headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + + if (alert) { + HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key); + headsUpEntry.updateEntry(); + setEntryToShade(headsUpEntry, mIsExpanded, false /* justAdded */, false); + } + } + + private void addHeadsUpEntry(NotificationData.Entry entry) { + HeadsUpEntry headsUpEntry = mEntryPool.acquire(); + + // This will also add the entry to the sortedList + headsUpEntry.setEntry(entry); + mHeadsUpEntries.put(entry.key, headsUpEntry); + entry.row.setHeadsUp(true); + setEntryToShade(headsUpEntry, mIsExpanded /* inShade */, true /* justAdded */, false); + for (OnHeadsUpChangedListener listener : mListeners) { + listener.OnHeadsUpStateChanged(entry, true); + } + entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + } + + private void setEntryToShade(HeadsUpEntry headsUpEntry, boolean inShade, boolean justAdded, + boolean forceImmediate) { + ExpandableNotificationRow row = headsUpEntry.entry.row; + if (row.isInShade() != inShade || justAdded) { + row.setInShade(inShade); + if (!justAdded || !inShade) { + updatePinnedHeadsUpState(forceImmediate); + for (OnHeadsUpChangedListener listener : mListeners) { + listener.OnHeadsUpPinnedChanged(row, !inShade); + } + } + } + } + + private void removeHeadsUpEntry(NotificationData.Entry entry) { + HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key); + mSortedEntries.remove(remove); + mEntryPool.release(remove); + entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + entry.row.setHeadsUp(false); + setEntryToShade(remove, true /* inShade */, false /* justAdded */, + false /* forceImmediate */); + for (OnHeadsUpChangedListener listener : mListeners) { + listener.OnHeadsUpStateChanged(entry, false); + } + } + + private void updatePinnedHeadsUpState(boolean forceImmediate) { + boolean hasPinnedHeadsUp = hasPinnedHeadsUpInternal(); + if (hasPinnedHeadsUp == mHasPinnedHeadsUp) { + return; + } + mHasPinnedHeadsUp = hasPinnedHeadsUp; + for (OnHeadsUpChangedListener listener :mListeners) { + listener.OnPinnedHeadsUpExistChanged(hasPinnedHeadsUp, forceImmediate); + } + } + + /** + * React to the removal of the notification in the heads up. + * + * @return true if the notification was removed and false if it still needs to be kept around + * for a bit since it wasn't shown long enough + */ + public boolean removeNotification(String key) { + if (DEBUG) Log.v(TAG, "remove"); + if (wasShownLongEnough(key)) { + releaseImmediately(key); + return true; + } else { + getHeadsUpEntry(key).hideAsSoonAsPossible(); + return false; + } + } + + private boolean wasShownLongEnough(String key) { + HeadsUpEntry headsUpEntry = getHeadsUpEntry(key); + HeadsUpEntry topEntry = getTopEntry(); + if (mSwipedOutKeys.contains(key)) { + // We always instantly dismiss views being manually swiped out. + mSwipedOutKeys.remove(key); + return true; + } + if (headsUpEntry != topEntry) { + return true; + } + return headsUpEntry.wasShownLongEnough(); + } + + public boolean isHeadsUp(String key) { + return mHeadsUpEntries.containsKey(key); + } + + + /** + * Push any current Heads Up notification down into the shade. + */ + public void releaseAllImmediately() { + if (DEBUG) Log.v(TAG, "releaseAllImmediately"); + HashSet<String> keys = new HashSet<>(mHeadsUpEntries.keySet()); + for (String key: keys) { + releaseImmediately(key); + } + } + + public void releaseImmediately(String key) { + HeadsUpEntry headsUpEntry = getHeadsUpEntry(key); + if (headsUpEntry == null) { + return; + } + NotificationData.Entry shadeEntry = headsUpEntry.entry; + removeHeadsUpEntry(shadeEntry); + } + + public boolean isSnoozed(String packageName) { + final String key = snoozeKey(packageName, mUser); + Long snoozedUntil = mSnoozedPackages.get(key); + if (snoozedUntil != null) { + if (snoozedUntil > SystemClock.elapsedRealtime()) { + if (DEBUG) Log.v(TAG, key + " snoozed"); + return true; + } + mSnoozedPackages.remove(packageName); + } + return false; + } + + public void snooze() { + for (String key: mHeadsUpEntries.keySet()) { + HeadsUpEntry entry = mHeadsUpEntries.get(key); + String packageName = entry.entry.notification.getPackageName(); + mSnoozedPackages.put(snoozeKey(packageName, mUser), + SystemClock.elapsedRealtime() + mSnoozeLengthMs); + } + mReleaseOnExpandFinish = true; + } + + private static String snoozeKey(String packageName, int user) { + return user + "," + packageName; + } + + private HeadsUpEntry getHeadsUpEntry(String key) { + return mHeadsUpEntries.get(key); + } + + public NotificationData.Entry getEntry(String key) { + return mHeadsUpEntries.get(key).entry; + } + + public TreeSet<HeadsUpEntry> getSortedEntries() { + return mSortedEntries; + } + + public HeadsUpEntry getTopEntry() { + return mSortedEntries.isEmpty() ? null : mSortedEntries.first(); + } + + /** + * @param key the key of the touched notification + * @return whether the touch is valid and should not be discarded + */ + public boolean shouldSwallowClick(String key) { + if (mClock.currentTimeMillis() < mHeadsUpEntries.get(key).postTime) { + return true; + } + return false; + } + + public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { + if (!mIsExpanded && mHasPinnedHeadsUp) { + int minX = Integer.MAX_VALUE; + int maxX = 0; + int minY = Integer.MAX_VALUE; + int maxY = 0; + for (HeadsUpEntry entry: mSortedEntries) { + ExpandableNotificationRow row = entry.entry.row; + if (!row.isInShade()) { + row.getLocationOnScreen(mTmpTwoArray); + minX = Math.min(minX, mTmpTwoArray[0]); + minY = Math.min(minY, 0); + maxX = Math.max(maxX, mTmpTwoArray[0] + row.getWidth()); + maxY = Math.max(maxY, row.getHeadsUpHeight()); + } + } + + info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); + info.touchableRegion.set(minX, minY, maxX, maxY); + } + } + + public void setUser(int user) { + mUser = user; + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("HeadsUpManager state:"); + pw.print(" mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay); + pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs); + pw.print(" now="); pw.println(SystemClock.elapsedRealtime()); + pw.print(" mUser="); pw.println(mUser); + for (HeadsUpEntry entry: mSortedEntries) { + pw.print(" HeadsUpEntry="); pw.println(entry.entry); + } + int N = mSnoozedPackages.size(); + pw.println(" snoozed packages: " + N); + for (int i = 0; i < N; i++) { + pw.print(" "); pw.print(mSnoozedPackages.valueAt(i)); + pw.print(", "); pw.println(mSnoozedPackages.keyAt(i)); + } + } + + public boolean hasPinnedHeadsUp() { + return mHasPinnedHeadsUp; + } + + private boolean hasPinnedHeadsUpInternal() { + for (String key: mHeadsUpEntries.keySet()) { + HeadsUpEntry entry = mHeadsUpEntries.get(key); + if (!entry.entry.row.isInShade()) { + return true; + } + } + return false; + } + + public void addSwipedOutKey(String key) { + mSwipedOutKeys.add(key); + } + + public float getHighestPinnedHeadsUp() { + float max = 0; + for (HeadsUpEntry entry: mSortedEntries) { + if (!entry.entry.row.isInShade()) { + max = Math.max(max, entry.entry.row.getActualHeight()); + } + } + return max; + } + + public void releaseAllToShade() { + for (String key: mHeadsUpEntries.keySet()) { + HeadsUpEntry entry = mHeadsUpEntries.get(key); + setEntryToShade(entry, true /* toShade */, false /* justAdded */, + true /* forceImmediate */); + } + } + + public void onExpandingFinished() { + if (mReleaseOnExpandFinish) { + releaseAllImmediately(); + mReleaseOnExpandFinish = false; + } else { + for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) { + removeHeadsUpEntry(entry); + } + mEntriesToRemoveAfterExpand.clear(); + } + } + + public void setTrackingHeadsUp(boolean trackingHeadsUp) { + mTrackingHeadsUp = trackingHeadsUp; + } + + public void setIsExpanded(boolean isExpanded) { + if (isExpanded != mIsExpanded) { + mIsExpanded = isExpanded; + if (isExpanded) { + releaseAllToShade(); + } + } + } + + public int getTopHeadsUpHeight() { + HeadsUpEntry topEntry = getTopEntry(); + return topEntry != null ? topEntry.entry.row.getHeadsUpHeight() : 0; + } + + public int compare(NotificationData.Entry a, NotificationData.Entry b) { + HeadsUpEntry aEntry = getHeadsUpEntry(a.key); + HeadsUpEntry bEntry = getHeadsUpEntry(b.key); + if (aEntry == null || bEntry == null) { + return aEntry == null ? 1 : -1; + } + return aEntry.compareTo(bEntry); + } + + public class HeadsUpEntry implements Comparable<HeadsUpEntry> { + public NotificationData.Entry entry; + public long postTime; + public long earliestRemovaltime; + private Runnable mRemoveHeadsUpRunnable; + + public void setEntry(final NotificationData.Entry entry) { + this.entry = entry; + + // The actual post time will be just after the heads-up really slided in + postTime = mClock.currentTimeMillis() + mTouchSensitivityDelay; + mRemoveHeadsUpRunnable = new Runnable() { + @Override + public void run() { + if (!mTrackingHeadsUp) { + removeHeadsUpEntry(entry); + } else { + mEntriesToRemoveAfterExpand.add(entry); + } + } + }; + updateEntry(); + } + + public void updateEntry() { + long currentTime = mClock.currentTimeMillis(); + postTime = Math.max(postTime, currentTime); + long finishTime = postTime + mHeadsUpNotificationDecay; + long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); + earliestRemovaltime = currentTime + mMinimumDisplayTime; + removeAutoCancelCallbacks(); + mHandler.postDelayed(mRemoveHeadsUpRunnable, removeDelay); + updateSortOrder(HeadsUpEntry.this); + } + + @Override + public int compareTo(HeadsUpEntry o) { + return postTime < o.postTime ? 1 + : postTime == o.postTime ? 0 + : -1; + } + + public void removeAutoCancelCallbacks() { + mHandler.removeCallbacks(mRemoveHeadsUpRunnable); + } + + public boolean wasShownLongEnough() { + return earliestRemovaltime < mClock.currentTimeMillis(); + } + + public void hideAsSoonAsPossible() { + removeAutoCancelCallbacks(); + mHandler.postDelayed(mRemoveHeadsUpRunnable, + earliestRemovaltime - mClock.currentTimeMillis()); + } + } + + /** + * Update the sorted heads up order. + * + * @param headsUpEntry the headsUp that changed + */ + private void updateSortOrder(HeadsUpEntry headsUpEntry) { + mSortedEntries.remove(headsUpEntry); + mSortedEntries.add(headsUpEntry); + } + + public static class Clock { + public long currentTimeMillis() { + return SystemClock.elapsedRealtime(); + } + } + + public interface OnHeadsUpChangedListener { + void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly); + void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp); + void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java deleted file mode 100644 index 1e40bab..0000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (C) 2011 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 android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.graphics.Outline; -import android.graphics.Rect; -import android.os.SystemClock; -import android.provider.Settings; -import android.util.ArrayMap; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; -import android.view.ViewTreeObserver; -import android.view.accessibility.AccessibilityEvent; -import android.widget.FrameLayout; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.ExpandHelper; -import com.android.systemui.Gefingerpoken; -import com.android.systemui.R; -import com.android.systemui.SwipeHelper; -import com.android.systemui.statusbar.ExpandableView; -import com.android.systemui.statusbar.NotificationData; -import com.android.systemui.statusbar.phone.PhoneStatusBar; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.Callback, ExpandHelper.Callback, - ViewTreeObserver.OnComputeInternalInsetsListener { - private static final String TAG = "HeadsUpNotificationView"; - private static final boolean DEBUG = false; - private static final boolean SPEW = DEBUG; - private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms"; - - Rect mTmpRect = new Rect(); - int[] mTmpTwoArray = new int[2]; - - private final int mHeadsUpNotificationDecay; - private final int mMinimumDisplayTime; - - private final int mTouchSensitivityDelay; - private final float mMaxAlpha = 1f; - private final ArrayMap<String, Long> mSnoozedPackages; - private final int mDefaultSnoozeLengthMs; - - private SwipeHelper mSwipeHelper; - private EdgeSwipeHelper mEdgeSwipeHelper; - - private PhoneStatusBar mBar; - - private long mLingerUntilMs; - private long mStartTouchTime; - private ViewGroup mContentHolder; - private int mSnoozeLengthMs; - private ContentObserver mSettingsObserver; - - private NotificationData.Entry mHeadsUp; - private int mUser; - private String mMostRecentPackageName; - private boolean mTouched; - private Clock mClock; - - public static class Clock { - public long currentTimeMillis() { - return SystemClock.elapsedRealtime(); - } - } - - public HeadsUpNotificationView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public HeadsUpNotificationView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - Resources resources = context.getResources(); - mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay); - if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay); - mSnoozedPackages = new ArrayMap<>(); - mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms); - mSnoozeLengthMs = mDefaultSnoozeLengthMs; - mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time); - mHeadsUpNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay); - mClock = new Clock(); - } - - @VisibleForTesting - public HeadsUpNotificationView(Context context, Clock clock, SwipeHelper swipeHelper, - EdgeSwipeHelper edgeSwipeHelper, int headsUpNotificationDecay, int minimumDisplayTime, - int touchSensitivityDelay, int snoozeLength) { - super(context, null); - mClock = clock; - mSwipeHelper = swipeHelper; - mEdgeSwipeHelper = edgeSwipeHelper; - mMinimumDisplayTime = minimumDisplayTime; - mHeadsUpNotificationDecay = headsUpNotificationDecay; - mTouchSensitivityDelay = touchSensitivityDelay; - mSnoozedPackages = new ArrayMap<>(); - mDefaultSnoozeLengthMs = snoozeLength; - } - - public void updateResources() { - if (mContentHolder != null) { - final LayoutParams lp = (LayoutParams) mContentHolder.getLayoutParams(); - lp.width = getResources().getDimensionPixelSize(R.dimen.notification_panel_width); - lp.gravity = getResources().getInteger(R.integer.notification_panel_layout_gravity); - mContentHolder.setLayoutParams(lp); - } - } - - public void setBar(PhoneStatusBar bar) { - mBar = bar; - } - - public PhoneStatusBar getBar() { - return mBar; - } - - public ViewGroup getHolder() { - return mContentHolder; - } - - /** - * Called when posting a new notification to the heads up. - */ - public void showNotification(NotificationData.Entry headsUp) { - if (DEBUG) Log.v(TAG, "showNotification"); - if (mHeadsUp != null) { - // bump any previous heads up back to the shade - releaseImmediately(); - } - mTouched = false; - updateNotification(headsUp, true); - mLingerUntilMs = mClock.currentTimeMillis() + mMinimumDisplayTime; - } - - /** - * Called when updating or posting a notification to the heads up. - */ - public void updateNotification(NotificationData.Entry headsUp, boolean alert) { - if (DEBUG) Log.v(TAG, "updateNotification"); - - if (mHeadsUp == headsUp) { - resetViewForHeadsup(); - // This is an in-place update. Noting more to do. - return; - } - - mHeadsUp = headsUp; - - if (mContentHolder != null) { - mContentHolder.removeAllViews(); - } - - if (mHeadsUp != null) { - mMostRecentPackageName = mHeadsUp.notification.getPackageName(); - if (mHeadsUp.row != null) { - resetViewForHeadsup(); - } - - mStartTouchTime = SystemClock.elapsedRealtime() + mTouchSensitivityDelay; - if (mContentHolder != null) { // only null in tests and before we are attached to a window - mContentHolder.setX(0); - mContentHolder.setVisibility(View.VISIBLE); - mContentHolder.setAlpha(mMaxAlpha); - mContentHolder.addView(mHeadsUp.row); - sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - - mSwipeHelper.snapChild(mContentHolder, 1f); - } - - mHeadsUp.setInterruption(); - } - if (alert) { - // Make sure the heads up window is open. - mBar.scheduleHeadsUpOpen(); - mBar.scheduleHeadsUpDecay(mHeadsUpNotificationDecay); - } - } - - private void resetViewForHeadsup() { - if (mHeadsUp.row.areChildrenExpanded()) { - mHeadsUp.row.setChildrenExpanded(false /* expanded */, false /* animated */); - } - mHeadsUp.row.setSystemExpanded(true); - mHeadsUp.row.setSensitive(false); - mHeadsUp.row.setHeadsUp(true); - mHeadsUp.row.setTranslationY(0); - mHeadsUp.row.setTranslationZ(0); - mHeadsUp.row.setHideSensitive( - false, false /* animated */, 0 /* delay */, 0 /* duration */); - } - - /** - * Possibly enter the lingering state by delaying the closing of the window. - * - * @return true if the notification has entered the lingering state. - */ - private boolean startLingering(boolean removed) { - final long now = mClock.currentTimeMillis(); - if (!mTouched && mHeadsUp != null && now < mLingerUntilMs) { - if (removed) { - mHeadsUp = null; - } - mBar.scheduleHeadsUpDecay(mLingerUntilMs - now); - return true; - } - return false; - } - - /** - * React to the removal of the notification in the heads up. - */ - public void removeNotification(String key) { - if (DEBUG) Log.v(TAG, "remove"); - if (mHeadsUp == null || !mHeadsUp.key.equals(key)) { - return; - } - if (!startLingering(/* removed */ true)) { - mHeadsUp = null; - releaseImmediately(); - } - } - - /** - * Ask for any current Heads Up notification to be pushed down into the shade. - */ - public void release() { - if (DEBUG) Log.v(TAG, "release"); - if (!startLingering(/* removed */ false)) { - releaseImmediately(); - } - } - - /** - * Push any current Heads Up notification down into the shade. - */ - public void releaseImmediately() { - if (DEBUG) Log.v(TAG, "releaseImmediately"); - if (mHeadsUp != null) { - mContentHolder.removeView(mHeadsUp.row); - mBar.displayNotificationFromHeadsUp(mHeadsUp); - } - mHeadsUp = null; - mBar.scheduleHeadsUpClose(); - } - - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - if (DEBUG) Log.v(TAG, "onVisibilityChanged: " + visibility); - if (changedView.getVisibility() == VISIBLE) { - mStartTouchTime = mClock.currentTimeMillis() + mTouchSensitivityDelay; - sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - } - } - - public boolean isSnoozed(String packageName) { - final String key = snoozeKey(packageName, mUser); - Long snoozedUntil = mSnoozedPackages.get(key); - if (snoozedUntil != null) { - if (snoozedUntil > SystemClock.elapsedRealtime()) { - if (DEBUG) Log.v(TAG, key + " snoozed"); - return true; - } - mSnoozedPackages.remove(packageName); - } - return false; - } - - private void snooze() { - if (mMostRecentPackageName != null) { - mSnoozedPackages.put(snoozeKey(mMostRecentPackageName, mUser), - SystemClock.elapsedRealtime() + mSnoozeLengthMs); - } - releaseImmediately(); - } - - private static String snoozeKey(String packageName, int user) { - return user + "," + packageName; - } - - public boolean isShowing(String key) { - return mHeadsUp != null && mHeadsUp.key.equals(key); - } - - public NotificationData.Entry getEntry() { - return mHeadsUp; - } - - public boolean isClearable() { - return mHeadsUp == null || mHeadsUp.notification.isClearable(); - } - - // ViewGroup methods - -private static final ViewOutlineProvider CONTENT_HOLDER_OUTLINE_PROVIDER = - new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - int outlineLeft = view.getPaddingLeft(); - int outlineTop = view.getPaddingTop(); - - // Apply padding to shadow. - outline.setRect(outlineLeft, outlineTop, - view.getWidth() - outlineLeft - view.getPaddingRight(), - view.getHeight() - outlineTop - view.getPaddingBottom()); - } - }; - - @Override - public void onAttachedToWindow() { - final ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext()); - float touchSlop = viewConfiguration.getScaledTouchSlop(); - mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext()); - mSwipeHelper.setMaxSwipeProgress(mMaxAlpha); - mEdgeSwipeHelper = new EdgeSwipeHelper(this, touchSlop); - - int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height); - int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height); - - mContentHolder = (ViewGroup) findViewById(R.id.content_holder); - mContentHolder.setOutlineProvider(CONTENT_HOLDER_OUTLINE_PROVIDER); - - mSnoozeLengthMs = Settings.Global.getInt(mContext.getContentResolver(), - SETTING_HEADS_UP_SNOOZE_LENGTH_MS, mDefaultSnoozeLengthMs); - mSettingsObserver = new ContentObserver(getHandler()) { - @Override - public void onChange(boolean selfChange) { - final int packageSnoozeLengthMs = Settings.Global.getInt( - mContext.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1); - if (packageSnoozeLengthMs > -1 && packageSnoozeLengthMs != mSnoozeLengthMs) { - mSnoozeLengthMs = packageSnoozeLengthMs; - if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); - } - } - }; - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false, - mSettingsObserver); - if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); - - if (mHeadsUp != null) { - // whoops, we're on already! - showNotification(mHeadsUp); - } - - getViewTreeObserver().addOnComputeInternalInsetsListener(this); - } - - - @Override - protected void onDetachedFromWindow() { - mContext.getContentResolver().unregisterContentObserver(mSettingsObserver); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); - if (mClock.currentTimeMillis() < mStartTouchTime) { - return true; - } - mTouched = true; - return mEdgeSwipeHelper.onInterceptTouchEvent(ev) - || mSwipeHelper.onInterceptTouchEvent(ev) - || mHeadsUp == null // lingering - || super.onInterceptTouchEvent(ev); - } - - // View methods - - @Override - public void onDraw(android.graphics.Canvas c) { - super.onDraw(c); - if (DEBUG) { - //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: " - // + getMeasuredHeight() + "px"); - c.save(); - c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6, - android.graphics.Region.Op.DIFFERENCE); - c.drawColor(0xFFcc00cc); - c.restore(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (mClock.currentTimeMillis() < mStartTouchTime) { - return false; - } - - final boolean wasRemoved = mHeadsUp == null; - if (!wasRemoved) { - mBar.scheduleHeadsUpDecay(mHeadsUpNotificationDecay); - } - return mEdgeSwipeHelper.onTouchEvent(ev) - || mSwipeHelper.onTouchEvent(ev) - || wasRemoved - || super.onTouchEvent(ev); - } - - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - float densityScale = getResources().getDisplayMetrics().density; - mSwipeHelper.setDensityScale(densityScale); - float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); - mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); - } - - // ExpandHelper.Callback methods - - @Override - public ExpandableView getChildAtRawPosition(float x, float y) { - return getChildAtPosition(x, y); - } - - @Override - public ExpandableView getChildAtPosition(float x, float y) { - return mHeadsUp == null ? null : mHeadsUp.row; - } - - @Override - public boolean canChildBeExpanded(View v) { - return mHeadsUp != null && mHeadsUp.row == v && mHeadsUp.row.isExpandable(); - } - - @Override - public void setUserExpandedChild(View v, boolean userExpanded) { - if (mHeadsUp != null && mHeadsUp.row == v) { - mHeadsUp.row.setUserExpanded(userExpanded); - } - } - - @Override - public void setUserLockedChild(View v, boolean userLocked) { - if (mHeadsUp != null && mHeadsUp.row == v) { - mHeadsUp.row.setUserLocked(userLocked); - } - } - - @Override - public void expansionStateChanged(boolean isExpanding) { - - } - - // SwipeHelper.Callback methods - - @Override - public boolean canChildBeDismissed(View v) { - return true; - } - - @Override - public boolean isAntiFalsingNeeded() { - return false; - } - - @Override - public float getFalsingThresholdFactor() { - return 1.0f; - } - - @Override - public void onChildDismissed(View v) { - Log.v(TAG, "User swiped heads up to dismiss"); - if (mHeadsUp != null && mHeadsUp.notification.isClearable()) { - mBar.onNotificationClear(mHeadsUp.notification); - mHeadsUp = null; - } - releaseImmediately(); - } - - @Override - public void onBeginDrag(View v) { - } - - @Override - public void onDragCancelled(View v) { - mContentHolder.setAlpha(mMaxAlpha); // sometimes this isn't quite reset - } - - @Override - public void onChildSnappedBack(View animView) { - } - - @Override - public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) { - getBackground().setAlpha((int) (255 * swipeProgress)); - return false; - } - - @Override - public View getChildAtPosition(MotionEvent ev) { - return mContentHolder; - } - - @Override - public View getChildContentView(View v) { - return mContentHolder; - } - - @Override - public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - mContentHolder.getLocationOnScreen(mTmpTwoArray); - - info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); - info.touchableRegion.set(mTmpTwoArray[0], mTmpTwoArray[1], - mTmpTwoArray[0] + mContentHolder.getWidth(), - mTmpTwoArray[1] + mContentHolder.getHeight()); - } - - public void escalate() { - mBar.scheduleHeadsUpEscalation(); - } - - public String getKey() { - return mHeadsUp == null ? null : mHeadsUp.notification.getKey(); - } - - public void setUser(int user) { - mUser = user; - } - - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("HeadsUpNotificationView state:"); - pw.print(" mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay); - pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs); - pw.print(" mLingerUntilMs="); pw.println(mLingerUntilMs); - pw.print(" mTouched="); pw.println(mTouched); - pw.print(" mMostRecentPackageName="); pw.println(mMostRecentPackageName); - pw.print(" mStartTouchTime="); pw.println(mStartTouchTime); - pw.print(" now="); pw.println(SystemClock.elapsedRealtime()); - pw.print(" mUser="); pw.println(mUser); - if (mHeadsUp == null) { - pw.println(" mHeadsUp=null"); - } else { - pw.print(" mHeadsUp="); pw.println(mHeadsUp.notification.getKey()); - } - int N = mSnoozedPackages.size(); - pw.println(" snoozed packages: " + N); - for (int i = 0; i < N; i++) { - pw.print(" "); pw.print(mSnoozedPackages.valueAt(i)); - pw.print(", "); pw.println(mSnoozedPackages.keyAt(i)); - } - } - - public static class EdgeSwipeHelper implements Gefingerpoken { - private static final boolean DEBUG_EDGE_SWIPE = false; - private final float mTouchSlop; - private final HeadsUpNotificationView mHeadsUpView; - private boolean mConsuming; - private float mFirstY; - private float mFirstX; - - public EdgeSwipeHelper(HeadsUpNotificationView headsUpView, float touchSlop) { - mHeadsUpView = headsUpView; - mTouchSlop = touchSlop; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - switch (ev.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action down " + ev.getY()); - mFirstX = ev.getX(); - mFirstY = ev.getY(); - mConsuming = false; - break; - - case MotionEvent.ACTION_MOVE: - if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action move " + ev.getY()); - final float dY = ev.getY() - mFirstY; - final float daX = Math.abs(ev.getX() - mFirstX); - final float daY = Math.abs(dY); - if (!mConsuming && daX < daY && daY > mTouchSlop) { - mHeadsUpView.snooze(); - if (dY > 0) { - if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found an open"); - mHeadsUpView.getBar().animateExpandNotificationsPanel(); - } - mConsuming = true; - } - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action done"); - mConsuming = false; - break; - } - return mConsuming; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - return mConsuming; - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index ba938cc..c3c6b12 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -114,6 +114,11 @@ public class MobileSignalController extends SignalController< setInetCondition(inetCondition); } + public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { + mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode; + notifyListenersIfNecessary(); + } + /** * Start listening for phone state changes. */ @@ -123,7 +128,8 @@ public class MobileSignalController extends SignalController< | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CALL_STATE | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY); + | PhoneStateListener.LISTEN_DATA_ACTIVITY + | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE); } /** @@ -201,8 +207,12 @@ public class MobileSignalController extends SignalController< && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription, qsTypeIcon, - mCurrentState.dataConnected && mCurrentState.activityIn, - mCurrentState.dataConnected && mCurrentState.activityOut, + mCurrentState.dataConnected + && !mCurrentState.carrierNetworkChangeMode + && mCurrentState.activityIn, + mCurrentState.dataConnected + && !mCurrentState.carrierNetworkChangeMode + && mCurrentState.activityOut, dataContentDescription, mCurrentState.isEmergency ? null : mCurrentState.networkName, // Only wide if actually showing something. @@ -215,6 +225,7 @@ public class MobileSignalController extends SignalController< mSignalClusters.get(i).setMobileDataIndicators( mCurrentState.enabled && !mCurrentState.airplaneMode, getCurrentIconId(), + getCurrentDarkIconId(), typeIcon, contentDescription, dataContentDescription, @@ -224,6 +235,10 @@ public class MobileSignalController extends SignalController< } } + private int getCurrentDarkIconId() { + return getCurrentIconId(false /* light */); + } + @Override protected MobileState cleanState() { return new MobileState(); @@ -270,6 +285,10 @@ public class MobileSignalController extends SignalController< } } + private boolean isCarrierNetworkChangeActive() { + return !hasService() && mCurrentState.carrierNetworkChangeMode; + } + public void handleBroadcast(Intent intent) { String action = intent.getAction(); if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { @@ -351,7 +370,9 @@ public class MobileSignalController extends SignalController< mCurrentState.dataConnected = mCurrentState.connected && mDataState == TelephonyManager.DATA_CONNECTED; - if (isRoaming()) { + if (isCarrierNetworkChangeActive()) { + mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; + } else if (isRoaming()) { mCurrentState.iconGroup = TelephonyIcons.ROAMING; } if (isEmergencyOnly() != mCurrentState.isEmergency) { @@ -363,6 +384,7 @@ public class MobileSignalController extends SignalController< && mServiceState.getOperatorAlphaShort() != null) { mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); } + notifyListenersIfNecessary(); } @@ -428,6 +450,16 @@ public class MobileSignalController extends SignalController< } setActivity(direction); } + + @Override + public void onCarrierNetworkChange(boolean active) { + if (DEBUG) { + Log.d(mTag, "onCarrierNetworkChange: active=" + active); + } + mCurrentState.carrierNetworkChangeMode = active; + + updateTelephony(); + } }; static class MobileIconGroup extends SignalController.IconGroup { @@ -440,8 +472,17 @@ public class MobileSignalController extends SignalController< int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, int discContentDesc, int dataContentDesc, int dataType, boolean isWide, int[] qsDataType) { - super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, - qsDiscState, discContentDesc); + this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, + sbDiscState, sbDiscState, qsDiscState, discContentDesc, dataContentDesc, + dataType, isWide, qsDataType); + } + + public MobileIconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons, + int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, + int sbDarkDiscState, int qsDiscState, int discContentDesc, int dataContentDesc, + int dataType, boolean isWide, int[] qsDataType) { + super(name, sbIcons, sbDarkIcons, qsIcons, contentDesc, sbNullState, qsNullState, + sbDiscState, sbDarkDiscState, qsDiscState, discContentDesc); mDataContentDescription = dataContentDesc; mDataType = dataType; mIsWide = isWide; @@ -455,6 +496,7 @@ public class MobileSignalController extends SignalController< boolean dataConnected; boolean isEmergency; boolean airplaneMode; + boolean carrierNetworkChangeMode; int inetForNetwork; @Override @@ -467,6 +509,7 @@ public class MobileSignalController extends SignalController< inetForNetwork = state.inetForNetwork; isEmergency = state.isEmergency; airplaneMode = state.airplaneMode; + carrierNetworkChangeMode = state.carrierNetworkChangeMode; } @Override @@ -478,7 +521,8 @@ public class MobileSignalController extends SignalController< builder.append("dataConnected=").append(dataConnected).append(','); builder.append("inetForNetwork=").append(inetForNetwork).append(','); builder.append("isEmergency=").append(isEmergency).append(','); - builder.append("airplaneMode=").append(airplaneMode); + builder.append("airplaneMode=").append(airplaneMode).append(','); + builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode); } @Override @@ -489,6 +533,7 @@ public class MobileSignalController extends SignalController< && ((MobileState) o).dataConnected == dataConnected && ((MobileState) o).isEmergency == isEmergency && ((MobileState) o).airplaneMode == airplaneMode + && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode && ((MobileState) o).inetForNetwork == inetForNetwork; } } 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 bb3eb7a..5cf6a6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -704,6 +704,13 @@ public class NetworkControllerImpl extends BroadcastReceiver controller.getState().enabled = show; controller.notifyListeners(); } + String carrierNetworkChange = args.getString("carriernetworkchange"); + if (carrierNetworkChange != null) { + boolean show = carrierNetworkChange.equals("show"); + for (MobileSignalController controller : mMobileSignalControllers.values()) { + controller.setCarrierNetworkChangeMode(show); + } + } } } @@ -718,9 +725,9 @@ public class NetworkControllerImpl extends BroadcastReceiver public interface SignalCluster { void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); - void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean isTypeIconWide, - int subId); + void setMobileDataIndicators(boolean visible, int strengthIcon, int darkStrengthIcon, + int typeIcon, String contentDescription, String typeContentDescription, + boolean isTypeIconWide, int subId); void setSubs(List<SubscriptionInfo> subs); void setNoSims(boolean show); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java index 1d96c6b..c204814 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java @@ -142,8 +142,16 @@ public abstract class SignalController<T extends SignalController.State, * Gets the signal icon for SB based on current state of connected, enabled, and level. */ public int getCurrentIconId() { + return getCurrentIconId(true /* light */); + } + + protected int getCurrentIconId(boolean light) { if (mCurrentState.connected) { - return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; + if (light) { + return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; + } else { + return getIcons().mSbDarkIcons[mCurrentState.inetCondition][mCurrentState.level]; + } } else if (mCurrentState.enabled) { return getIcons().mSbDiscState; } else { @@ -226,11 +234,13 @@ public abstract class SignalController<T extends SignalController.State, */ static class IconGroup { final int[][] mSbIcons; + final int[][] mSbDarkIcons; final int[][] mQsIcons; final int[] mContentDesc; final int mSbNullState; final int mQsNullState; final int mSbDiscState; + final int mSbDarkDiscState; final int mQsDiscState; final int mDiscContentDesc; // For logging. @@ -239,13 +249,22 @@ public abstract class SignalController<T extends SignalController.State, public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, int discContentDesc) { + this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, + sbDiscState, sbDiscState, qsDiscState, discContentDesc); + } + + public IconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons, + int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, + int sbDarkDiscState, int qsDiscState, int discContentDesc) { mName = name; mSbIcons = sbIcons; + mSbDarkIcons = sbDarkIcons; mQsIcons = qsIcons; mContentDesc = contentDesc; mSbNullState = sbNullState; mQsNullState = qsNullState; mSbDiscState = sbDiscState; + mSbDarkDiscState = sbDarkDiscState; mQsDiscState = qsDiscState; mDiscContentDesc = discContentDesc; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index d266ed8..053feb12 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -68,6 +68,42 @@ class TelephonyIcons { R.drawable.stat_sys_signal_4_fully } }; + //CarrierNetworkChange + static final int[][] TELEPHONY_CARRIER_NETWORK_CHANGE = { + { R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation }, + { R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation } + }; + + static final int[][] TELEPHONY_CARRIER_NETWORK_CHANGE_DARK = { + { R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation }, + { R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation, + R.drawable.stat_sys_signal_dark_carrier_network_change_animation } + }; + + static final int[][] QS_TELEPHONY_CARRIER_NETWORK_CHANGE = { + { R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation }, + { R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation, + R.drawable.ic_qs_signal_carrier_network_change_animation } + }; + static final int[] QS_DATA_R = { R.drawable.ic_qs_signal_r, R.drawable.ic_qs_signal_r @@ -202,11 +238,34 @@ class TelephonyIcons { static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g; static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g; static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; + static final int ICON_CARRIER_NETWORK_CHANGE = + R.drawable.stat_sys_signal_carrier_network_change_animation; + static final int ICON_CARRIER_NETWORK_CHANGE_DARK = + R.drawable.stat_sys_signal_dark_carrier_network_change_animation; static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte; static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g; static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g; static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x; + static final int QS_ICON_CARRIER_NETWORK_CHANGE = + R.drawable.ic_qs_signal_carrier_network_change_animation; + + static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( + "CARRIER_NETWORK_CHANGE", + TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE, + TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE_DARK, + TelephonyIcons.QS_TELEPHONY_CARRIER_NETWORK_CHANGE, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE, + TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE_DARK, + TelephonyIcons.QS_ICON_CARRIER_NETWORK_CHANGE, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_carrier_network_change_mode, + 0, + false, + null + ); static final MobileIconGroup THREE_G = new MobileIconGroup( "3G", 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 8e677f1..f2b971f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java @@ -17,9 +17,13 @@ package com.android.systemui.statusbar.stack; import android.view.View; + import com.android.systemui.statusbar.ActivatableNotificationView; +import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.policy.HeadsUpManager; import java.util.ArrayList; +import java.util.TreeSet; /** * A global state to track all input states for the algorithm. @@ -34,6 +38,12 @@ public class AmbientState { private int mSpeedBumpIndex = -1; private boolean mDark; private boolean mHideSensitive; + private HeadsUpManager mHeadsUpManager; + private float mStackTranslation; + private int mLayoutHeight; + private int mTopPadding; + private boolean mShadeExpanded; + private float mMaxHeadsUpTranslation; public int getScrollY() { return mScrollY; @@ -115,4 +125,67 @@ public class AmbientState { public void setSpeedBumpIndex(int speedBumpIndex) { mSpeedBumpIndex = speedBumpIndex; } + + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + } + + public TreeSet<HeadsUpManager.HeadsUpEntry> getSortedHeadsUpEntries() { + return mHeadsUpManager.getSortedEntries(); + } + + public float getStackTranslation() { + return mStackTranslation; + } + + public void setStackTranslation(float stackTranslation) { + mStackTranslation = stackTranslation; + } + + public int getLayoutHeight() { + return mLayoutHeight; + } + + public void setLayoutHeight(int layoutHeight) { + mLayoutHeight = layoutHeight; + } + + public float getTopPadding() { + return mTopPadding; + } + + public void setTopPadding(int topPadding) { + mTopPadding = topPadding; + } + + public int getInnerHeight() { + return mLayoutHeight - mTopPadding - getTopHeadsUpPushIn(); + } + + private int getTopHeadsUpPushIn() { + ExpandableNotificationRow topHeadsUpEntry = getTopHeadsUpEntry(); + return topHeadsUpEntry != null ? topHeadsUpEntry.getHeadsUpHeight() + - topHeadsUpEntry.getMinHeight(): 0; + } + + public boolean isShadeExpanded() { + return mShadeExpanded; + } + + public void setShadeExpanded(boolean shadeExpanded) { + mShadeExpanded = shadeExpanded; + } + + public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) { + mMaxHeadsUpTranslation = maxHeadsUpTranslation; + } + + public float getMaxHeadsUpTranslation() { + return mMaxHeadsUpTranslation; + } + + public ExpandableNotificationRow getTopHeadsUpEntry() { + HeadsUpManager.HeadsUpEntry topEntry = mHeadsUpManager.getTopEntry(); + return topEntry == null ? null : topEntry.entry.row; + } } 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 2eafd57..f247488 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -24,6 +24,7 @@ import android.graphics.Paint; import android.graphics.PointF; import android.util.AttributeSet; import android.util.Log; +import android.util.Pair; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -47,6 +48,8 @@ import com.android.systemui.statusbar.StackScrollerDecorView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.PhoneStatusBar; +import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ScrollAdapter; import java.util.ArrayList; @@ -121,15 +124,15 @@ public class NotificationStackScrollLayout extends ViewGroup private StackScrollState mCurrentStackScrollState = new StackScrollState(this); private AmbientState mAmbientState = new AmbientState(); private NotificationGroupManager mGroupManager; - private ArrayList<View> mChildrenToAddAnimated = new ArrayList<View>(); - private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<View>(); - private ArrayList<View> mSnappedBackChildren = new ArrayList<View>(); - private ArrayList<View> mDragAnimPendingChildren = new ArrayList<View>(); - private ArrayList<View> mChildrenChangingPositions = new ArrayList<View>(); + private ArrayList<View> mChildrenToAddAnimated = new ArrayList<>(); + private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>(); + private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<>(); + private ArrayList<View> mSnappedBackChildren = new ArrayList<>(); + private ArrayList<View> mDragAnimPendingChildren = new ArrayList<>(); + private ArrayList<View> mChildrenChangingPositions = new ArrayList<>(); private HashSet<View> mFromMoreCardAdditions = new HashSet<>(); - private ArrayList<AnimationEvent> mAnimationEvents - = new ArrayList<AnimationEvent>(); - private ArrayList<View> mSwipedOutViews = new ArrayList<View>(); + private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>(); + private ArrayList<View> mSwipedOutViews = new ArrayList<>(); private final StackStateAnimator mStateAnimator = new StackStateAnimator(this); private boolean mAnimationsEnabled; private boolean mChangePositionInProgress; @@ -143,7 +146,6 @@ public class NotificationStackScrollLayout extends ViewGroup * The raw amount of the overScroll on the bottom, which is not rubber-banded. */ private float mOverScrolledBottomPixels; - private OnChildLocationsChangedListener mListener; private OnOverscrollTopChangedListener mOverscrollTopChangedListener; private ExpandableView.OnHeightChangedListener mOnHeightChangedListener; @@ -171,7 +173,6 @@ public class NotificationStackScrollLayout extends ViewGroup * Was the scroller scrolled to the top when the down motion was observed? */ private boolean mScrolledToTopOnFirstDown; - /** * The minimal amount of over scroll which is needed in order to switch to the quick settings * when over scrolling on a expanded card. @@ -179,6 +180,7 @@ public class NotificationStackScrollLayout extends ViewGroup private float mMinTopOverScrollToEscape; private int mIntrinsicPadding; private int mNotificationTopPadding; + private float mStackTranslation; private float mTopPaddingOverflow; private boolean mDontReportNextOverScroll; private boolean mRequestViewResizeAnimationOnLayout; @@ -202,9 +204,9 @@ public class NotificationStackScrollLayout extends ViewGroup private ViewGroup mScrollView; private boolean mInterceptDelegateEnabled; private boolean mDelegateToScrollView; + private boolean mDisallowScrollingInThisMotion; private long mGoToFullShadeDelay; - private ViewTreeObserver.OnPreDrawListener mChildrenUpdater = new ViewTreeObserver.OnPreDrawListener() { @Override @@ -219,6 +221,12 @@ public class NotificationStackScrollLayout extends ViewGroup private int[] mTempInt2 = new int[2]; private boolean mGenerateChildOrderChangedEvent; private boolean mRemoveAnimationEnabled; + private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>(); + private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations + = new HashSet<>(); + private HeadsUpManager mHeadsUpManager; + private boolean mTrackingHeadsUp; + private ScrimController mScrimController; public NotificationStackScrollLayout(Context context) { this(context, null); @@ -404,8 +412,8 @@ public class NotificationStackScrollLayout extends ViewGroup } private void updateAlgorithmHeightAndPadding() { - mStackScrollAlgorithm.setLayoutHeight(getLayoutHeight()); - mStackScrollAlgorithm.setTopPadding(mTopPadding); + mAmbientState.setLayoutHeight(getLayoutHeight()); + mAmbientState.setTopPadding(mTopPadding); } /** @@ -478,9 +486,13 @@ public class NotificationStackScrollLayout extends ViewGroup int newStackHeight = (int) height; int minStackHeight = getMinStackHeight(); int stackHeight; - if (newStackHeight - mTopPadding - mTopPaddingOverflow >= minStackHeight + float paddingOffset; + boolean trackingHeadsUp = mTrackingHeadsUp; + int normalExpandPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight() + : minStackHeight; + if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalExpandPositionStart || getNotGoneChildCount() == 0) { - setTranslationY(mTopPaddingOverflow); + paddingOffset = mTopPaddingOverflow; stackHeight = newStackHeight; } else { @@ -492,9 +504,13 @@ public class NotificationStackScrollLayout extends ViewGroup float partiallyThere = (newStackHeight - mTopPadding - mTopPaddingOverflow) / minStackHeight; partiallyThere = Math.max(0, partiallyThere); - translationY += (1 - partiallyThere) * (mBottomStackPeekSize + - mCollapseSecondCardPadding); - setTranslationY(translationY - mTopPadding); + if (!trackingHeadsUp) { + translationY += (1 - partiallyThere) * (mBottomStackPeekSize + + mCollapseSecondCardPadding); + } else { + translationY = (int) (height - mHeadsUpManager.getTopHeadsUpHeight()); + } + paddingOffset = translationY - mTopPadding; stackHeight = (int) (height - (translationY - mTopPadding)); } if (stackHeight != mCurrentStackHeight) { @@ -502,6 +518,19 @@ public class NotificationStackScrollLayout extends ViewGroup updateAlgorithmHeightAndPadding(); requestChildrenUpdate(); } + setStackTranslation(paddingOffset); + } + + public float getStackTranslation() { + return mStackTranslation; + } + + private void setStackTranslation(float stackTranslation) { + if (stackTranslation != mStackTranslation) { + mStackTranslation = stackTranslation; + mAmbientState.setStackTranslation(stackTranslation); + requestChildrenUpdate(); + } } /** @@ -543,11 +572,6 @@ public class NotificationStackScrollLayout extends ViewGroup if (mDismissAllInProgress) { return; } - if (DEBUG) Log.v(TAG, "onChildDismissed: " + v); - final View veto = v.findViewById(R.id.veto); - if (veto != null && veto.getVisibility() != View.GONE) { - veto.performClick(); - } setSwipingInProgress(false); if (mDragAnimPendingChildren.contains(v)) { // We start the swipe and finish it in the same frame, we don't want any animation @@ -556,6 +580,17 @@ public class NotificationStackScrollLayout extends ViewGroup } mSwipedOutViews.add(v); mAmbientState.onDragFinished(v); + if (v instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) v; + if (row.isHeadsUp()) { + mHeadsUpManager.addSwipedOutKey(row.getStatusBarNotification().getKey()); + } + } + final View veto = v.findViewById(R.id.veto); + if (veto != null && veto.getVisibility() != View.GONE) { + veto.performClick(); + } + if (DEBUG) Log.v(TAG, "onChildDismissed: " + v); } @Override @@ -575,28 +610,48 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) { + if (isPinnedHeadsUp(animView) && canChildBeDismissed(animView)) { + mScrimController.setTopHeadsUpDragAmount(animView, + Math.min(Math.abs(swipeProgress - 1.0f), 1.0f)); + } return false; } - @Override - public float getFalsingThresholdFactor() { - return mPhoneStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f; - } - public void onBeginDrag(View v) { setSwipingInProgress(true); mAmbientState.onBeginDrag(v); - if (mAnimationsEnabled) { + if (mAnimationsEnabled && !isPinnedHeadsUp(v)) { mDragAnimPendingChildren.add(v); mNeedsAnimation = true; } requestChildrenUpdate(); } + public boolean isPinnedHeadsUp(View v) { + if (v instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) v; + return row.isHeadsUp() && !row.isInShade(); + } + return false; + } + + private boolean isHeadsUp(View v) { + if (v instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) v; + return row.isHeadsUp(); + } + return false; + } + public void onDragCancelled(View v) { setSwipingInProgress(false); } + @Override + public float getFalsingThresholdFactor() { + return mPhoneStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f; + } + public View getChildAtPosition(MotionEvent ev) { return getChildAtPosition(ev.getX(), ev.getY()); } @@ -657,6 +712,10 @@ public class NotificationStackScrollLayout extends ViewGroup if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) { if (slidingChild instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild; + if (row.isHeadsUp() && !row.isInShade() + && mHeadsUpManager.getTopEntry().entry.row != row) { + continue; + } return row.getViewAtPosition(touchY - childTop); } return slidingChild; @@ -667,7 +726,8 @@ public class NotificationStackScrollLayout extends ViewGroup public boolean canChildBeExpanded(View v) { return v instanceof ExpandableNotificationRow - && ((ExpandableNotificationRow) v).isExpandable(); + && ((ExpandableNotificationRow) v).isExpandable() + && !((ExpandableNotificationRow) v).isHeadsUp(); } public void setUserExpandedChild(View v, boolean userExpanded) { @@ -1343,12 +1403,9 @@ public class NotificationStackScrollLayout extends ViewGroup // add the padding before this element height += mPaddingBetweenElements; } - if (child instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) child; - height += row.getIntrinsicHeight(); - } else if (child instanceof ExpandableView) { + if (child instanceof ExpandableView) { ExpandableView expandableView = (ExpandableView) child; - height += expandableView.getActualHeight(); + height += expandableView.getIntrinsicHeight(); } } } @@ -1713,16 +1770,17 @@ public class NotificationStackScrollLayout extends ViewGroup } private void updateNotificationAnimationStates() { - boolean running = mIsExpanded && mAnimationsEnabled; + boolean running = mAnimationsEnabled; int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); + running &= mIsExpanded || isPinnedHeadsUp(child); updateAnimationState(running, child); } } private void updateAnimationState(View child) { - updateAnimationState(mAnimationsEnabled && mIsExpanded, child); + updateAnimationState((mAnimationsEnabled || isPinnedHeadsUp(child)) && mIsExpanded, child); } @@ -1752,6 +1810,10 @@ public class NotificationStackScrollLayout extends ViewGroup } mNeedsAnimation = true; } + if (isHeadsUp(child)) { + mAddedHeadsUpChildren.add(child); + mChildrenToAddAnimated.remove(child); + } } /** @@ -1790,6 +1852,7 @@ public class NotificationStackScrollLayout extends ViewGroup } private void generateChildHierarchyEvents() { + generateHeadsUpAnimationEvents(); generateChildRemovalEvents(); generateChildAdditionEvents(); generatePositionChangeEvents(); @@ -1807,6 +1870,40 @@ public class NotificationStackScrollLayout extends ViewGroup mNeedsAnimation = false; } + private void generateHeadsUpAnimationEvents() { + for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) { + ExpandableNotificationRow row = eventPair.first; + boolean isHeadsUp = eventPair.second; + int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER; + boolean onBottom = false; + if (!mIsExpanded && !isHeadsUp) { + type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR; + } else if (mAddedHeadsUpChildren.contains(row) || (!row.isInShade() && !mIsExpanded)) { + if (!row.isInShade() || shouldHunAppearFromBottom(row)) { + // Our custom add animation + type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR; + } else { + // Normal add animation + type = AnimationEvent.ANIMATION_TYPE_ADD; + } + onBottom = row.isInShade(); + } + AnimationEvent event = new AnimationEvent(row, type); + event.headsUpFromBottom = onBottom; + mAnimationEvents.add(event); + } + mHeadsUpChangeAnimations.clear(); + mAddedHeadsUpChildren.clear(); + } + + private boolean shouldHunAppearFromBottom(ExpandableNotificationRow row) { + StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row); + if (viewState.yTranslation + viewState.height < mAmbientState.getMaxHeadsUpTranslation()) { + return false; + } + return true; + } + private void generateGroupExpansionEvent() { // Generate a group expansion/collapsing event if there is such a group at all if (mExpandedGroupView != null) { @@ -2182,6 +2279,10 @@ public class NotificationStackScrollLayout extends ViewGroup public void onChildAnimationFinished() { requestChildrenUpdate(); + for (Runnable runnable : mAnimationFinishedRunnables) { + runnable.run(); + } + mAnimationFinishedRunnables.clear(); } /** @@ -2283,7 +2384,7 @@ public class NotificationStackScrollLayout extends ViewGroup * @return the y position of the first notification */ public float getNotificationsTopY() { - return mTopPadding + getTranslationY(); + return mTopPadding + getStackTranslation(); } @Override @@ -2470,7 +2571,7 @@ public class NotificationStackScrollLayout extends ViewGroup max = bottom; } } - return max + getTranslationY(); + return max + getStackTranslation(); } /** @@ -2579,6 +2680,50 @@ public class NotificationStackScrollLayout extends ViewGroup } } + public void performOnAnimationFinished(Runnable runnable) { + mAnimationFinishedRunnables.add(runnable); + } + + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + mAmbientState.setHeadsUpManager(headsUpManager); + mStackScrollAlgorithm.setHeadsUpManager(headsUpManager); + } + + public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) { + if (mAnimationsEnabled) { + mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp)); + mNeedsAnimation = true; + requestChildrenUpdate(); + } + } + + public void setShadeExpanded(boolean shadeExpanded) { + mAmbientState.setShadeExpanded(shadeExpanded); + mStateAnimator.setShadeExpanded(shadeExpanded); + } + + /** + * Set the boundary for the bottom heads up position. The heads up will always be above this + * position. + * + * @param height the height of the screen + * @param bottomBarHeight the height of the bar on the bottom + */ + public void setHeadsUpBoundaries(int height, int bottomBarHeight) { + mAmbientState.setMaxHeadsUpTranslation(height - bottomBarHeight); + mStateAnimator.setHeadsUpAppearHeightBottom(height); + requestChildrenUpdate(); + } + + public void setTrackingHeadsUp(boolean trackingHeadsUp) { + mTrackingHeadsUp = trackingHeadsUp; + } + + public void setScrimController(ScrimController scrimController) { + mScrimController = scrimController; + } + /** * A listener that is notified when some child locations might have changed. */ @@ -2723,6 +2868,30 @@ public class NotificationStackScrollLayout extends ViewGroup .animateY() .animateZ(), + // ANIMATION_TYPE_HEADS_UP_APPEAR + new AnimationFilter() + .animateAlpha() + .animateHeight() + .animateTopInset() + .animateY() + .animateZ(), + + // ANIMATION_TYPE_HEADS_UP_DISAPPEAR + new AnimationFilter() + .animateAlpha() + .animateHeight() + .animateTopInset() + .animateY() + .animateZ(), + + // ANIMATION_TYPE_HEADS_UP_OTHER + new AnimationFilter() + .animateAlpha() + .animateHeight() + .animateTopInset() + .animateY() + .animateZ(), + // ANIMATION_TYPE_EVERYTHING new AnimationFilter() .animateAlpha() @@ -2780,6 +2949,15 @@ public class NotificationStackScrollLayout extends ViewGroup // ANIMATION_TYPE_GROUP_EXPANSION_CHANGED StackStateAnimator.ANIMATION_DURATION_EXPAND_CLICKED, + // ANIMATION_TYPE_HEADS_UP_APPEAR + StackStateAnimator.ANIMATION_DURATION_HEADS_UP_APPEAR, + + // ANIMATION_TYPE_HEADS_UP_DISAPPEAR + StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR, + + // ANIMATION_TYPE_HEADS_UP_OTHER + StackStateAnimator.ANIMATION_DURATION_STANDARD, + // ANIMATION_TYPE_EVERYTHING StackStateAnimator.ANIMATION_DURATION_STANDARD, }; @@ -2798,7 +2976,10 @@ public class NotificationStackScrollLayout extends ViewGroup static final int ANIMATION_TYPE_HIDE_SENSITIVE = 11; static final int ANIMATION_TYPE_VIEW_RESIZE = 12; static final int ANIMATION_TYPE_GROUP_EXPANSION_CHANGED = 13; - static final int ANIMATION_TYPE_EVERYTHING = 14; + static final int ANIMATION_TYPE_HEADS_UP_APPEAR = 14; + static final int ANIMATION_TYPE_HEADS_UP_DISAPPEAR = 15; + static final int ANIMATION_TYPE_HEADS_UP_OTHER = 16; + static final int ANIMATION_TYPE_EVERYTHING = 17; static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1; static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2; @@ -2810,6 +2991,7 @@ public class NotificationStackScrollLayout extends ViewGroup final long length; View viewAfterChangingView; int darkAnimationOriginIndex; + boolean headsUpFromBottom; AnimationEvent(View view, int type) { this(view, type, LENGTHS[type]); 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 e7bf47b..d98bcfe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java @@ -25,9 +25,11 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; +import com.android.systemui.statusbar.policy.HeadsUpManager; import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; /** * The Algorithm of the {@link com.android.systemui.statusbar.stack @@ -54,11 +56,6 @@ public class StackScrollAlgorithm { private StackIndentationFunctor mTopStackIndentationFunctor; private StackIndentationFunctor mBottomStackIndentationFunctor; - private int mLayoutHeight; - - /** mLayoutHeight - mTopPadding */ - private int mInnerHeight; - private int mTopPadding; private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState(); private boolean mIsExpansionChanging; private int mFirstChildMaxHeight; @@ -74,6 +71,7 @@ public class StackScrollAlgorithm { private boolean mIsSmallScreen; private int mMaxNotificationHeight; private boolean mScaleDimmed; + private HeadsUpManager mHeadsUpManager; public StackScrollAlgorithm(Context context) { initConstants(context); @@ -157,20 +155,20 @@ public class StackScrollAlgorithm { scrollY = Math.max(0, scrollY); algorithmState.scrollY = (int) (scrollY + mCollapsedSize + bottomOverScroll); - updateVisibleChildren(resultState, algorithmState); + updateVisibleChildren(resultState, algorithmState, ambientState); // Phase 1: - findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState); + findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState, ambientState); // Phase 2: - updatePositionsForState(resultState, algorithmState); + updatePositionsForState(resultState, algorithmState, ambientState); // Phase 3: updateZValuesForState(resultState, algorithmState); handleDraggedViews(ambientState, resultState, algorithmState); updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState); - updateClipping(resultState, algorithmState); + updateClipping(resultState, algorithmState, ambientState); updateSpeedBumpState(resultState, algorithmState, ambientState.getSpeedBumpIndex()); getNotificationChildrenStates(resultState, algorithmState); } @@ -201,7 +199,7 @@ public class StackScrollAlgorithm { } private void updateClipping(StackScrollState resultState, - StackScrollAlgorithmState algorithmState) { + StackScrollAlgorithmState algorithmState, AmbientState ambientState) { float previousNotificationEnd = 0; float previousNotificationStart = 0; boolean previousNotificationIsSwiped = false; @@ -242,7 +240,7 @@ public class StackScrollAlgorithm { // otherwise we would clip to a transparent view. previousNotificationStart = newYTranslation + state.clipTopAmount * state.scale; previousNotificationEnd = newNotificationEnd; - previousNotificationIsSwiped = child.getTranslationX() != 0; + previousNotificationIsSwiped = ambientState.getDraggedViews().contains(child); } } } @@ -314,7 +312,9 @@ public class StackScrollAlgorithm { StackViewState viewState = resultState.getViewStateForView( nextChild); // The child below the dragged one must be fully visible - viewState.alpha = 1; + if (!isPinnedHeadsUpView(draggedView) || isPinnedHeadsUpView(nextChild)) { + viewState.alpha = 1; + } } // Lets set the alpha to the one it currently has, as its currently being dragged @@ -325,27 +325,41 @@ public class StackScrollAlgorithm { } } + private boolean isPinnedHeadsUpView(View view) { + if (view instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) view; + return row.isHeadsUp() && !row.isInShade(); + } + return false; + } + /** * Update the visible children on the state. */ private void updateVisibleChildren(StackScrollState resultState, - StackScrollAlgorithmState state) { + StackScrollAlgorithmState state, AmbientState ambientState) { ViewGroup hostView = resultState.getHostView(); int childCount = hostView.getChildCount(); state.visibleChildren.clear(); state.visibleChildren.ensureCapacity(childCount); int notGoneIndex = 0; + TreeSet<HeadsUpManager.HeadsUpEntry> headsUpEntries + = ambientState.getSortedHeadsUpEntries(); + for (HeadsUpManager.HeadsUpEntry entry: headsUpEntries) { + ExpandableView v = entry.entry.row; + notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v); + } for (int i = 0; i < childCount; i++) { ExpandableView v = (ExpandableView) hostView.getChildAt(i); if (v.getVisibility() != View.GONE) { - StackViewState viewState = resultState.getViewStateForView(v); - viewState.notGoneIndex = notGoneIndex; - state.visibleChildren.add(v); - notGoneIndex++; - - // handle the notgoneIndex for the children as well if (v instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) v; + if (row.isHeadsUp()) { + continue; + } + notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v); + + // handle the notgoneIndex for the children as well List<ExpandableNotificationRow> children = row.getNotificationChildren(); if (row.areChildrenExpanded() && children != null) { @@ -358,22 +372,35 @@ public class StackScrollAlgorithm { } } } + } else { + notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v); } } } } + private int updateNotGoneIndex(StackScrollState resultState, + StackScrollAlgorithmState state, int notGoneIndex, + ExpandableView v) { + StackViewState viewState = resultState.getViewStateForView(v); + viewState.notGoneIndex = notGoneIndex; + state.visibleChildren.add(v); + notGoneIndex++; + return notGoneIndex; + } + /** * Determine the positions for the views. This is the main part of the algorithm. * - * @param resultState The result state to update if a change to the properties of a child occurs + * @param resultState The result state to update if a change to the properties of a child occurs * @param algorithmState The state in which the current pass of the algorithm is currently in + * @param ambientState The current ambient state */ private void updatePositionsForState(StackScrollState resultState, - StackScrollAlgorithmState algorithmState) { + StackScrollAlgorithmState algorithmState, AmbientState ambientState) { // The starting position of the bottom stack peek - float bottomPeekStart = mInnerHeight - mBottomStackPeekSize; + float bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize; // The position where the bottom stack starts. float bottomStackStart = bottomPeekStart - mBottomStackSlowDownLength; @@ -384,13 +411,17 @@ public class StackScrollAlgorithm { // How far in is the element currently transitioning into the bottom stack. float yPositionInScrollView = 0.0f; + // If we have a heads-up higher than the collapsed height we need to add the difference to + // the padding of all other elements, i.e push in the top stack slightly. + ExpandableNotificationRow topHeadsUpEntry = ambientState.getTopHeadsUpEntry(); + int childCount = algorithmState.visibleChildren.size(); int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack; for (int i = 0; i < childCount; i++) { ExpandableView child = algorithmState.visibleChildren.get(i); StackViewState childViewState = resultState.getViewStateForView(child); childViewState.location = StackViewState.LOCATION_UNKNOWN; - int childHeight = getMaxAllowedChildHeight(child); + int childHeight = getMaxAllowedChildHeight(child, ambientState); float yPositionInScrollViewAfterElement = yPositionInScrollView + childHeight + mPaddingBetweenElements; @@ -427,7 +458,8 @@ public class StackScrollAlgorithm { bottomPeekStart, childViewState.yTranslation, childViewState, childHeight); } - clampPositionToBottomStackStart(childViewState, childViewState.height); + clampPositionToBottomStackStart(childViewState, childViewState.height, + ambientState); } else if (nextYPosition >= bottomStackStart) { // Case 2: // We are in the bottom stack. @@ -435,7 +467,7 @@ public class StackScrollAlgorithm { // According to the regular scroll view we are fully translated out of the // bottom of the screen so we are fully in the bottom stack updateStateForChildFullyInBottomStack(algorithmState, - bottomStackStart, childViewState, childHeight); + bottomStackStart, childViewState, childHeight, ambientState); } else { // According to the regular scroll view we are currently translating out of / // into the bottom of the screen @@ -447,7 +479,7 @@ public class StackScrollAlgorithm { // Case 3: // We are in the regular scroll area. childViewState.location = StackViewState.LOCATION_MAIN_AREA; - clampYTranslation(childViewState, childHeight); + clampYTranslation(childViewState, childHeight, ambientState); } // The first card is always rendered. @@ -468,7 +500,44 @@ public class StackScrollAlgorithm { currentYPosition = childViewState.yTranslation + childHeight + mPaddingBetweenElements; yPositionInScrollView = yPositionInScrollViewAfterElement; - childViewState.yTranslation += mTopPadding; + if (ambientState.isShadeExpanded() && topHeadsUpEntry != null + && child != topHeadsUpEntry) { + childViewState.yTranslation += topHeadsUpEntry.getHeadsUpHeight() - mCollapsedSize; + } + childViewState.yTranslation += ambientState.getTopPadding() + + ambientState.getStackTranslation(); + } + updateHeadsUpStates(resultState, ambientState); + } + + private void updateHeadsUpStates(StackScrollState resultState, AmbientState ambientState) { + TreeSet<HeadsUpManager.HeadsUpEntry> headsUpEntries = ambientState.getSortedHeadsUpEntries(); + for (HeadsUpManager.HeadsUpEntry entry: headsUpEntries) { + ExpandableNotificationRow row = entry.entry.row; + StackViewState childState = resultState.getViewStateForView(row); + ExpandableNotificationRow topHeadsUpEntry = ambientState.getTopHeadsUpEntry(); + boolean isTopEntry = topHeadsUpEntry == row; + if (!row.isInShade()) { + childState.yTranslation = 0; + childState.height = row.getHeadsUpHeight(); + if (!isTopEntry) { + // Ensure that a headsUp is never below the topmost headsUp + StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry); + childState.height = row.getHeadsUpHeight(); + childState.yTranslation = topState.yTranslation + topState.height + - childState.height; + } + } else if (mIsExpanded) { + if (isTopEntry) { + childState.height += row.getHeadsUpHeight() - mCollapsedSize; + } + childState.height = Math.max(childState.height, row.getHeadsUpHeight()); + // Ensure that the heads up is always visible even when scrolled of from the bottom + float bottomPosition = ambientState.getMaxHeadsUpTranslation() - childState.height; + childState.yTranslation = Math.min(childState.yTranslation, + bottomPosition); + } + } } @@ -478,8 +547,9 @@ public class StackScrollAlgorithm { * @param childViewState the view state of the child * @param childHeight the height of this child */ - private void clampYTranslation(StackViewState childViewState, int childHeight) { - clampPositionToBottomStackStart(childViewState, childHeight); + private void clampYTranslation(StackViewState childViewState, int childHeight, + AmbientState ambientState) { + clampPositionToBottomStackStart(childViewState, childHeight, ambientState); clampPositionToTopStackEnd(childViewState, childHeight); } @@ -491,14 +561,15 @@ public class StackScrollAlgorithm { * @param childHeight the height of this child */ private void clampPositionToBottomStackStart(StackViewState childViewState, - int childHeight) { + int childHeight, AmbientState ambientState) { childViewState.yTranslation = Math.min(childViewState.yTranslation, - mInnerHeight - mBottomStackPeekSize - mCollapseSecondCardPadding - childHeight); + ambientState.getInnerHeight() - mBottomStackPeekSize - mCollapseSecondCardPadding + - childHeight); } /** * Clamp the yTranslation of the child up such that its end is at lest on the end of the top - * stack.get + * stack. * * @param childViewState the view state of the child * @param childHeight the height of this child @@ -509,9 +580,14 @@ public class StackScrollAlgorithm { mCollapsedSize - childHeight); } - private int getMaxAllowedChildHeight(View child) { + private int getMaxAllowedChildHeight(View child, AmbientState ambientState) { if (child instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; + if (ambientState == null && row.isHeadsUp() + || ambientState != null && ambientState.getTopHeadsUpEntry() == child) { + int extraSize = row.getIntrinsicHeight() - row.getHeadsUpHeight(); + return mCollapsedSize + extraSize; + } return row.getIntrinsicHeight(); } else if (child instanceof ExpandableView) { ExpandableView expandableView = (ExpandableView) child; @@ -548,8 +624,7 @@ public class StackScrollAlgorithm { private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState, float transitioningPositionStart, StackViewState childViewState, - int childHeight) { - + int childHeight, AmbientState ambientState) { float currentYPosition; algorithmState.itemsInBottomStack += 1.0f; if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) { @@ -567,7 +642,7 @@ public class StackScrollAlgorithm { childViewState.alpha = 1.0f - algorithmState.partialInBottom; } childViewState.location = StackViewState.LOCATION_BOTTOM_STACK_HIDDEN; - currentYPosition = mInnerHeight; + currentYPosition = ambientState.getInnerHeight(); } childViewState.yTranslation = currentYPosition - childHeight; clampPositionToTopStackEnd(childViewState, childHeight); @@ -629,7 +704,7 @@ public class StackScrollAlgorithm { * @param algorithmState The state in which the current pass of the algorithm is currently in */ private void findNumberOfItemsInTopStackAndUpdateState(StackScrollState resultState, - StackScrollAlgorithmState algorithmState) { + StackScrollAlgorithmState algorithmState, AmbientState ambientState) { // The y Position if the element would be in a regular scrollView float yPositionInScrollView = 0.0f; @@ -639,7 +714,7 @@ public class StackScrollAlgorithm { for (int i = 0; i < childCount; i++) { ExpandableView child = algorithmState.visibleChildren.get(i); StackViewState childViewState = resultState.getViewStateForView(child); - int childHeight = getMaxAllowedChildHeight(child); + int childHeight = getMaxAllowedChildHeight(child, ambientState); float yPositionInScrollViewAfterElement = yPositionInScrollView + childHeight + mPaddingBetweenElements; @@ -647,7 +722,7 @@ public class StackScrollAlgorithm { if (i == 0 && algorithmState.scrollY <= mCollapsedSize) { // The starting position of the bottom stack peek - int bottomPeekStart = mInnerHeight - mBottomStackPeekSize - + int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize - mCollapseSecondCardPadding; // Collapse and expand the first child while the shade is being expanded float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding @@ -744,21 +819,6 @@ public class StackScrollAlgorithm { } } - public void setLayoutHeight(int layoutHeight) { - this.mLayoutHeight = layoutHeight; - updateInnerHeight(); - } - - public void setTopPadding(int topPadding) { - mTopPadding = topPadding; - updateInnerHeight(); - } - - private void updateInnerHeight() { - mInnerHeight = mLayoutHeight - mTopPadding; - } - - /** * Update whether the device is very small, i.e. Notifications can be in both the top and the * bottom stack at the same time @@ -788,6 +848,13 @@ public class StackScrollAlgorithm { // current height or the end value of the animation. mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight( mFirstChildWhileExpanding); + if (mFirstChildWhileExpanding instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = + (ExpandableNotificationRow) mFirstChildWhileExpanding; + if (row.isHeadsUp()) { + mFirstChildMaxHeight += mCollapsedSize - row.getHeadsUpHeight(); + } + } } else { updateFirstChildMaxSizeToMaxHeight(); } @@ -809,7 +876,7 @@ public class StackScrollAlgorithm { int oldBottom) { if (mFirstChildWhileExpanding != null) { mFirstChildMaxHeight = getMaxAllowedChildHeight( - mFirstChildWhileExpanding); + mFirstChildWhileExpanding, null); } else { mFirstChildMaxHeight = 0; } @@ -817,7 +884,7 @@ public class StackScrollAlgorithm { } }); } else { - mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding); + mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding, null); } } @@ -830,6 +897,9 @@ public class StackScrollAlgorithm { } private View findFirstVisibleChild(ViewGroup container) { + if (mHeadsUpManager != null && mHeadsUpManager.getTopEntry() != null) { + return mHeadsUpManager.getTopEntry().entry.row; + } int childCount = container.getChildCount(); for (int i = 0; i < childCount; i++) { View child = container.getChildAt(i); @@ -870,6 +940,10 @@ public class StackScrollAlgorithm { } } + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + } + class StackScrollAlgorithmState { /** 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 b249fbf..f5d94c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -21,9 +21,11 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; +import android.graphics.Path; import android.view.View; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableNotificationRow; @@ -32,7 +34,6 @@ import com.android.systemui.statusbar.SpeedBumpView; import java.util.ArrayList; import java.util.HashSet; -import java.util.Set; import java.util.Stack; /** @@ -45,6 +46,8 @@ public class StackStateAnimator { public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464; public static final int ANIMATION_DURATION_EXPAND_CLICKED = 360; public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220; + public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 650; + public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 230; public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80; public static final int ANIMATION_DELAY_PER_ELEMENT_EXPAND_CHILDREN = 54; public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32; @@ -73,12 +76,15 @@ public class StackStateAnimator { private static final int TAG_START_TOP_INSET = R.id.top_inset_animator_start_value_tag; private final Interpolator mFastOutSlowInInterpolator; + private final Interpolator mHeadsUpAppearInterpolator; private final int mGoToFullShadeAppearingTranslation; public NotificationStackScrollLayout mHostLayout; private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents = new ArrayList<>(); private ArrayList<View> mNewAddChildren = new ArrayList<>(); - private Set<Animator> mAnimatorSet = new HashSet<>(); + private HashSet<View> mHeadsUpAppearChildren = new HashSet<>(); + private HashSet<View> mHeadsUpDisappearChildren = new HashSet<>(); + private HashSet<Animator> mAnimatorSet = new HashSet<>(); private Stack<AnimatorListenerAdapter> mAnimationListenerPool = new Stack<>(); private AnimationFilter mAnimationFilter = new AnimationFilter(); private long mCurrentLength; @@ -86,10 +92,12 @@ public class StackStateAnimator { /** The current index for the last child which was not added in this event set. */ private int mCurrentLastNotAddedIndex; - private ValueAnimator mTopOverScrollAnimator; private ValueAnimator mBottomOverScrollAnimator; private ExpandableNotificationRow mChildExpandingView; + private StackViewState mTmpState = new StackViewState(); + private int mHeadsUpAppearHeightBottom; + private boolean mShadeExpanded; public StackStateAnimator(NotificationStackScrollLayout hostLayout) { mHostLayout = hostLayout; @@ -98,6 +106,25 @@ public class StackStateAnimator { mGoToFullShadeAppearingTranslation = hostLayout.getContext().getResources().getDimensionPixelSize( R.dimen.go_to_full_shade_appearing_translation); + Path path = new Path(); + path.moveTo(0, 0); + float x1 = 250f; + float x2 = 150f; + float x3 = 100f; + float y1 = 90f; + float y2 = 78f; + float y3 = 80f; + float xTot = (x1 + x2 + x3); + path.cubicTo(x1 * 0.9f / xTot, 0f, + x1 * 0.8f / xTot, y1 / y3, + x1 / xTot , y1 / y3); + path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3, + (x1 + x2 * 0.2f) / xTot, y2 / y3, + (x1 + x2) / xTot, y2 / y3); + path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3, + (x1 + x2 + x3 * 0.2f) / xTot, 1f, + 1f, 1f); + mHeadsUpAppearInterpolator = new PathInterpolator(path); } public boolean isRunning() { @@ -119,7 +146,8 @@ public class StackStateAnimator { final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i); StackViewState viewState = finalState.getViewStateForView(child); - if (viewState == null || child.getVisibility() == View.GONE) { + if (viewState == null || child.getVisibility() == View.GONE + || applyWithoutAnimation(child, viewState, finalState)) { continue; } @@ -130,11 +158,39 @@ public class StackStateAnimator { // no child has preformed any animation, lets finish onAnimationFinished(); } + mHeadsUpAppearChildren.clear(); + mHeadsUpDisappearChildren.clear(); mNewEvents.clear(); mNewAddChildren.clear(); mChildExpandingView = null; } + /** + * Determines if a view should not perform an animation and applies it directly. + * + * @return true if no animation should be performed + */ + private boolean applyWithoutAnimation(ExpandableView child, StackViewState viewState, + StackScrollState finalState) { + if (mShadeExpanded) { + return false; + } + if (getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null) { + // A Y translation animation is running + return false; + } + if (mHeadsUpDisappearChildren.contains(child) || mHeadsUpAppearChildren.contains(child)) { + // This is a heads up animation + return false; + } + if (mHostLayout.isPinnedHeadsUp(child)) { + // This is another headsUp which might move. Let's animate! + return false; + } + finalState.applyState(child, viewState); + return true; + } + private int findLastNotAddedIndex(StackScrollState finalState) { int childCount = mHostLayout.getChildCount(); for (int i = childCount - 1; i >= 0; i--) { @@ -616,7 +672,9 @@ public class StackStateAnimator { ObjectAnimator animator = ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, child.getTranslationY(), newEndValue); - animator.setInterpolator(mFastOutSlowInInterpolator); + Interpolator interpolator = mHeadsUpAppearChildren.contains(child) ? + mHeadsUpAppearInterpolator :mFastOutSlowInInterpolator; + animator.setInterpolator(interpolator); long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator); animator.setDuration(newDuration); if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) { @@ -731,7 +789,7 @@ public class StackStateAnimator { }; } - private static <T> T getChildTag(View child, int tag) { + public static <T> T getChildTag(View child, int tag) { return (T) child.getTag(tag); } @@ -828,6 +886,22 @@ public class StackStateAnimator { ExpandableNotificationRow row = (ExpandableNotificationRow) event.changingView; row.prepareExpansionChanged(finalState); mChildExpandingView = row; + } else if (event.animationType == NotificationStackScrollLayout + .AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) { + // This item is added, initialize it's properties. + StackViewState viewState = finalState.getViewStateForView(changingView); + mTmpState.copyFrom(viewState); + if (event.headsUpFromBottom) { + mTmpState.yTranslation = mHeadsUpAppearHeightBottom; + } else { + mTmpState.yTranslation = -mTmpState.height; + } + mHeadsUpAppearChildren.add(changingView); + finalState.applyState(changingView, mTmpState); + } else if (event.animationType == NotificationStackScrollLayout + .AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) { + // This item is added, initialize it's properties. + mHeadsUpDisappearChildren.add(changingView); } mNewEvents.add(event); } @@ -893,4 +967,12 @@ public class StackStateAnimator { return getChildTag(view, TAG_END_HEIGHT); } } + + public void setHeadsUpAppearHeightBottom(int headsUpAppearHeightBottom) { + mHeadsUpAppearHeightBottom = headsUpAppearHeightBottom; + } + + public void setShadeExpanded(boolean shadeExpanded) { + mShadeExpanded = shadeExpanded; + } } 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 c272e48..78122d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -123,19 +123,7 @@ public class TvStatusBar extends BaseStatusBar { } @Override - public void scheduleHeadsUpDecay(long delay) { - } - - @Override - public void scheduleHeadsUpOpen() { - } - - @Override - public void scheduleHeadsUpEscalation() { - } - - @Override - public void scheduleHeadsUpClose() { + public void escalateHeadsUp() { } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpNotificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpNotificationTest.java deleted file mode 100644 index e8a80d9..0000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpNotificationTest.java +++ /dev/null @@ -1,261 +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.policy; - -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; - -import android.app.Notification; -import android.os.*; -import android.service.notification.StatusBarNotification; -import com.android.systemui.SwipeHelper; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.ExpandableNotificationRow; -import com.android.systemui.statusbar.NotificationData; -import com.android.systemui.statusbar.phone.PhoneStatusBar; - -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -/** - * Test the Heads Up Notification. - * - * Specifically the policy that a notificaiton must remain visibile for a minimum period of time. - */ -public class HeadsUpNotificationTest extends SysuiTestCase { - private static final String TAG = "HeadsUpNotificationTest"; - - private static int TOUCH_SENSITIVITY = 100; - private static int NOTIFICATION_DECAY = 10000; - private static int MINIMUM_DISPLAY_TIME = 3000; - private static int SNOOZE_TIME = 60000; - private static long TOO_SOON = 1000L; // less than MINIMUM_DISPLAY_TIME - private static long LATER = 5000L; // more than MINIMUM_DISPLAY_TIME - private static long REMAINING_VISIBILITY = MINIMUM_DISPLAY_TIME - TOO_SOON; - - protected HeadsUpNotificationView mHeadsUp; - - @Mock protected PhoneStatusBar mMockStatusBar; - @Mock private HeadsUpNotificationView.Clock mClock; - @Mock private SwipeHelper mMockSwipeHelper; - @Mock private HeadsUpNotificationView.EdgeSwipeHelper mMockEdgeSwipeHelper; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - MockitoAnnotations.initMocks(this); - - mHeadsUp = new HeadsUpNotificationView(mContext, - mClock, mMockSwipeHelper, mMockEdgeSwipeHelper, - NOTIFICATION_DECAY, MINIMUM_DISPLAY_TIME, TOUCH_SENSITIVITY, SNOOZE_TIME); - mHeadsUp.setBar(mMockStatusBar); - } - - private NotificationData.Entry makeNotification(String key) { - StatusBarNotification sbn = mock(StatusBarNotification.class); - when(sbn.getKey()).thenReturn(key); - return new NotificationData.Entry(sbn, null); - } - - public void testPostAndDecay() { - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpOpen(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar).scheduleHeadsUpDecay(decayArg.capture()); - // New notification gets a full decay time. - assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue()); - } - - public void testPostAndDeleteTooSoon() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - mHeadsUp.removeNotification(a.key); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar).scheduleHeadsUpDecay(decayArg.capture()); - // Leave the window up for the balance of the minumum time. - assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue()); - } - - public void testPostAndDeleteLater() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(LATER); - mHeadsUp.removeNotification(a.key); - // Delete closes immediately if the minimum time window is satisfied. - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt()); - } - - // This is a bad test. It should not care that there is a call to scheduleHeadsUpClose(), - // but it happens that there will be one, so it is important that it happen before the - // call to scheduleHeadsUpOpen(), so that the final state is open. - // Maybe mMockStatusBar should instead be a fake that tracks the open/closed state. - public void testPostAndReplaceTooSoon() { - InOrder callOrder = inOrder(mMockStatusBar); - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - NotificationData.Entry b = makeNotification("b"); - mHeadsUp.showNotification(b); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture()); - // New notification gets a full decay time. - assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue()); - - // Make sure close was called before open, so that the heads up stays open. - callOrder.verify(mMockStatusBar).scheduleHeadsUpClose(); - callOrder.verify(mMockStatusBar).scheduleHeadsUpOpen(); - } - - public void testPostAndUpdateAlertAgain() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - mHeadsUp.updateNotification(a, true); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture()); - // Alert again gets a full decay time. - assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue()); - } - - public void testPostAndUpdateAlertAgainFastFail() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - NotificationData.Entry a_prime = makeNotification("a"); - mHeadsUp.updateNotification(a_prime, true); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture()); - // Alert again gets a full decay time. - assertEquals(NOTIFICATION_DECAY, (long) decayArg.getValue()); - } - - public void testPostAndUpdateNoAlertAgain() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - mHeadsUp.updateNotification(a, false); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt()); - } - - public void testPostAndUpdateNoAlertAgainFastFail() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - NotificationData.Entry a_prime = makeNotification("a"); - mHeadsUp.updateNotification(a_prime, false); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt()); - } - - public void testPostAndUpdateLowPriorityTooSoon() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - mHeadsUp.release(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture()); - // Down grade on update leaves the window up for the balance of the minumum time. - assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue()); - } - - public void testPostAndUpdateLowPriorityTooSoonFastFail() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(TOO_SOON); - NotificationData.Entry a_prime = makeNotification("a"); - mHeadsUp.updateNotification(a_prime, false); - mHeadsUp.release(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpClose(); - ArgumentCaptor<Long> decayArg = ArgumentCaptor.forClass(Long.class); - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpDecay(decayArg.capture()); - // Down grade on update leaves the window up for the balance of the minumum time. - assertEquals(REMAINING_VISIBILITY, (long) decayArg.getValue()); - } - - public void testPostAndUpdateLowPriorityLater() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(LATER); - mHeadsUp.release(); - // Down grade on update closes immediately if the minimum time window is satisfied. - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt()); - } - - public void testPostAndUpdateLowPriorityLaterFastFail() { - when(mClock.currentTimeMillis()).thenReturn(0L); - NotificationData.Entry a = makeNotification("a"); - mHeadsUp.showNotification(a); - reset(mMockStatusBar); - - when(mClock.currentTimeMillis()).thenReturn(LATER); - NotificationData.Entry a_prime = makeNotification("a"); - mHeadsUp.updateNotification(a_prime, false); - mHeadsUp.release(); - // Down grade on update closes immediately if the minimum time window is satisfied. - Mockito.verify(mMockStatusBar, times(1)).scheduleHeadsUpClose(); - Mockito.verify(mMockStatusBar, never()).scheduleHeadsUpDecay(anyInt()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 5d88407..5d40eed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -279,7 +279,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { // TODO: Verify all fields. Mockito.verify(mSignalCluster, Mockito.atLeastOnce()).setMobileDataIndicators( - visibleArg.capture(), iconArg.capture(), typeIconArg.capture(), + visibleArg.capture(), iconArg.capture(), iconArg.capture(), typeIconArg.capture(), ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(Boolean.class).capture(), |