Merge "Updated launcher text shadow values." into sc-dev
diff --git a/Android.mk b/Android.mk
index 54a80b7..c222f24 100644
--- a/Android.mk
+++ b/Android.mk
@@ -47,6 +47,9 @@
LOCAL_MANIFEST_FILE := go/AndroidManifest.xml
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
include $(BUILD_PACKAGE)
#
@@ -116,6 +119,9 @@
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
include $(BUILD_PACKAGE)
@@ -164,6 +170,9 @@
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
include $(BUILD_PACKAGE)
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 4e72260..87a08af 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -94,12 +94,6 @@
</receiver>
<service
- android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
- android:exported="false"
- android:process=":wallpaper_chooser"
- android:permission="android.permission.BIND_JOB_SERVICE" />
-
- <service
android:name="com.android.launcher3.notification.NotificationListener"
android:label="@string/notification_dots_service_title"
android:exported="true"
diff --git a/OWNERS b/OWNERS
index daad057..05fa502 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,6 +4,9 @@
# People who can approve changes for submission
#
+alexchau@google.com
+andraskloczl@google.com
+patmanning@google.com
petrcermak@google.com
pbdr@google.com
kideckel@google.com
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index fe81b4c..fb47b0a 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -125,6 +125,22 @@
// Folder's label is empty(i.e., title == "").
// Not eligible for auto-labeling.
EMPTY_LABEL = 12;
+
+ ALL_APPS_SEARCH_RESULT_APPLICATION = 13;
+ ALL_APPS_SEARCH_RESULT_SHORTCUT = 14;
+ ALL_APPS_SEARCH_RESULT_PEOPLE = 15;
+ ALL_APPS_SEARCH_RESULT_ACTION = 16;
+ ALL_APPS_SEARCH_RESULT_SETTING = 17;
+ ALL_APPS_SEARCH_RESULT_SCREENSHOT = 18;
+ ALL_APPS_SEARCH_RESULT_SLICE = 19;
+ ALL_APPS_SEARCH_RESULT_WIDGETS = 20;
+ ALL_APPS_SEARCH_RESULT_PLAY = 21;
+ ALL_APPS_SEARCH_RESULT_SUGGEST = 22;
+ ALL_APPS_SEARCH_RESULT_ASSISTANT = 23;
+ ALL_APPS_SEARCH_RESULT_CHROMETAB = 24;
+ ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25;
+ ALL_APPS_SEARCH_RESULT_TIPS = 26;
+ ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27;
}
// Main app icons
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 5e5cf73..842abc3 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -97,9 +97,6 @@
android:resource="@xml/overview_file_provider_paths"/>
</provider>
- <service android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
- tools:node="remove"/>
-
<activity android:name="com.android.launcher3.proxy.ProxyActivityStarter"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
diff --git a/quickstep/res/drawable/bg_sandbox_close_button.xml b/quickstep/res/drawable/bg_sandbox_close_button.xml
new file mode 100644
index 0000000..2811071
--- /dev/null
+++ b/quickstep/res/drawable/bg_sandbox_close_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="#303030"/>
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/bg_sandbox_feedback.xml b/quickstep/res/drawable/bg_sandbox_feedback.xml
index 1b3265d..83a3dea 100644
--- a/quickstep/res/drawable/bg_sandbox_feedback.xml
+++ b/quickstep/res/drawable/bg_sandbox_feedback.xml
@@ -1,10 +1,20 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="394dp"
- android:height="172dp"
- android:viewportWidth="394"
- android:viewportHeight="172">
- <path
- android:pathData="M20,0L374,0A20,20 0,0 1,394 20L394,152A20,20 0,0 1,374 172L20,172A20,20 0,0 1,0 152L0,20A20,20 0,0 1,20 0z"
- android:fillColor="?android:attr/colorBackgroundFloating"
- android:fillAlpha="0.9"/>
-</vector>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="28dp"/>
+ <solid android:color="?android:attr/colorBackgroundFloating"/>
+</shape>
diff --git a/quickstep/res/drawable/close_icon.xml b/quickstep/res/drawable/close_icon.xml
new file mode 100644
index 0000000..07f4336
--- /dev/null
+++ b/quickstep/res/drawable/close_icon.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="#909090"
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
+</vector>
diff --git a/quickstep/res/drawable/gesture_tutorial_action_button_background.xml b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
index 3f3b288..6fc2b76 100644
--- a/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
+++ b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <corners android:radius="@dimen/default_dialog_corner_radius"/>
+ <corners android:radius="50dp"/>
<solid android:color="@color/gesture_tutorial_primary_color"/>
</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_back_left.xml b/quickstep/res/drawable/gesture_tutorial_back_left.xml
new file mode 100644
index 0000000..92ae202
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_back_left.xml
@@ -0,0 +1,559 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="892dp" android:width="412dp" android:viewportHeight="892" android:viewportWidth="412">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_7_G" android:translateX="206" android:translateY="446">
+ <path android:name="_R_G_L_7_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_6_G" android:pivotX="206" android:pivotY="446" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_6_G_L_3_G" android:translateX="206" android:translateY="446" android:scaleX="1.2" android:scaleY="1.2">
+ <path android:name="_R_G_L_6_G_L_3_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G">
+ <group android:name="_R_G_L_6_G_L_2_G_L_11_G" android:translateX="206" android:translateY="496.5">
+ <path android:name="_R_G_L_6_G_L_2_G_L_11_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M235.5 -452.14 C235.5,-452.14 235.5,452.14 235.5,452.14 C235.5,452.14 -235.5,452.14 -235.5,452.14 C-235.5,452.14 -235.5,-452.14 -235.5,-452.14 C-235.5,-452.14 235.5,-452.14 235.5,-452.14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_10_G" android:translateX="182.5" android:translateY="831">
+ <path android:name="_R_G_L_6_G_L_2_G_L_10_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_9_G" android:translateX="186" android:translateY="801">
+ <path android:name="_R_G_L_6_G_L_2_G_L_9_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -7 C162,-7 162,7 162,7 C162,9.21 160.21,11 158,11 C158,11 -158,11 -158,11 C-160.21,11 -162,9.21 -162,7 C-162,7 -162,-7 -162,-7 C-162,-9.21 -160.21,-11 -158,-11 C-158,-11 158,-11 158,-11 C160.21,-11 162,-9.21 162,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_8_G" android:translateX="119" android:translateY="755">
+ <path android:name="_R_G_L_6_G_L_2_G_L_8_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M95 -7 C95,-7 95,7 95,7 C95,9.21 93.21,11 91,11 C91,11 -91,11 -91,11 C-93.21,11 -95,9.21 -95,7 C-95,7 -95,-7 -95,-7 C-95,-9.21 -93.21,-11 -91,-11 C-91,-11 91,-11 91,-11 C93.21,-11 95,-9.21 95,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_7_G" android:translateX="182.5" android:translateY="725">
+ <path android:name="_R_G_L_6_G_L_2_G_L_7_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_6_G" android:translateX="197.5" android:translateY="695">
+ <path android:name="_R_G_L_6_G_L_2_G_L_6_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M173.5 -7 C173.5,-7 173.5,7 173.5,7 C173.5,9.21 171.71,11 169.5,11 C169.5,11 -169.5,11 -169.5,11 C-171.71,11 -173.5,9.21 -173.5,7 C-173.5,7 -173.5,-7 -173.5,-7 C-173.5,-9.21 -171.71,-11 -169.5,-11 C-169.5,-11 169.5,-11 169.5,-11 C171.71,-11 173.5,-9.21 173.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_5_G" android:translateX="192" android:translateY="665">
+ <path android:name="_R_G_L_6_G_L_2_G_L_5_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M168 -7 C168,-7 168,7 168,7 C168,9.21 166.21,11 164,11 C164,11 -164,11 -164,11 C-166.21,11 -168,9.21 -168,7 C-168,7 -168,-7 -168,-7 C-168,-9.21 -166.21,-11 -164,-11 C-164,-11 164,-11 164,-11 C166.21,-11 168,-9.21 168,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_4_G" android:translateX="105.5" android:translateY="360">
+ <path android:name="_R_G_L_6_G_L_2_G_L_4_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_3_G" android:translateX="47.5" android:translateY="360">
+ <path android:name="_R_G_L_6_G_L_2_G_L_3_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_2_G" android:translateX="142.5" android:translateY="328">
+ <path android:name="_R_G_L_6_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M118.5 -14 C118.5,-14 118.5,14 118.5,14 C118.5,16.21 116.71,18 114.5,18 C114.5,18 -114.5,18 -114.5,18 C-116.71,18 -118.5,16.21 -118.5,14 C-118.5,14 -118.5,-14 -118.5,-14 C-118.5,-16.21 -116.71,-18 -114.5,-18 C-114.5,-18 114.5,-18 114.5,-18 C116.71,-18 118.5,-16.21 118.5,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_1_G" android:translateX="186" android:translateY="284">
+ <path android:name="_R_G_L_6_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -14 C162,-14 162,14 162,14 C162,16.21 160.21,18 158,18 C158,18 -158,18 -158,18 C-160.21,18 -162,16.21 -162,14 C-162,14 -162,-14 -162,-14 C-162,-16.21 -160.21,-18 -158,-18 C-158,-18 158,-18 158,-18 C160.21,-18 162,-16.21 162,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_0_G" android:translateX="155" android:translateY="240">
+ <path android:name="_R_G_L_6_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M131 -14 C131,-14 131,14 131,14 C131,16.21 129.21,18 127,18 C127,18 -127,18 -127,18 C-129.21,18 -131,16.21 -131,14 C-131,14 -131,-14 -131,-14 C-131,-16.21 -129.21,-18 -127,-18 C-127,-18 127,-18 127,-18 C129.21,-18 131,-16.21 131,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G" android:translateX="24" android:translateY="390">
+ <group android:name="_R_G_L_6_G_L_1_G_L_7_G" android:translateX="182" android:translateY="120"/>
+ <group android:name="_R_G_L_6_G_L_1_G_L_6_G" android:translateX="182" android:translateY="120">
+ <path android:name="_R_G_L_6_G_L_1_G_L_6_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M182 -116 C182,-116 182,116 182,116 C182,118.21 180.21,120 178,120 C178,120 -178,120 -178,120 C-180.21,120 -182,118.21 -182,116 C-182,116 -182,-116 -182,-116 C-182,-118.21 -180.21,-120 -178,-120 C-178,-120 178,-120 178,-120 C180.21,-120 182,-118.21 182,-116c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_5_G" android:translateX="77.322" android:translateY="150.552">
+ <path android:name="_R_G_L_6_G_L_1_G_L_5_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_5_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_4_G" android:translateX="38.772" android:translateY="121.73">
+ <path android:name="_R_G_L_6_G_L_1_G_L_4_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_4_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_3_G" android:translateX="183" android:translateY="222">
+ <path android:name="_R_G_L_6_G_L_1_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_3_G_D_1_P_0" android:strokeColor="#9aa0a6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_2_G" android:translateX="265.619" android:translateY="162.331">
+ <path android:name="_R_G_L_6_G_L_1_G_L_2_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_2_G_D_1_P_0" android:strokeColor="#a8cbfe" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_1_G" android:translateX="319.271" android:translateY="37.945">
+ <path android:name="_R_G_L_6_G_L_1_G_L_1_G_D_0_P_0" android:fillColor="#feefc3" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.42 2.99 C14.95,-4.17 9.93,-11.31 2.21,-12.96 C-0.9,-13.62 -3.97,-13.3 -6.64,-12.2 C-6.58,-12.19 -6.53,-12.18 -6.48,-12.17 C-1.03,-11.01 2.52,-5.97 1.44,-0.92 C0.36,4.13 -4.94,7.28 -10.4,6.12 C-11.6,5.86 -12.7,5.42 -13.69,4.83 C-11.9,8.78 -8.15,11.93 -3.34,12.96 C4.38,14.61 11.88,10.14 13.42,2.99c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_0_G" android:translateX="179.5" android:translateY="73.351">
+ <path android:name="_R_G_L_6_G_L_1_G_L_0_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M51.08 -40.95 C51.08,-40.95 50.55,-42.54 50.55,-42.54 C50.55,-42.54 49.67,-41.13 49.67,-41.13 C49.67,-41.13 48.17,-41.21 48.17,-41.21 C48.17,-41.21 49.05,-39.8 49.05,-39.8 C49.05,-39.8 48.61,-38.22 48.61,-38.22 C48.61,-38.22 50.02,-38.74 50.02,-38.74 C50.02,-38.74 51.35,-37.69 51.35,-37.69 C51.35,-37.69 51.26,-39.45 51.26,-39.45 C51.26,-39.45 52.59,-40.42 52.59,-40.42 C52.59,-40.42 51.08,-40.95 51.08,-40.95c M8.78 30.58 C8.78,30.58 8.25,28.99 8.25,28.99 C8.25,28.99 7.37,30.4 7.37,30.4 C7.37,30.4 5.87,30.31 5.87,30.31 C5.87,30.31 6.75,31.72 6.75,31.72 C6.75,31.72 6.31,33.31 6.31,33.31 C6.31,33.31 7.72,32.78 7.72,32.78 C7.72,32.78 9.05,33.84 9.05,33.84 C9.05,33.84 8.96,32.08 8.96,32.08 C8.96,32.08 10.29,31.11 10.29,31.11 C10.29,31.11 8.78,30.58 8.78,30.58c M19.38 -61.67 C19.38,-61.67 18.94,-63.35 18.94,-63.35 C18.94,-63.35 17.97,-61.94 17.97,-61.94 C17.97,-61.94 16.47,-61.94 16.47,-61.94 C16.47,-61.94 17.35,-60.62 17.35,-60.62 C17.35,-60.62 16.91,-58.94 16.91,-58.94 C16.91,-58.94 18.41,-59.56 18.41,-59.56 C18.41,-59.56 19.65,-58.5 19.65,-58.5 C19.65,-58.5 19.56,-60.18 19.56,-60.18 C19.56,-60.18 20.88,-61.23 20.88,-61.23 C20.88,-61.23 19.38,-61.67 19.38,-61.67c M-32.98 35.08 C-32.98,35.08 -33.51,33.4 -33.51,33.4 C-33.51,33.4 -34.4,34.81 -34.4,34.81 C-34.4,34.81 -35.9,34.81 -35.9,34.81 C-35.9,34.81 -35.01,36.22 -35.01,36.22 C-35.01,36.22 -35.45,37.81 -35.45,37.81 C-35.45,37.81 -34.04,37.28 -34.04,37.28 C-34.04,37.28 -32.72,38.25 -32.72,38.25 C-32.72,38.25 -32.81,36.58 -32.81,36.58 C-32.81,36.58 -31.48,35.6 -31.48,35.6 C-31.48,35.6 -32.98,35.08 -32.98,35.08c M45.34 7.56 C45.34,7.56 44.81,5.97 44.81,5.97 C44.81,5.97 43.93,7.38 43.93,7.38 C43.93,7.38 42.34,7.3 42.34,7.3 C42.34,7.3 43.31,8.71 43.31,8.71 C43.31,8.71 42.87,10.29 42.87,10.29 C42.87,10.29 44.28,9.77 44.28,9.77 C44.28,9.77 45.52,10.82 45.52,10.82 C45.52,10.82 45.52,9.06 45.52,9.06 C45.52,9.06 46.76,8.09 46.76,8.09 C46.76,8.09 45.34,7.56 45.34,7.56c M-9.59 -41.67 C-9.59,-41.67 -10.12,-43.35 -10.12,-43.35 C-10.12,-43.35 -11,-41.94 -11,-41.94 C-11,-41.94 -12.5,-41.94 -12.5,-41.94 C-12.5,-41.94 -11.62,-40.62 -11.62,-40.62 C-11.62,-40.62 -12.06,-38.94 -12.06,-38.94 C-12.06,-38.94 -10.65,-39.56 -10.65,-39.56 C-10.65,-39.56 -9.32,-38.5 -9.32,-38.5 C-9.32,-38.5 -9.41,-40.26 -9.41,-40.26 C-9.41,-40.26 -8.09,-41.23 -8.09,-41.23 C-8.09,-41.23 -9.59,-41.67 -9.59,-41.67c M97.74 -23.97 C97.74,-23.97 97.03,-26.35 97.03,-26.35 C97.03,-26.35 95.8,-24.32 95.8,-24.32 C95.8,-24.32 93.5,-24.32 93.5,-24.32 C93.5,-24.32 94.91,-22.38 94.91,-22.38 C94.91,-22.38 94.21,-20 94.21,-20 C94.21,-20 96.33,-20.88 96.33,-20.88 C96.33,-20.88 98.09,-19.38 98.09,-19.38 C98.09,-19.38 98.09,-21.85 98.09,-21.85 C98.09,-21.85 99.86,-23.26 99.86,-23.26 C99.86,-23.26 97.74,-23.97 97.74,-23.97c M167.29 43.28 C167.29,43.28 166.67,40.9 166.67,40.9 C166.67,40.9 165.35,42.93 165.35,42.93 C165.35,42.93 163.14,42.93 163.14,42.93 C163.14,42.93 164.47,44.87 164.47,44.87 C164.47,44.87 163.76,47.25 163.76,47.25 C163.76,47.25 165.88,46.37 165.88,46.37 C165.88,46.37 167.73,47.87 167.73,47.87 C167.73,47.87 167.65,45.4 167.65,45.4 C167.65,45.4 169.5,43.98 169.5,43.98 C169.5,43.98 167.29,43.28 167.29,43.28c M-1.1 -1.79 C-1.1,-1.79 -1.72,-4.08 -1.72,-4.08 C-1.72,-4.08 -3.05,-2.14 -3.05,-2.14 C-3.05,-2.14 -5.25,-2.14 -5.25,-2.14 C-5.25,-2.14 -3.93,-0.11 -3.93,-0.11 C-3.93,-0.11 -4.64,2.18 -4.64,2.18 C-4.64,2.18 -2.52,1.38 -2.52,1.38 C-2.52,1.38 -0.66,2.8 -0.66,2.8 C-0.66,2.8 -0.75,0.41 -0.75,0.41 C-0.75,0.41 1.1,-1.08 1.1,-1.08 C1.1,-1.08 -1.1,-1.79 -1.1,-1.79c M-60.89 -5.23 C-60.89,-5.23 -61.59,-7.61 -61.59,-7.61 C-61.59,-7.61 -62.83,-5.58 -62.83,-5.58 C-62.83,-5.58 -65.13,-5.58 -65.13,-5.58 C-65.13,-5.58 -63.71,-3.64 -63.71,-3.64 C-63.71,-3.64 -64.42,-1.26 -64.42,-1.26 C-64.42,-1.26 -62.39,-2.14 -62.39,-2.14 C-62.39,-2.14 -60.53,-0.64 -60.53,-0.64 C-60.53,-0.64 -60.62,-3.11 -60.62,-3.11 C-60.62,-3.11 -58.77,-4.52 -58.77,-4.52 C-58.77,-4.52 -60.89,-5.23 -60.89,-5.23c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-51.26 -42.98 C-51.26,-42.98 -54.09,-45.01 -54.09,-45.01 C-54.09,-45.01 -53.91,-41.57 -53.91,-41.57 C-53.91,-41.57 -56.65,-39.54 -56.65,-39.54 C-56.65,-39.54 -53.38,-38.57 -53.38,-38.57 C-53.38,-38.57 -52.32,-35.3 -52.32,-35.3 C-52.32,-35.3 -50.38,-38.13 -50.38,-38.13 C-50.38,-38.13 -46.94,-38.22 -46.94,-38.22 C-46.94,-38.22 -49.05,-40.86 -49.05,-40.86 C-49.05,-40.86 -47.99,-44.21 -47.99,-44.21 C-47.99,-44.21 -51.26,-42.98 -51.26,-42.98c M-92.06 -47.92 C-92.06,-47.92 -92.59,-49.59 -92.59,-49.59 C-92.59,-49.59 -93.47,-48.18 -93.47,-48.18 C-93.47,-48.18 -95.06,-48.18 -95.06,-48.18 C-95.06,-48.18 -94.09,-46.86 -94.09,-46.86 C-94.09,-46.86 -94.53,-45.18 -94.53,-45.18 C-94.53,-45.18 -93.12,-45.8 -93.12,-45.8 C-93.12,-45.8 -91.88,-44.74 -91.88,-44.74 C-91.88,-44.74 -91.88,-46.42 -91.88,-46.42 C-91.88,-46.42 -90.65,-47.47 -90.65,-47.47 C-90.65,-47.47 -92.06,-47.92 -92.06,-47.92c M62.83 -13.34 C62.83,-13.34 62.39,-14.93 62.39,-14.93 C62.39,-14.93 61.5,-13.52 61.5,-13.52 C61.5,-13.52 59.91,-13.52 59.91,-13.52 C59.91,-13.52 60.89,-12.2 60.89,-12.2 C60.89,-12.2 60.36,-10.52 60.36,-10.52 C60.36,-10.52 61.86,-11.14 61.86,-11.14 C61.86,-11.14 63.09,-10.08 63.09,-10.08 C63.09,-10.08 63.09,-11.84 63.09,-11.84 C63.09,-11.84 64.33,-12.81 64.33,-12.81 C64.33,-12.81 62.83,-13.34 62.83,-13.34c M-155.99 -40.95 C-155.99,-40.95 -156.43,-42.54 -156.43,-42.54 C-156.43,-42.54 -157.32,-41.13 -157.32,-41.13 C-157.32,-41.13 -158.91,-41.21 -158.91,-41.21 C-158.91,-41.21 -157.93,-39.8 -157.93,-39.8 C-157.93,-39.8 -158.46,-38.22 -158.46,-38.22 C-158.46,-38.22 -156.96,-38.74 -156.96,-38.74 C-156.96,-38.74 -155.73,-37.69 -155.73,-37.69 C-155.73,-37.69 -155.73,-39.45 -155.73,-39.45 C-155.73,-39.45 -154.49,-40.42 -154.49,-40.42 C-154.49,-40.42 -155.99,-40.95 -155.99,-40.95c M141.24 26.52 C141.24,26.52 140.71,24.85 140.71,24.85 C140.71,24.85 139.83,26.26 139.83,26.26 C139.83,26.26 138.33,26.26 138.33,26.26 C138.33,26.26 139.21,27.67 139.21,27.67 C139.21,27.67 138.77,29.26 138.77,29.26 C138.77,29.26 140.18,28.73 140.18,28.73 C140.18,28.73 141.51,29.7 141.51,29.7 C141.51,29.7 141.42,28.02 141.42,28.02 C141.42,28.02 142.74,27.05 142.74,27.05 C142.74,27.05 141.24,26.52 141.24,26.52c M111.4 -51.27 C111.4,-51.27 110.95,-52.94 110.95,-52.94 C110.95,-52.94 110.07,-51.53 110.07,-51.53 C110.07,-51.53 108.48,-51.53 108.48,-51.53 C108.48,-51.53 109.45,-50.21 109.45,-50.21 C109.45,-50.21 108.92,-48.53 108.92,-48.53 C108.92,-48.53 110.42,-49.15 110.42,-49.15 C110.42,-49.15 111.66,-48.09 111.66,-48.09 C111.66,-48.09 111.66,-49.86 111.66,-49.86 C111.66,-49.86 112.9,-50.83 112.9,-50.83 C112.9,-50.83 111.4,-51.27 111.4,-51.27c M-66.59 53.33 C-66.59,53.33 -67.03,51.65 -67.03,51.65 C-67.03,51.65 -67.91,53.06 -67.91,53.06 C-67.91,53.06 -69.5,53.06 -69.5,53.06 C-69.5,53.06 -68.53,54.47 -68.53,54.47 C-68.53,54.47 -69.06,56.06 -69.06,56.06 C-69.06,56.06 -67.56,55.53 -67.56,55.53 C-67.56,55.53 -66.32,56.5 -66.32,56.5 C-66.32,56.5 -66.32,54.82 -66.32,54.82 C-66.32,54.82 -65.08,53.77 -65.08,53.77 C-65.08,53.77 -66.59,53.33 -66.59,53.33c M-50.59 59.33 C-50.59,59.33 -51.12,57.65 -51.12,57.65 C-51.12,57.65 -52,59.06 -52,59.06 C-52,59.06 -53.5,59.06 -53.5,59.06 C-53.5,59.06 -52.62,60.38 -52.62,60.38 C-52.62,60.38 -53.06,62.06 -53.06,62.06 C-53.06,62.06 -51.65,61.53 -51.65,61.53 C-51.65,61.53 -50.32,62.5 -50.32,62.5 C-50.32,62.5 -50.41,60.82 -50.41,60.82 C-50.41,60.82 -49.08,59.77 -49.08,59.77 C-49.08,59.77 -50.59,59.33 -50.59,59.33c M29.98 -16.08 C29.98,-16.08 29.27,-18.46 29.27,-18.46 C29.27,-18.46 27.95,-16.43 27.95,-16.43 C27.95,-16.43 25.74,-16.43 25.74,-16.43 C25.74,-16.43 27.06,-14.49 27.06,-14.49 C27.06,-14.49 26.36,-12.11 26.36,-12.11 C26.36,-12.11 28.48,-12.9 28.48,-12.9 C28.48,-12.9 30.33,-11.49 30.33,-11.49 C30.33,-11.49 30.24,-13.96 30.24,-13.96 C30.24,-13.96 32.1,-15.37 32.1,-15.37 C32.1,-15.37 29.98,-16.08 29.98,-16.08c M81.28 55.98 C81.28,55.98 80.58,53.6 80.58,53.6 C80.58,53.6 79.25,55.63 79.25,55.63 C79.25,55.63 77.04,55.63 77.04,55.63 C77.04,55.63 78.37,57.57 78.37,57.57 C78.37,57.57 77.66,59.95 77.66,59.95 C77.66,59.95 79.78,59.07 79.78,59.07 C79.78,59.07 81.64,60.56 81.64,60.56 C81.64,60.56 81.55,58.1 81.55,58.1 C81.55,58.1 83.4,56.68 83.4,56.68 C83.4,56.68 81.28,55.98 81.28,55.98c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-74.05 21.76 C-74.05,21.76 -74.66,19.47 -74.66,19.47 C-74.66,19.47 -75.99,21.49 -75.99,21.49 C-75.99,21.49 -78.2,21.41 -78.2,21.41 C-78.2,21.41 -76.87,23.43 -76.87,23.43 C-76.87,23.43 -77.58,25.73 -77.58,25.73 C-77.58,25.73 -75.46,24.93 -75.46,24.93 C-75.46,24.93 -73.6,26.43 -73.6,26.43 C-73.6,26.43 -73.69,23.96 -73.69,23.96 C-73.69,23.96 -71.84,22.46 -71.84,22.46 C-71.84,22.46 -74.05,21.76 -74.05,21.76c M8.98 55.68 C8.98,55.68 6.15,53.65 6.15,53.65 C6.15,53.65 6.24,57.09 6.24,57.09 C6.24,57.09 3.5,59.12 3.5,59.12 C3.5,59.12 6.86,60.09 6.86,60.09 C6.86,60.09 7.92,63.35 7.92,63.35 C7.92,63.35 9.86,60.44 9.86,60.44 C9.86,60.44 13.3,60.44 13.3,60.44 C13.3,60.44 11.18,57.71 11.18,57.71 C11.18,57.71 12.15,54.44 12.15,54.44 C12.15,54.44 8.98,55.68 8.98,55.68c M124.89 -2.41 C124.89,-2.41 122.06,-4.35 122.06,-4.35 C122.06,-4.35 122.24,-0.91 122.24,-0.91 C122.24,-0.91 119.5,1.12 119.5,1.12 C119.5,1.12 122.77,2 122.77,2 C122.77,2 123.83,5.26 123.83,5.26 C123.83,5.26 125.77,2.44 125.77,2.44 C125.77,2.44 129.21,2.44 129.21,2.44 C129.21,2.44 127.09,-0.29 127.09,-0.29 C127.09,-0.29 128.15,-3.56 128.15,-3.56 C128.15,-3.56 124.89,-2.41 124.89,-2.41c M77.31 19.91 C77.31,19.91 74.57,17.88 74.57,17.88 C74.57,17.88 74.66,21.32 74.66,21.32 C74.66,21.32 71.92,23.35 71.92,23.35 C71.92,23.35 75.19,24.32 75.19,24.32 C75.19,24.32 76.34,27.58 76.34,27.58 C76.34,27.58 78.19,24.67 78.19,24.67 C78.19,24.67 81.64,24.67 81.64,24.67 C81.64,24.67 79.52,21.94 79.52,21.94 C79.52,21.94 80.58,18.67 80.58,18.67 C80.58,18.67 77.31,19.91 77.31,19.91c M-28.11 7.68 C-28.11,7.68 -30.94,5.65 -30.94,5.65 C-30.94,5.65 -30.76,9.09 -30.76,9.09 C-30.76,9.09 -33.5,11.12 -33.5,11.12 C-33.5,11.12 -30.23,12.09 -30.23,12.09 C-30.23,12.09 -29.17,15.35 -29.17,15.35 C-29.17,15.35 -27.23,12.44 -27.23,12.44 C-27.23,12.44 -23.79,12.44 -23.79,12.44 C-23.79,12.44 -25.91,9.71 -25.91,9.71 C-25.91,9.71 -24.85,6.44 -24.85,6.44 C-24.85,6.44 -28.11,7.68 -28.11,7.68c M-119.43 -20.22 C-119.43,-20.22 -122.26,-22.16 -122.26,-22.16 C-122.26,-22.16 -122.08,-18.72 -122.08,-18.72 C-122.08,-18.72 -124.82,-16.7 -124.82,-16.7 C-124.82,-16.7 -121.55,-15.81 -121.55,-15.81 C-121.55,-15.81 -120.49,-12.55 -120.49,-12.55 C-120.49,-12.55 -118.55,-15.37 -118.55,-15.37 C-118.55,-15.37 -115.11,-15.37 -115.11,-15.37 C-115.11,-15.37 -117.23,-18.11 -117.23,-18.11 C-117.23,-18.11 -116.17,-21.37 -116.17,-21.37 C-116.17,-21.37 -119.43,-20.22 -119.43,-20.22c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G">
+ <group android:name="_R_G_L_6_G_L_0_G_L_2_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#e8eaed" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M230.57 -95.63 C230.57,-95.63 230.57,42.37 230.57,42.37 C230.57,43.47 229.56,44.37 228.33,44.37 C228.33,44.37 -228.33,44.37 -228.33,44.37 C-229.56,44.37 -230.57,43.47 -230.57,42.37 C-230.57,42.37 -230.57,-95.63 -230.57,-95.63 C-230.57,-96.73 -229.56,-97.63 -228.33,-97.63 C-228.33,-97.63 228.33,-97.63 228.33,-97.63 C229.56,-97.63 230.57,-96.73 230.57,-95.63c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G_L_1_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M109 -14 C109,-14 109,14 109,14 C109,15.1 108.1,16 107,16 C107,16 -107,16 -107,16 C-108.1,16 -109,15.1 -109,14 C-109,14 -109,-14 -109,-14 C-109,-15.1 -108.1,-16 -107,-16 C-107,-16 107,-16 107,-16 C108.1,-16 109,-15.1 109,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G_L_0_G" android:translateX="46" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M22 -14 C22,-14 22,14 22,14 C22,18.42 18.42,22 14,22 C14,22 -14,22 -14,22 C-18.42,22 -22,18.42 -22,14 C-22,14 -22,-14 -22,-14 C-22,-18.42 -18.42,-22 -14,-22 C-14,-22 14,-22 14,-22 C18.42,-22 22,-18.42 22,-14c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_5_G" android:scaleY="0">
+ <group android:name="_R_G_L_5_G_L_11_G" android:translateX="206" android:translateY="446" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_11_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_10_G" android:translateX="148" android:translateY="441" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_10_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M48 -8 C48,-8 48,8 48,8 C48,10.21 46.21,12 44,12 C44,12 -44,12 -44,12 C-46.21,12 -48,10.21 -48,8 C-48,8 -48,-8 -48,-8 C-48,-10.21 -46.21,-12 -44,-12 C-44,-12 44,-12 44,-12 C46.21,-12 48,-10.21 48,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_9_G" android:translateX="264" android:translateY="441" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_9_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M48 -8 C48,-8 48,8 48,8 C48,10.21 46.21,12 44,12 C44,12 -44,12 -44,12 C-46.21,12 -48,10.21 -48,8 C-48,8 -48,-8 -48,-8 C-48,-10.21 -46.21,-12 -44,-12 C-44,-12 44,-12 44,-12 C46.21,-12 48,-10.21 48,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_8_G" android:translateX="206" android:translateY="380" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_8_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M176 0 C176,0 176,0 176,0 C176,14.9 163.9,27 149,27 C149,27 -149,27 -149,27 C-163.9,27 -176,14.9 -176,0 C-176,0 -176,0 -176,0 C-176,-14.9 -163.9,-27 -149,-27 C-149,-27 149,-27 149,-27 C163.9,-27 176,-14.9 176,0c "/>
+ <path android:name="_R_G_L_5_G_L_8_G_D_1_P_0" android:strokeColor="#bdc1c6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M176 0 C176,0 176,0 176,0 C176,14.9 163.9,27 149,27 C149,27 -149,27 -149,27 C-163.9,27 -176,14.9 -176,0 C-176,0 -176,0 -176,0 C-176,-14.9 -163.9,-27 -149,-27 C-149,-27 149,-27 149,-27 C163.9,-27 176,-14.9 176,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_7_G" android:translateX="120" android:translateY="268" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_7_G_D_0_P_0" android:fillColor="#4285f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M26 0 C26,0 26,0 26,0 C26,14.35 14.35,26 0,26 C0,26 0,26 0,26 C-14.35,26 -26,14.35 -26,0 C-26,0 -26,0 -26,0 C-26,-14.35 -14.35,-26 0,-26 C0,-26 0,-26 0,-26 C14.35,-26 26,-14.35 26,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_6_G" android:translateX="167" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_6_G_D_0_P_0" android:fillColor="#e94235" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_5_G" android:translateX="205" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_5_G_D_0_P_0" android:fillColor="#fabb05" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_4_G" android:translateX="243" android:translateY="286" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_4_G_D_0_P_0" android:fillColor="#4285f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 -8 C17,-8 17,8 17,8 C17,17.38 9.38,25 0,25 C0,25 0,25 0,25 C-9.38,25 -17,17.38 -17,8 C-17,8 -17,-8 -17,-8 C-17,-17.38 -9.38,-25 0,-25 C0,-25 0,-25 0,-25 C9.38,-25 17,-17.38 17,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_3_G" android:translateX="272" android:translateY="269" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_3_G_D_0_P_0" android:fillColor="#34a853" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8 -17 C8,-17 8,17 8,17 C8,21.42 4.42,25 0,25 C0,25 0,25 0,25 C-4.42,25 -8,21.42 -8,17 C-8,17 -8,-17 -8,-17 C-8,-21.42 -4.42,-25 0,-25 C0,-25 0,-25 0,-25 C4.42,-25 8,-21.42 8,-17c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_2_G" android:translateX="301" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_2_G_D_0_P_0" android:fillColor="#e94235" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_1_G" android:translateX="42" android:translateY="140" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M12 -8 C12,-8 12,8 12,8 C12,10.21 10.21,12 8,12 C8,12 -8,12 -8,12 C-10.21,12 -12,10.21 -12,8 C-12,8 -12,-8 -12,-8 C-12,-10.21 -10.21,-12 -8,-12 C-8,-12 8,-12 8,-12 C10.21,-12 12,-10.21 12,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_0_G" android:translateX="92.5" android:translateY="140" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M28.5 -5 C28.5,-5 28.5,5 28.5,5 C28.5,7.21 26.71,9 24.5,9 C24.5,9 -24.5,9 -24.5,9 C-26.71,9 -28.5,7.21 -28.5,5 C-28.5,5 -28.5,-5 -28.5,-5 C-28.5,-7.21 -26.71,-9 -24.5,-9 C-24.5,-9 24.5,-9 24.5,-9 C26.71,-9 28.5,-7.21 28.5,-5c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_4_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_3_G">
+ <group android:name="_R_G_L_3_G_L_1_G" android:translateX="206" android:translateY="50.5">
+ <path android:name="_R_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -50.5 C206,-50.5 206,50.5 206,50.5 C206,50.5 -206,50.5 -206,50.5 C-206,50.5 -206,-50.5 -206,-50.5 C-206,-50.5 206,-50.5 206,-50.5c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_0_G" android:translateX="206" android:translateY="66.5">
+ <path android:name="_R_G_L_3_G_L_0_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M190 0 C190,0 190,0 190,0 C190,10.21 181.71,18.5 171.5,18.5 C171.5,18.5 -171.5,18.5 -171.5,18.5 C-181.71,18.5 -190,10.21 -190,0 C-190,0 -190,0 -190,0 C-190,-10.21 -181.71,-18.5 -171.5,-18.5 C-171.5,-18.5 171.5,-18.5 171.5,-18.5 C181.71,-18.5 190,-10.21 190,0c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_2_G" android:translateX="28.25" android:translateY="462.5" android:scaleY="0">
+ <group android:name="_R_G_L_2_G_D_0_P_0_G_0_T_0" android:translateX="-60" android:translateY="0">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M28.25 0 C28.25,31.2 2.95,56.5 -28.25,56.5 C-28.25,56.5 -28.25,-56.5 -28.25,-56.5 C2.95,-56.5 28.25,-31.2 28.25,0c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G" android:translateX="-4.25" android:translateY="463" android:scaleX="0.5" android:scaleY="0" android:rotation="180">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M3.87 -13.45 C3.07,-14.21 1.8,-14.18 1.04,-13.38 C0.28,-12.58 0.31,-11.31 1.11,-10.55 C1.11,-10.55 9.75,-2.32 9.75,-2.32 C9.75,-2.32 -14.75,-2.32 -14.75,-2.32 C-15.85,-2.32 -16.75,-1.43 -16.75,-0.32 C-16.75,0.78 -15.85,1.68 -14.75,1.68 C-14.75,1.68 9.94,1.68 9.94,1.68 C9.94,1.68 1.07,10.59 1.07,10.59 C0.29,11.37 0.29,12.64 1.08,13.42 C1.86,14.2 3.13,14.19 3.9,13.41 C3.9,13.41 16.17,1.09 16.17,1.09 C16.55,0.71 16.76,0.19 16.75,-0.35 C16.74,-0.89 16.52,-1.4 16.13,-1.77 C16.13,-1.77 3.87,-13.45 3.87,-13.45c "/>
+ </group>
+ <group android:name="_R_G_L_0_G" android:translateX="-130.003" android:translateY="399" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_2_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M-166 64 C-130.65,64 -102,35.35 -102,0 C-102,-35.34 -130.65,-64 -166,-64 C-201.34,-64 -230,-35.34 -230,0 C-230,35.35 -201.34,64 -166,64c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_1_G" android:translateX="192" android:translateY="63.997" android:rotation="90" android:scaleX="-1" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_0_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0" android:translateX="-166" android:translateY="0">
+ <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 64 C35.35,64 64,35.35 64,0 C64,-35.34 35.35,-64 0,-64 C-35.34,-64 -64,-35.34 -64,0 C-64,35.35 -35.34,64 0,64c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_6_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2283" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2283" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="2133" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="2133" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.88012" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.88012" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2417" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_11_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_10_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2433" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_9_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2433" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_8_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_7_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1133" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -60,0C -50,0 -70,0 -60,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="667" android:startOffset="1133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -60,0C -50,0 -10,0 0,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="1800" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,0C 0,0 0,0 0,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0.333 0,0 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="2133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 0,0C -10,0 -50,0 -60,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2467" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1133" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -4.25,463C 0.75,463 -9.25,463 -4.25,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="583" android:startOffset="1133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -4.25,463C 0.75,463 20.75,463 25.75,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="417" android:startOffset="1717" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 25.75,463C 25.75,463 25.75,463 25.75,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0.333 0.667,0.667 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="2133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 25.75,463C 25.75,463 -4.25,463 -4.25,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="1300" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="1300" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="1300" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="1300" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="1717" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="1717" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="200" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="200" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1300" android:valueFrom="0" android:valueTo="0.5" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0.5" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1033" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="867" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="467" android:startOffset="1033" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 167.99 C35.35,167.99 64,139.34 64,104 C64,104 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,104 -64,104 C-64,139.34 -35.34,167.99 0,167.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1033" android:valueFrom="0" android:valueTo="-1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="-1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="167" android:startOffset="867" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -138.333,0 -193.667,0 -166,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="467" android:startOffset="1033" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -138.333,0 -27.667,0 0,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="4017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_back_right.xml b/quickstep/res/drawable/gesture_tutorial_back_right.xml
new file mode 100644
index 0000000..77d9924
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_back_right.xml
@@ -0,0 +1,561 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="892dp" android:width="412dp" android:viewportHeight="892" android:viewportWidth="412">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_7_G" android:translateX="206" android:translateY="446">
+ <path android:name="_R_G_L_7_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_6_G" android:pivotX="206" android:pivotY="446" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_6_G_L_3_G" android:translateX="206" android:translateY="446" android:scaleX="1.2" android:scaleY="1.2">
+ <path android:name="_R_G_L_6_G_L_3_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G">
+ <group android:name="_R_G_L_6_G_L_2_G_L_11_G" android:translateX="206" android:translateY="496.5">
+ <path android:name="_R_G_L_6_G_L_2_G_L_11_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M235.5 -452.14 C235.5,-452.14 235.5,452.14 235.5,452.14 C235.5,452.14 -235.5,452.14 -235.5,452.14 C-235.5,452.14 -235.5,-452.14 -235.5,-452.14 C-235.5,-452.14 235.5,-452.14 235.5,-452.14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_10_G" android:translateX="182.5" android:translateY="831">
+ <path android:name="_R_G_L_6_G_L_2_G_L_10_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_9_G" android:translateX="186" android:translateY="801">
+ <path android:name="_R_G_L_6_G_L_2_G_L_9_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -7 C162,-7 162,7 162,7 C162,9.21 160.21,11 158,11 C158,11 -158,11 -158,11 C-160.21,11 -162,9.21 -162,7 C-162,7 -162,-7 -162,-7 C-162,-9.21 -160.21,-11 -158,-11 C-158,-11 158,-11 158,-11 C160.21,-11 162,-9.21 162,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_8_G" android:translateX="119" android:translateY="755">
+ <path android:name="_R_G_L_6_G_L_2_G_L_8_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M95 -7 C95,-7 95,7 95,7 C95,9.21 93.21,11 91,11 C91,11 -91,11 -91,11 C-93.21,11 -95,9.21 -95,7 C-95,7 -95,-7 -95,-7 C-95,-9.21 -93.21,-11 -91,-11 C-91,-11 91,-11 91,-11 C93.21,-11 95,-9.21 95,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_7_G" android:translateX="182.5" android:translateY="725">
+ <path android:name="_R_G_L_6_G_L_2_G_L_7_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_6_G" android:translateX="197.5" android:translateY="695">
+ <path android:name="_R_G_L_6_G_L_2_G_L_6_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M173.5 -7 C173.5,-7 173.5,7 173.5,7 C173.5,9.21 171.71,11 169.5,11 C169.5,11 -169.5,11 -169.5,11 C-171.71,11 -173.5,9.21 -173.5,7 C-173.5,7 -173.5,-7 -173.5,-7 C-173.5,-9.21 -171.71,-11 -169.5,-11 C-169.5,-11 169.5,-11 169.5,-11 C171.71,-11 173.5,-9.21 173.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_5_G" android:translateX="192" android:translateY="665">
+ <path android:name="_R_G_L_6_G_L_2_G_L_5_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M168 -7 C168,-7 168,7 168,7 C168,9.21 166.21,11 164,11 C164,11 -164,11 -164,11 C-166.21,11 -168,9.21 -168,7 C-168,7 -168,-7 -168,-7 C-168,-9.21 -166.21,-11 -164,-11 C-164,-11 164,-11 164,-11 C166.21,-11 168,-9.21 168,-7c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_4_G" android:translateX="105.5" android:translateY="360">
+ <path android:name="_R_G_L_6_G_L_2_G_L_4_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_3_G" android:translateX="47.5" android:translateY="360">
+ <path android:name="_R_G_L_6_G_L_2_G_L_3_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_2_G" android:translateX="142.5" android:translateY="328">
+ <path android:name="_R_G_L_6_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M118.5 -14 C118.5,-14 118.5,14 118.5,14 C118.5,16.21 116.71,18 114.5,18 C114.5,18 -114.5,18 -114.5,18 C-116.71,18 -118.5,16.21 -118.5,14 C-118.5,14 -118.5,-14 -118.5,-14 C-118.5,-16.21 -116.71,-18 -114.5,-18 C-114.5,-18 114.5,-18 114.5,-18 C116.71,-18 118.5,-16.21 118.5,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_1_G" android:translateX="186" android:translateY="284">
+ <path android:name="_R_G_L_6_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -14 C162,-14 162,14 162,14 C162,16.21 160.21,18 158,18 C158,18 -158,18 -158,18 C-160.21,18 -162,16.21 -162,14 C-162,14 -162,-14 -162,-14 C-162,-16.21 -160.21,-18 -158,-18 C-158,-18 158,-18 158,-18 C160.21,-18 162,-16.21 162,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_2_G_L_0_G" android:translateX="155" android:translateY="240">
+ <path android:name="_R_G_L_6_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M131 -14 C131,-14 131,14 131,14 C131,16.21 129.21,18 127,18 C127,18 -127,18 -127,18 C-129.21,18 -131,16.21 -131,14 C-131,14 -131,-14 -131,-14 C-131,-16.21 -129.21,-18 -127,-18 C-127,-18 127,-18 127,-18 C129.21,-18 131,-16.21 131,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G" android:translateX="24" android:translateY="390">
+ <group android:name="_R_G_L_6_G_L_1_G_L_7_G" android:translateX="182" android:translateY="120"/>
+ <group android:name="_R_G_L_6_G_L_1_G_L_6_G" android:translateX="182" android:translateY="120">
+ <path android:name="_R_G_L_6_G_L_1_G_L_6_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M182 -116 C182,-116 182,116 182,116 C182,118.21 180.21,120 178,120 C178,120 -178,120 -178,120 C-180.21,120 -182,118.21 -182,116 C-182,116 -182,-116 -182,-116 C-182,-118.21 -180.21,-120 -178,-120 C-178,-120 178,-120 178,-120 C180.21,-120 182,-118.21 182,-116c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_5_G" android:translateX="77.322" android:translateY="150.552">
+ <path android:name="_R_G_L_6_G_L_1_G_L_5_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_5_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_4_G" android:translateX="38.772" android:translateY="121.73">
+ <path android:name="_R_G_L_6_G_L_1_G_L_4_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_4_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_3_G" android:translateX="183" android:translateY="222">
+ <path android:name="_R_G_L_6_G_L_1_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_3_G_D_1_P_0" android:strokeColor="#9aa0a6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_2_G" android:translateX="265.619" android:translateY="162.331">
+ <path android:name="_R_G_L_6_G_L_1_G_L_2_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ <path android:name="_R_G_L_6_G_L_1_G_L_2_G_D_1_P_0" android:strokeColor="#a8cbfe" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_1_G" android:translateX="319.271" android:translateY="37.945">
+ <path android:name="_R_G_L_6_G_L_1_G_L_1_G_D_0_P_0" android:fillColor="#feefc3" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.42 2.99 C14.95,-4.17 9.93,-11.31 2.21,-12.96 C-0.9,-13.62 -3.97,-13.3 -6.64,-12.2 C-6.58,-12.19 -6.53,-12.18 -6.48,-12.17 C-1.03,-11.01 2.52,-5.97 1.44,-0.92 C0.36,4.13 -4.94,7.28 -10.4,6.12 C-11.6,5.86 -12.7,5.42 -13.69,4.83 C-11.9,8.78 -8.15,11.93 -3.34,12.96 C4.38,14.61 11.88,10.14 13.42,2.99c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_1_G_L_0_G" android:translateX="179.5" android:translateY="73.351">
+ <path android:name="_R_G_L_6_G_L_1_G_L_0_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M51.08 -40.95 C51.08,-40.95 50.55,-42.54 50.55,-42.54 C50.55,-42.54 49.67,-41.13 49.67,-41.13 C49.67,-41.13 48.17,-41.21 48.17,-41.21 C48.17,-41.21 49.05,-39.8 49.05,-39.8 C49.05,-39.8 48.61,-38.22 48.61,-38.22 C48.61,-38.22 50.02,-38.74 50.02,-38.74 C50.02,-38.74 51.35,-37.69 51.35,-37.69 C51.35,-37.69 51.26,-39.45 51.26,-39.45 C51.26,-39.45 52.59,-40.42 52.59,-40.42 C52.59,-40.42 51.08,-40.95 51.08,-40.95c M8.78 30.58 C8.78,30.58 8.25,28.99 8.25,28.99 C8.25,28.99 7.37,30.4 7.37,30.4 C7.37,30.4 5.87,30.31 5.87,30.31 C5.87,30.31 6.75,31.72 6.75,31.72 C6.75,31.72 6.31,33.31 6.31,33.31 C6.31,33.31 7.72,32.78 7.72,32.78 C7.72,32.78 9.05,33.84 9.05,33.84 C9.05,33.84 8.96,32.08 8.96,32.08 C8.96,32.08 10.29,31.11 10.29,31.11 C10.29,31.11 8.78,30.58 8.78,30.58c M19.38 -61.67 C19.38,-61.67 18.94,-63.35 18.94,-63.35 C18.94,-63.35 17.97,-61.94 17.97,-61.94 C17.97,-61.94 16.47,-61.94 16.47,-61.94 C16.47,-61.94 17.35,-60.62 17.35,-60.62 C17.35,-60.62 16.91,-58.94 16.91,-58.94 C16.91,-58.94 18.41,-59.56 18.41,-59.56 C18.41,-59.56 19.65,-58.5 19.65,-58.5 C19.65,-58.5 19.56,-60.18 19.56,-60.18 C19.56,-60.18 20.88,-61.23 20.88,-61.23 C20.88,-61.23 19.38,-61.67 19.38,-61.67c M-32.98 35.08 C-32.98,35.08 -33.51,33.4 -33.51,33.4 C-33.51,33.4 -34.4,34.81 -34.4,34.81 C-34.4,34.81 -35.9,34.81 -35.9,34.81 C-35.9,34.81 -35.01,36.22 -35.01,36.22 C-35.01,36.22 -35.45,37.81 -35.45,37.81 C-35.45,37.81 -34.04,37.28 -34.04,37.28 C-34.04,37.28 -32.72,38.25 -32.72,38.25 C-32.72,38.25 -32.81,36.58 -32.81,36.58 C-32.81,36.58 -31.48,35.6 -31.48,35.6 C-31.48,35.6 -32.98,35.08 -32.98,35.08c M45.34 7.56 C45.34,7.56 44.81,5.97 44.81,5.97 C44.81,5.97 43.93,7.38 43.93,7.38 C43.93,7.38 42.34,7.3 42.34,7.3 C42.34,7.3 43.31,8.71 43.31,8.71 C43.31,8.71 42.87,10.29 42.87,10.29 C42.87,10.29 44.28,9.77 44.28,9.77 C44.28,9.77 45.52,10.82 45.52,10.82 C45.52,10.82 45.52,9.06 45.52,9.06 C45.52,9.06 46.76,8.09 46.76,8.09 C46.76,8.09 45.34,7.56 45.34,7.56c M-9.59 -41.67 C-9.59,-41.67 -10.12,-43.35 -10.12,-43.35 C-10.12,-43.35 -11,-41.94 -11,-41.94 C-11,-41.94 -12.5,-41.94 -12.5,-41.94 C-12.5,-41.94 -11.62,-40.62 -11.62,-40.62 C-11.62,-40.62 -12.06,-38.94 -12.06,-38.94 C-12.06,-38.94 -10.65,-39.56 -10.65,-39.56 C-10.65,-39.56 -9.32,-38.5 -9.32,-38.5 C-9.32,-38.5 -9.41,-40.26 -9.41,-40.26 C-9.41,-40.26 -8.09,-41.23 -8.09,-41.23 C-8.09,-41.23 -9.59,-41.67 -9.59,-41.67c M97.74 -23.97 C97.74,-23.97 97.03,-26.35 97.03,-26.35 C97.03,-26.35 95.8,-24.32 95.8,-24.32 C95.8,-24.32 93.5,-24.32 93.5,-24.32 C93.5,-24.32 94.91,-22.38 94.91,-22.38 C94.91,-22.38 94.21,-20 94.21,-20 C94.21,-20 96.33,-20.88 96.33,-20.88 C96.33,-20.88 98.09,-19.38 98.09,-19.38 C98.09,-19.38 98.09,-21.85 98.09,-21.85 C98.09,-21.85 99.86,-23.26 99.86,-23.26 C99.86,-23.26 97.74,-23.97 97.74,-23.97c M167.29 43.28 C167.29,43.28 166.67,40.9 166.67,40.9 C166.67,40.9 165.35,42.93 165.35,42.93 C165.35,42.93 163.14,42.93 163.14,42.93 C163.14,42.93 164.47,44.87 164.47,44.87 C164.47,44.87 163.76,47.25 163.76,47.25 C163.76,47.25 165.88,46.37 165.88,46.37 C165.88,46.37 167.73,47.87 167.73,47.87 C167.73,47.87 167.65,45.4 167.65,45.4 C167.65,45.4 169.5,43.98 169.5,43.98 C169.5,43.98 167.29,43.28 167.29,43.28c M-1.1 -1.79 C-1.1,-1.79 -1.72,-4.08 -1.72,-4.08 C-1.72,-4.08 -3.05,-2.14 -3.05,-2.14 C-3.05,-2.14 -5.25,-2.14 -5.25,-2.14 C-5.25,-2.14 -3.93,-0.11 -3.93,-0.11 C-3.93,-0.11 -4.64,2.18 -4.64,2.18 C-4.64,2.18 -2.52,1.38 -2.52,1.38 C-2.52,1.38 -0.66,2.8 -0.66,2.8 C-0.66,2.8 -0.75,0.41 -0.75,0.41 C-0.75,0.41 1.1,-1.08 1.1,-1.08 C1.1,-1.08 -1.1,-1.79 -1.1,-1.79c M-60.89 -5.23 C-60.89,-5.23 -61.59,-7.61 -61.59,-7.61 C-61.59,-7.61 -62.83,-5.58 -62.83,-5.58 C-62.83,-5.58 -65.13,-5.58 -65.13,-5.58 C-65.13,-5.58 -63.71,-3.64 -63.71,-3.64 C-63.71,-3.64 -64.42,-1.26 -64.42,-1.26 C-64.42,-1.26 -62.39,-2.14 -62.39,-2.14 C-62.39,-2.14 -60.53,-0.64 -60.53,-0.64 C-60.53,-0.64 -60.62,-3.11 -60.62,-3.11 C-60.62,-3.11 -58.77,-4.52 -58.77,-4.52 C-58.77,-4.52 -60.89,-5.23 -60.89,-5.23c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-51.26 -42.98 C-51.26,-42.98 -54.09,-45.01 -54.09,-45.01 C-54.09,-45.01 -53.91,-41.57 -53.91,-41.57 C-53.91,-41.57 -56.65,-39.54 -56.65,-39.54 C-56.65,-39.54 -53.38,-38.57 -53.38,-38.57 C-53.38,-38.57 -52.32,-35.3 -52.32,-35.3 C-52.32,-35.3 -50.38,-38.13 -50.38,-38.13 C-50.38,-38.13 -46.94,-38.22 -46.94,-38.22 C-46.94,-38.22 -49.05,-40.86 -49.05,-40.86 C-49.05,-40.86 -47.99,-44.21 -47.99,-44.21 C-47.99,-44.21 -51.26,-42.98 -51.26,-42.98c M-92.06 -47.92 C-92.06,-47.92 -92.59,-49.59 -92.59,-49.59 C-92.59,-49.59 -93.47,-48.18 -93.47,-48.18 C-93.47,-48.18 -95.06,-48.18 -95.06,-48.18 C-95.06,-48.18 -94.09,-46.86 -94.09,-46.86 C-94.09,-46.86 -94.53,-45.18 -94.53,-45.18 C-94.53,-45.18 -93.12,-45.8 -93.12,-45.8 C-93.12,-45.8 -91.88,-44.74 -91.88,-44.74 C-91.88,-44.74 -91.88,-46.42 -91.88,-46.42 C-91.88,-46.42 -90.65,-47.47 -90.65,-47.47 C-90.65,-47.47 -92.06,-47.92 -92.06,-47.92c M62.83 -13.34 C62.83,-13.34 62.39,-14.93 62.39,-14.93 C62.39,-14.93 61.5,-13.52 61.5,-13.52 C61.5,-13.52 59.91,-13.52 59.91,-13.52 C59.91,-13.52 60.89,-12.2 60.89,-12.2 C60.89,-12.2 60.36,-10.52 60.36,-10.52 C60.36,-10.52 61.86,-11.14 61.86,-11.14 C61.86,-11.14 63.09,-10.08 63.09,-10.08 C63.09,-10.08 63.09,-11.84 63.09,-11.84 C63.09,-11.84 64.33,-12.81 64.33,-12.81 C64.33,-12.81 62.83,-13.34 62.83,-13.34c M-155.99 -40.95 C-155.99,-40.95 -156.43,-42.54 -156.43,-42.54 C-156.43,-42.54 -157.32,-41.13 -157.32,-41.13 C-157.32,-41.13 -158.91,-41.21 -158.91,-41.21 C-158.91,-41.21 -157.93,-39.8 -157.93,-39.8 C-157.93,-39.8 -158.46,-38.22 -158.46,-38.22 C-158.46,-38.22 -156.96,-38.74 -156.96,-38.74 C-156.96,-38.74 -155.73,-37.69 -155.73,-37.69 C-155.73,-37.69 -155.73,-39.45 -155.73,-39.45 C-155.73,-39.45 -154.49,-40.42 -154.49,-40.42 C-154.49,-40.42 -155.99,-40.95 -155.99,-40.95c M141.24 26.52 C141.24,26.52 140.71,24.85 140.71,24.85 C140.71,24.85 139.83,26.26 139.83,26.26 C139.83,26.26 138.33,26.26 138.33,26.26 C138.33,26.26 139.21,27.67 139.21,27.67 C139.21,27.67 138.77,29.26 138.77,29.26 C138.77,29.26 140.18,28.73 140.18,28.73 C140.18,28.73 141.51,29.7 141.51,29.7 C141.51,29.7 141.42,28.02 141.42,28.02 C141.42,28.02 142.74,27.05 142.74,27.05 C142.74,27.05 141.24,26.52 141.24,26.52c M111.4 -51.27 C111.4,-51.27 110.95,-52.94 110.95,-52.94 C110.95,-52.94 110.07,-51.53 110.07,-51.53 C110.07,-51.53 108.48,-51.53 108.48,-51.53 C108.48,-51.53 109.45,-50.21 109.45,-50.21 C109.45,-50.21 108.92,-48.53 108.92,-48.53 C108.92,-48.53 110.42,-49.15 110.42,-49.15 C110.42,-49.15 111.66,-48.09 111.66,-48.09 C111.66,-48.09 111.66,-49.86 111.66,-49.86 C111.66,-49.86 112.9,-50.83 112.9,-50.83 C112.9,-50.83 111.4,-51.27 111.4,-51.27c M-66.59 53.33 C-66.59,53.33 -67.03,51.65 -67.03,51.65 C-67.03,51.65 -67.91,53.06 -67.91,53.06 C-67.91,53.06 -69.5,53.06 -69.5,53.06 C-69.5,53.06 -68.53,54.47 -68.53,54.47 C-68.53,54.47 -69.06,56.06 -69.06,56.06 C-69.06,56.06 -67.56,55.53 -67.56,55.53 C-67.56,55.53 -66.32,56.5 -66.32,56.5 C-66.32,56.5 -66.32,54.82 -66.32,54.82 C-66.32,54.82 -65.08,53.77 -65.08,53.77 C-65.08,53.77 -66.59,53.33 -66.59,53.33c M-50.59 59.33 C-50.59,59.33 -51.12,57.65 -51.12,57.65 C-51.12,57.65 -52,59.06 -52,59.06 C-52,59.06 -53.5,59.06 -53.5,59.06 C-53.5,59.06 -52.62,60.38 -52.62,60.38 C-52.62,60.38 -53.06,62.06 -53.06,62.06 C-53.06,62.06 -51.65,61.53 -51.65,61.53 C-51.65,61.53 -50.32,62.5 -50.32,62.5 C-50.32,62.5 -50.41,60.82 -50.41,60.82 C-50.41,60.82 -49.08,59.77 -49.08,59.77 C-49.08,59.77 -50.59,59.33 -50.59,59.33c M29.98 -16.08 C29.98,-16.08 29.27,-18.46 29.27,-18.46 C29.27,-18.46 27.95,-16.43 27.95,-16.43 C27.95,-16.43 25.74,-16.43 25.74,-16.43 C25.74,-16.43 27.06,-14.49 27.06,-14.49 C27.06,-14.49 26.36,-12.11 26.36,-12.11 C26.36,-12.11 28.48,-12.9 28.48,-12.9 C28.48,-12.9 30.33,-11.49 30.33,-11.49 C30.33,-11.49 30.24,-13.96 30.24,-13.96 C30.24,-13.96 32.1,-15.37 32.1,-15.37 C32.1,-15.37 29.98,-16.08 29.98,-16.08c M81.28 55.98 C81.28,55.98 80.58,53.6 80.58,53.6 C80.58,53.6 79.25,55.63 79.25,55.63 C79.25,55.63 77.04,55.63 77.04,55.63 C77.04,55.63 78.37,57.57 78.37,57.57 C78.37,57.57 77.66,59.95 77.66,59.95 C77.66,59.95 79.78,59.07 79.78,59.07 C79.78,59.07 81.64,60.56 81.64,60.56 C81.64,60.56 81.55,58.1 81.55,58.1 C81.55,58.1 83.4,56.68 83.4,56.68 C83.4,56.68 81.28,55.98 81.28,55.98c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-74.05 21.76 C-74.05,21.76 -74.66,19.47 -74.66,19.47 C-74.66,19.47 -75.99,21.49 -75.99,21.49 C-75.99,21.49 -78.2,21.41 -78.2,21.41 C-78.2,21.41 -76.87,23.43 -76.87,23.43 C-76.87,23.43 -77.58,25.73 -77.58,25.73 C-77.58,25.73 -75.46,24.93 -75.46,24.93 C-75.46,24.93 -73.6,26.43 -73.6,26.43 C-73.6,26.43 -73.69,23.96 -73.69,23.96 C-73.69,23.96 -71.84,22.46 -71.84,22.46 C-71.84,22.46 -74.05,21.76 -74.05,21.76c M8.98 55.68 C8.98,55.68 6.15,53.65 6.15,53.65 C6.15,53.65 6.24,57.09 6.24,57.09 C6.24,57.09 3.5,59.12 3.5,59.12 C3.5,59.12 6.86,60.09 6.86,60.09 C6.86,60.09 7.92,63.35 7.92,63.35 C7.92,63.35 9.86,60.44 9.86,60.44 C9.86,60.44 13.3,60.44 13.3,60.44 C13.3,60.44 11.18,57.71 11.18,57.71 C11.18,57.71 12.15,54.44 12.15,54.44 C12.15,54.44 8.98,55.68 8.98,55.68c M124.89 -2.41 C124.89,-2.41 122.06,-4.35 122.06,-4.35 C122.06,-4.35 122.24,-0.91 122.24,-0.91 C122.24,-0.91 119.5,1.12 119.5,1.12 C119.5,1.12 122.77,2 122.77,2 C122.77,2 123.83,5.26 123.83,5.26 C123.83,5.26 125.77,2.44 125.77,2.44 C125.77,2.44 129.21,2.44 129.21,2.44 C129.21,2.44 127.09,-0.29 127.09,-0.29 C127.09,-0.29 128.15,-3.56 128.15,-3.56 C128.15,-3.56 124.89,-2.41 124.89,-2.41c M77.31 19.91 C77.31,19.91 74.57,17.88 74.57,17.88 C74.57,17.88 74.66,21.32 74.66,21.32 C74.66,21.32 71.92,23.35 71.92,23.35 C71.92,23.35 75.19,24.32 75.19,24.32 C75.19,24.32 76.34,27.58 76.34,27.58 C76.34,27.58 78.19,24.67 78.19,24.67 C78.19,24.67 81.64,24.67 81.64,24.67 C81.64,24.67 79.52,21.94 79.52,21.94 C79.52,21.94 80.58,18.67 80.58,18.67 C80.58,18.67 77.31,19.91 77.31,19.91c M-28.11 7.68 C-28.11,7.68 -30.94,5.65 -30.94,5.65 C-30.94,5.65 -30.76,9.09 -30.76,9.09 C-30.76,9.09 -33.5,11.12 -33.5,11.12 C-33.5,11.12 -30.23,12.09 -30.23,12.09 C-30.23,12.09 -29.17,15.35 -29.17,15.35 C-29.17,15.35 -27.23,12.44 -27.23,12.44 C-27.23,12.44 -23.79,12.44 -23.79,12.44 C-23.79,12.44 -25.91,9.71 -25.91,9.71 C-25.91,9.71 -24.85,6.44 -24.85,6.44 C-24.85,6.44 -28.11,7.68 -28.11,7.68c M-119.43 -20.22 C-119.43,-20.22 -122.26,-22.16 -122.26,-22.16 C-122.26,-22.16 -122.08,-18.72 -122.08,-18.72 C-122.08,-18.72 -124.82,-16.7 -124.82,-16.7 C-124.82,-16.7 -121.55,-15.81 -121.55,-15.81 C-121.55,-15.81 -120.49,-12.55 -120.49,-12.55 C-120.49,-12.55 -118.55,-15.37 -118.55,-15.37 C-118.55,-15.37 -115.11,-15.37 -115.11,-15.37 C-115.11,-15.37 -117.23,-18.11 -117.23,-18.11 C-117.23,-18.11 -116.17,-21.37 -116.17,-21.37 C-116.17,-21.37 -119.43,-20.22 -119.43,-20.22c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G">
+ <group android:name="_R_G_L_6_G_L_0_G_L_2_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#e8eaed" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M230.57 -95.63 C230.57,-95.63 230.57,42.37 230.57,42.37 C230.57,43.47 229.56,44.37 228.33,44.37 C228.33,44.37 -228.33,44.37 -228.33,44.37 C-229.56,44.37 -230.57,43.47 -230.57,42.37 C-230.57,42.37 -230.57,-95.63 -230.57,-95.63 C-230.57,-96.73 -229.56,-97.63 -228.33,-97.63 C-228.33,-97.63 228.33,-97.63 228.33,-97.63 C229.56,-97.63 230.57,-96.73 230.57,-95.63c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G_L_1_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M109 -14 C109,-14 109,14 109,14 C109,15.1 108.1,16 107,16 C107,16 -107,16 -107,16 C-108.1,16 -109,15.1 -109,14 C-109,14 -109,-14 -109,-14 C-109,-15.1 -108.1,-16 -107,-16 C-107,-16 107,-16 107,-16 C108.1,-16 109,-15.1 109,-14c "/>
+ </group>
+ <group android:name="_R_G_L_6_G_L_0_G_L_0_G" android:translateX="46" android:translateY="145">
+ <path android:name="_R_G_L_6_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M22 -14 C22,-14 22,14 22,14 C22,18.42 18.42,22 14,22 C14,22 -14,22 -14,22 C-18.42,22 -22,18.42 -22,14 C-22,14 -22,-14 -22,-14 C-22,-18.42 -18.42,-22 -14,-22 C-14,-22 14,-22 14,-22 C18.42,-22 22,-18.42 22,-14c "/>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_5_G" android:scaleY="0">
+ <group android:name="_R_G_L_5_G_L_11_G" android:translateX="206" android:translateY="446" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_11_G_D_0_P_0" android:fillColor="#f1f3f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_10_G" android:translateX="148" android:translateY="441" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_10_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M48 -8 C48,-8 48,8 48,8 C48,10.21 46.21,12 44,12 C44,12 -44,12 -44,12 C-46.21,12 -48,10.21 -48,8 C-48,8 -48,-8 -48,-8 C-48,-10.21 -46.21,-12 -44,-12 C-44,-12 44,-12 44,-12 C46.21,-12 48,-10.21 48,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_9_G" android:translateX="264" android:translateY="441" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_9_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M48 -8 C48,-8 48,8 48,8 C48,10.21 46.21,12 44,12 C44,12 -44,12 -44,12 C-46.21,12 -48,10.21 -48,8 C-48,8 -48,-8 -48,-8 C-48,-10.21 -46.21,-12 -44,-12 C-44,-12 44,-12 44,-12 C46.21,-12 48,-10.21 48,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_8_G" android:translateX="206" android:translateY="380" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_8_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M176 0 C176,0 176,0 176,0 C176,14.9 163.9,27 149,27 C149,27 -149,27 -149,27 C-163.9,27 -176,14.9 -176,0 C-176,0 -176,0 -176,0 C-176,-14.9 -163.9,-27 -149,-27 C-149,-27 149,-27 149,-27 C163.9,-27 176,-14.9 176,0c "/>
+ <path android:name="_R_G_L_5_G_L_8_G_D_1_P_0" android:strokeColor="#bdc1c6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M176 0 C176,0 176,0 176,0 C176,14.9 163.9,27 149,27 C149,27 -149,27 -149,27 C-163.9,27 -176,14.9 -176,0 C-176,0 -176,0 -176,0 C-176,-14.9 -163.9,-27 -149,-27 C-149,-27 149,-27 149,-27 C163.9,-27 176,-14.9 176,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_7_G" android:translateX="120" android:translateY="268" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_7_G_D_0_P_0" android:fillColor="#4285f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M26 0 C26,0 26,0 26,0 C26,14.35 14.35,26 0,26 C0,26 0,26 0,26 C-14.35,26 -26,14.35 -26,0 C-26,0 -26,0 -26,0 C-26,-14.35 -14.35,-26 0,-26 C0,-26 0,-26 0,-26 C14.35,-26 26,-14.35 26,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_6_G" android:translateX="167" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_6_G_D_0_P_0" android:fillColor="#e94235" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_5_G" android:translateX="205" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_5_G_D_0_P_0" android:fillColor="#fabb05" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_4_G" android:translateX="243" android:translateY="286" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_4_G_D_0_P_0" android:fillColor="#4285f4" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 -8 C17,-8 17,8 17,8 C17,17.38 9.38,25 0,25 C0,25 0,25 0,25 C-9.38,25 -17,17.38 -17,8 C-17,8 -17,-8 -17,-8 C-17,-17.38 -9.38,-25 0,-25 C0,-25 0,-25 0,-25 C9.38,-25 17,-17.38 17,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_3_G" android:translateX="272" android:translateY="269" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_3_G_D_0_P_0" android:fillColor="#34a853" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8 -17 C8,-17 8,17 8,17 C8,21.42 4.42,25 0,25 C0,25 0,25 0,25 C-4.42,25 -8,21.42 -8,17 C-8,17 -8,-17 -8,-17 C-8,-21.42 -4.42,-25 0,-25 C0,-25 0,-25 0,-25 C4.42,-25 8,-21.42 8,-17c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_2_G" android:translateX="301" android:translateY="278" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_2_G_D_0_P_0" android:fillColor="#e94235" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M17 0 C17,0 17,0 17,0 C17,9.38 9.38,17 0,17 C0,17 0,17 0,17 C-9.38,17 -17,9.38 -17,0 C-17,0 -17,0 -17,0 C-17,-9.38 -9.38,-17 0,-17 C0,-17 0,-17 0,-17 C9.38,-17 17,-9.38 17,0c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_1_G" android:translateX="42" android:translateY="140" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M12 -8 C12,-8 12,8 12,8 C12,10.21 10.21,12 8,12 C8,12 -8,12 -8,12 C-10.21,12 -12,10.21 -12,8 C-12,8 -12,-8 -12,-8 C-12,-10.21 -10.21,-12 -8,-12 C-8,-12 8,-12 8,-12 C10.21,-12 12,-10.21 12,-8c "/>
+ </group>
+ <group android:name="_R_G_L_5_G_L_0_G" android:translateX="92.5" android:translateY="140" android:scaleY="0">
+ <path android:name="_R_G_L_5_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M28.5 -5 C28.5,-5 28.5,5 28.5,5 C28.5,7.21 26.71,9 24.5,9 C24.5,9 -24.5,9 -24.5,9 C-26.71,9 -28.5,7.21 -28.5,5 C-28.5,5 -28.5,-5 -28.5,-5 C-28.5,-7.21 -26.71,-9 -24.5,-9 C-24.5,-9 24.5,-9 24.5,-9 C26.71,-9 28.5,-7.21 28.5,-5c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_4_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_3_G">
+ <group android:name="_R_G_L_3_G_L_1_G" android:translateX="206" android:translateY="50.5">
+ <path android:name="_R_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -50.5 C206,-50.5 206,50.5 206,50.5 C206,50.5 -206,50.5 -206,50.5 C-206,50.5 -206,-50.5 -206,-50.5 C-206,-50.5 206,-50.5 206,-50.5c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_0_G" android:translateX="206" android:translateY="66.5">
+ <path android:name="_R_G_L_3_G_L_0_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M190 0 C190,0 190,0 190,0 C190,10.21 181.71,18.5 171.5,18.5 C171.5,18.5 -171.5,18.5 -171.5,18.5 C-181.71,18.5 -190,10.21 -190,0 C-190,0 -190,0 -190,0 C-190,-10.21 -181.71,-18.5 -171.5,-18.5 C-171.5,-18.5 171.5,-18.5 171.5,-18.5 C181.71,-18.5 190,-10.21 190,0c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_2_G" android:translateX="382.824" android:translateY="462.5" android:scaleX="-1" android:scaleY="0">
+ <group android:name="_R_G_L_2_G_D_0_P_0_G_0_T_0" android:translateX="-60" android:translateY="0">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M28.25 0 C28.25,31.2 2.95,56.5 -28.25,56.5 C-28.25,56.5 -28.25,-56.5 -28.25,-56.5 C2.95,-56.5 28.25,-31.2 28.25,0c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G" android:translateX="414.087" android:translateY="463" android:scaleX="0.5" android:scaleY="0" android:rotation="180">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M3.87 -13.45 C3.07,-14.21 1.8,-14.18 1.04,-13.38 C0.28,-12.58 0.31,-11.31 1.11,-10.55 C1.11,-10.55 9.75,-2.32 9.75,-2.32 C9.75,-2.32 -14.75,-2.32 -14.75,-2.32 C-15.85,-2.32 -16.75,-1.43 -16.75,-0.32 C-16.75,0.78 -15.85,1.68 -14.75,1.68 C-14.75,1.68 9.94,1.68 9.94,1.68 C9.94,1.68 1.07,10.59 1.07,10.59 C0.29,11.37 0.29,12.64 1.08,13.42 C1.86,14.2 3.13,14.19 3.9,13.41 C3.9,13.41 16.17,1.09 16.17,1.09 C16.55,0.71 16.76,0.19 16.75,-0.35 C16.74,-0.89 16.52,-1.4 16.13,-1.77 C16.13,-1.77 3.87,-13.45 3.87,-13.45c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_N_1_T_0" android:translateX="206" android:translateY="446" android:scaleX="-1" android:scaleY="0">
+ <group android:name="_R_G_L_0_G" android:translateX="-336.003" android:translateY="-48.003">
+ <group android:name="_R_G_L_0_G_L_2_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M-166 64 C-130.65,64 -102,35.35 -102,0 C-102,-35.34 -130.65,-64 -166,-64 C-201.34,-64 -230,-35.34 -230,0 C-230,35.35 -201.34,64 -166,64c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_1_G" android:translateX="192" android:translateY="63.997" android:rotation="90" android:scaleX="-1" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_0_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0" android:translateX="-166" android:translateY="0">
+ <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 64 C35.35,64 64,35.35 64,0 C64,-35.34 35.35,-64 0,-64 C-35.34,-64 -64,-35.34 -64,0 C-64,35.35 -35.34,64 0,64c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_6_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2283" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2283" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="2133" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="2133" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.88012" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.88012" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,0.536 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2417" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_11_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_10_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2433" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_9_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2433" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_8_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_7_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2367" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1133" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -60,0C -50.167,0 -69.833,0 -60,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="667" android:startOffset="1133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -60,0C -50.167,0 -10.833,0 -1,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="1800" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -1,0C -1,0 -1,0 -1,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0.333 0,0 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="2133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -1,0C -10.833,0 -50.167,0 -60,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1133" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2467" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1133" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 414.087,463C 409.087,463 419.087,463 414.087,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="583" android:startOffset="1133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 414.087,463C 409.087,463 389.087,463 384.087,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="417" android:startOffset="1717" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 384.087,463C 384.087,463 384.087,463 384.087,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0.333 0.667,0.667 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="333" android:startOffset="2133" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 384.087,463C 389.087,463 409.087,463 414.087,463">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="1300" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="1300" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="1300" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="1300" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="417" android:startOffset="1717" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="417" android:startOffset="1717" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="200" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="200" android:startOffset="2133" android:valueFrom="1" android:valueTo="0.5" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1300" android:valueFrom="0" android:valueTo="0.5" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2333" android:valueFrom="0.5" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1033" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="867" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="467" android:startOffset="1033" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 167.99 C35.35,167.99 64,139.34 64,104 C64,104 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,104 -64,104 C-64,139.34 -35.34,167.99 0,167.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1033" android:valueFrom="0" android:valueTo="-1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="-1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="167" android:startOffset="867" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -138.333,0 -193.667,0 -166,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="467" android:startOffset="1033" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -138.333,0 -27.667,0 0,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_1_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="867" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_1_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2267" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="4017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml b/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml
new file mode 100644
index 0000000..0a34af6
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="50dp"/>
+ <solid android:color="@android:color/transparent"/>
+ <stroke android:width="1dp" android:color="@color/gesture_tutorial_primary_color"/>
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_home.xml b/quickstep/res/drawable/gesture_tutorial_home.xml
new file mode 100644
index 0000000..e77eb74
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_home.xml
@@ -0,0 +1,394 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="892dp" android:width="412dp" android:viewportHeight="892" android:viewportWidth="412">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_4_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_4_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_3_G">
+ <path android:name="_R_G_L_3_G_S" android:fillColor="#000000" android:pathData="M0,0 L412,0 L412,892 L0,892z"/>
+ </group>
+ <group android:name="_R_G_L_2_G" android:scaleY="0">
+ <group android:name="_R_G_L_2_G_L_5_G" android:translateX="206" android:translateY="872" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_5_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_2_G_L_4_G" android:translateX="206" android:translateY="776" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_4_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M180 0 C180,0 180,0 180,0 C180,13.8 168.8,25 155,25 C155,25 -155,25 -155,25 C-168.8,25 -180,13.8 -180,0 C-180,0 -180,0 -180,0 C-180,-13.8 -168.8,-25 -155,-25 C-155,-25 155,-25 155,-25 C168.8,-25 180,-13.8 180,0c "/>
+ </group>
+ <group android:name="_R_G_L_2_G_L_3_G" android:translateX="56" android:translateY="673" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_3_G_D_0_P_0" android:fillColor="#8ab4f8" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -30 C16.56,-30 30,-16.56 30,0 C30,16.56 16.56,30 0,30 C-16.56,30 -30,16.56 -30,0 C-30,-16.56 -16.56,-30 0,-30c "/>
+ </group>
+ <group android:name="_R_G_L_2_G_L_2_G" android:translateX="156" android:translateY="673" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#f28b82" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -30 C16.56,-30 30,-16.56 30,0 C30,16.56 16.56,30 0,30 C-16.56,30 -30,16.56 -30,0 C-30,-16.56 -16.56,-30 0,-30c "/>
+ </group>
+ <group android:name="_R_G_L_2_G_L_1_G" android:translateX="256" android:translateY="673" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#fdd663" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -30 C16.56,-30 30,-16.56 30,0 C30,16.56 16.56,30 0,30 C-16.56,30 -30,16.56 -30,0 C-30,-16.56 -16.56,-30 0,-30c "/>
+ </group>
+ <group android:name="_R_G_L_2_G_L_0_G" android:translateX="356" android:translateY="673" android:scaleY="0">
+ <path android:name="_R_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#81c995" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 -30 C16.56,-30 30,-16.56 30,0 C30,16.56 16.56,30 0,30 C-16.56,30 -30,16.56 -30,0 C-30,-16.56 -16.56,-30 0,-30c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_N_1_T_0" android:translateX="206" android:translateY="446" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_1_G" android:translateX="-206" android:translateY="-446">
+ <group android:name="_R_G_L_1_G_L_4_G">
+ <group android:name="_R_G_L_1_G_L_4_G_L_11_G" android:translateX="206" android:translateY="472.769" android:scaleX="0.87473" android:scaleY="0.98643">
+ <path android:name="_R_G_L_1_G_L_4_G_L_11_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M235.5 -407 C235.5,-407 235.5,407 235.5,407 C235.5,416.93 227.43,425 217.5,425 C217.5,425 -217.5,425 -217.5,425 C-227.43,425 -235.5,416.93 -235.5,407 C-235.5,407 -235.5,-407 -235.5,-407 C-235.5,-416.93 -227.43,-425 -217.5,-425 C-217.5,-425 217.5,-425 217.5,-425 C227.43,-425 235.5,-416.93 235.5,-407c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_10_G" android:translateX="182.5" android:translateY="831">
+ <path android:name="_R_G_L_1_G_L_4_G_L_10_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_9_G" android:translateX="186" android:translateY="801">
+ <path android:name="_R_G_L_1_G_L_4_G_L_9_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -7 C162,-7 162,7 162,7 C162,9.21 160.21,11 158,11 C158,11 -158,11 -158,11 C-160.21,11 -162,9.21 -162,7 C-162,7 -162,-7 -162,-7 C-162,-9.21 -160.21,-11 -158,-11 C-158,-11 158,-11 158,-11 C160.21,-11 162,-9.21 162,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_8_G" android:translateX="119" android:translateY="755">
+ <path android:name="_R_G_L_1_G_L_4_G_L_8_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M95 -7 C95,-7 95,7 95,7 C95,9.21 93.21,11 91,11 C91,11 -91,11 -91,11 C-93.21,11 -95,9.21 -95,7 C-95,7 -95,-7 -95,-7 C-95,-9.21 -93.21,-11 -91,-11 C-91,-11 91,-11 91,-11 C93.21,-11 95,-9.21 95,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_7_G" android:translateX="182.5" android:translateY="725">
+ <path android:name="_R_G_L_1_G_L_4_G_L_7_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_6_G" android:translateX="197.5" android:translateY="695">
+ <path android:name="_R_G_L_1_G_L_4_G_L_6_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M173.5 -7 C173.5,-7 173.5,7 173.5,7 C173.5,9.21 171.71,11 169.5,11 C169.5,11 -169.5,11 -169.5,11 C-171.71,11 -173.5,9.21 -173.5,7 C-173.5,7 -173.5,-7 -173.5,-7 C-173.5,-9.21 -171.71,-11 -169.5,-11 C-169.5,-11 169.5,-11 169.5,-11 C171.71,-11 173.5,-9.21 173.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_5_G" android:translateX="192" android:translateY="665">
+ <path android:name="_R_G_L_1_G_L_4_G_L_5_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M168 -7 C168,-7 168,7 168,7 C168,9.21 166.21,11 164,11 C164,11 -164,11 -164,11 C-166.21,11 -168,9.21 -168,7 C-168,7 -168,-7 -168,-7 C-168,-9.21 -166.21,-11 -164,-11 C-164,-11 164,-11 164,-11 C166.21,-11 168,-9.21 168,-7c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_4_G" android:translateX="105.5" android:translateY="360">
+ <path android:name="_R_G_L_1_G_L_4_G_L_4_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_3_G" android:translateX="47.5" android:translateY="360">
+ <path android:name="_R_G_L_1_G_L_4_G_L_3_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_2_G" android:translateX="142.5" android:translateY="328">
+ <path android:name="_R_G_L_1_G_L_4_G_L_2_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M118.5 -14 C118.5,-14 118.5,14 118.5,14 C118.5,16.21 116.71,18 114.5,18 C114.5,18 -114.5,18 -114.5,18 C-116.71,18 -118.5,16.21 -118.5,14 C-118.5,14 -118.5,-14 -118.5,-14 C-118.5,-16.21 -116.71,-18 -114.5,-18 C-114.5,-18 114.5,-18 114.5,-18 C116.71,-18 118.5,-16.21 118.5,-14c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_1_G" android:translateX="186" android:translateY="284">
+ <path android:name="_R_G_L_1_G_L_4_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -14 C162,-14 162,14 162,14 C162,16.21 160.21,18 158,18 C158,18 -158,18 -158,18 C-160.21,18 -162,16.21 -162,14 C-162,14 -162,-14 -162,-14 C-162,-16.21 -160.21,-18 -158,-18 C-158,-18 158,-18 158,-18 C160.21,-18 162,-16.21 162,-14c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_4_G_L_0_G" android:translateX="155" android:translateY="240">
+ <path android:name="_R_G_L_1_G_L_4_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M131 -14 C131,-14 131,14 131,14 C131,16.21 129.21,18 127,18 C127,18 -127,18 -127,18 C-129.21,18 -131,16.21 -131,14 C-131,14 -131,-14 -131,-14 C-131,-16.21 -129.21,-18 -127,-18 C-127,-18 127,-18 127,-18 C129.21,-18 131,-16.21 131,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G" android:translateX="24" android:translateY="390">
+ <group android:name="_R_G_L_1_G_L_3_G_L_7_G" android:translateX="182" android:translateY="120"/>
+ <group android:name="_R_G_L_1_G_L_3_G_L_6_G" android:translateX="182" android:translateY="120">
+ <path android:name="_R_G_L_1_G_L_3_G_L_6_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M182 -116 C182,-116 182,116 182,116 C182,118.21 180.21,120 178,120 C178,120 -178,120 -178,120 C-180.21,120 -182,118.21 -182,116 C-182,116 -182,-116 -182,-116 C-182,-118.21 -180.21,-120 -178,-120 C-178,-120 178,-120 178,-120 C180.21,-120 182,-118.21 182,-116c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_5_G" android:translateX="77.322" android:translateY="150.552">
+ <path android:name="_R_G_L_1_G_L_3_G_L_5_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ <path android:name="_R_G_L_1_G_L_3_G_L_5_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_4_G" android:translateX="38.772" android:translateY="121.73">
+ <path android:name="_R_G_L_1_G_L_3_G_L_4_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ <path android:name="_R_G_L_1_G_L_3_G_L_4_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_3_G" android:translateX="183" android:translateY="222">
+ <path android:name="_R_G_L_1_G_L_3_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ <path android:name="_R_G_L_1_G_L_3_G_L_3_G_D_1_P_0" android:strokeColor="#9aa0a6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_2_G" android:translateX="265.619" android:translateY="162.331">
+ <path android:name="_R_G_L_1_G_L_3_G_L_2_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ <path android:name="_R_G_L_1_G_L_3_G_L_2_G_D_1_P_0" android:strokeColor="#a8cbfe" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_1_G" android:translateX="319.271" android:translateY="37.945">
+ <path android:name="_R_G_L_1_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#feefc3" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.42 2.99 C14.95,-4.17 9.93,-11.31 2.21,-12.96 C-0.9,-13.62 -3.97,-13.3 -6.64,-12.2 C-6.58,-12.19 -6.53,-12.18 -6.48,-12.17 C-1.03,-11.01 2.52,-5.97 1.44,-0.92 C0.36,4.13 -4.94,7.28 -10.4,6.12 C-11.6,5.86 -12.7,5.42 -13.69,4.83 C-11.9,8.78 -8.15,11.93 -3.34,12.96 C4.38,14.61 11.88,10.14 13.42,2.99c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_3_G_L_0_G" android:translateX="179.5" android:translateY="73.351">
+ <path android:name="_R_G_L_1_G_L_3_G_L_0_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M51.08 -40.95 C51.08,-40.95 50.55,-42.54 50.55,-42.54 C50.55,-42.54 49.67,-41.13 49.67,-41.13 C49.67,-41.13 48.17,-41.21 48.17,-41.21 C48.17,-41.21 49.05,-39.8 49.05,-39.8 C49.05,-39.8 48.61,-38.22 48.61,-38.22 C48.61,-38.22 50.02,-38.74 50.02,-38.74 C50.02,-38.74 51.35,-37.69 51.35,-37.69 C51.35,-37.69 51.26,-39.45 51.26,-39.45 C51.26,-39.45 52.59,-40.42 52.59,-40.42 C52.59,-40.42 51.08,-40.95 51.08,-40.95c M8.78 30.58 C8.78,30.58 8.25,28.99 8.25,28.99 C8.25,28.99 7.37,30.4 7.37,30.4 C7.37,30.4 5.87,30.31 5.87,30.31 C5.87,30.31 6.75,31.72 6.75,31.72 C6.75,31.72 6.31,33.31 6.31,33.31 C6.31,33.31 7.72,32.78 7.72,32.78 C7.72,32.78 9.05,33.84 9.05,33.84 C9.05,33.84 8.96,32.08 8.96,32.08 C8.96,32.08 10.29,31.11 10.29,31.11 C10.29,31.11 8.78,30.58 8.78,30.58c M19.38 -61.67 C19.38,-61.67 18.94,-63.35 18.94,-63.35 C18.94,-63.35 17.97,-61.94 17.97,-61.94 C17.97,-61.94 16.47,-61.94 16.47,-61.94 C16.47,-61.94 17.35,-60.62 17.35,-60.62 C17.35,-60.62 16.91,-58.94 16.91,-58.94 C16.91,-58.94 18.41,-59.56 18.41,-59.56 C18.41,-59.56 19.65,-58.5 19.65,-58.5 C19.65,-58.5 19.56,-60.18 19.56,-60.18 C19.56,-60.18 20.88,-61.23 20.88,-61.23 C20.88,-61.23 19.38,-61.67 19.38,-61.67c M-32.98 35.08 C-32.98,35.08 -33.51,33.4 -33.51,33.4 C-33.51,33.4 -34.4,34.81 -34.4,34.81 C-34.4,34.81 -35.9,34.81 -35.9,34.81 C-35.9,34.81 -35.01,36.22 -35.01,36.22 C-35.01,36.22 -35.45,37.81 -35.45,37.81 C-35.45,37.81 -34.04,37.28 -34.04,37.28 C-34.04,37.28 -32.72,38.25 -32.72,38.25 C-32.72,38.25 -32.81,36.58 -32.81,36.58 C-32.81,36.58 -31.48,35.6 -31.48,35.6 C-31.48,35.6 -32.98,35.08 -32.98,35.08c M45.34 7.56 C45.34,7.56 44.81,5.97 44.81,5.97 C44.81,5.97 43.93,7.38 43.93,7.38 C43.93,7.38 42.34,7.3 42.34,7.3 C42.34,7.3 43.31,8.71 43.31,8.71 C43.31,8.71 42.87,10.29 42.87,10.29 C42.87,10.29 44.28,9.77 44.28,9.77 C44.28,9.77 45.52,10.82 45.52,10.82 C45.52,10.82 45.52,9.06 45.52,9.06 C45.52,9.06 46.76,8.09 46.76,8.09 C46.76,8.09 45.34,7.56 45.34,7.56c M-9.59 -41.67 C-9.59,-41.67 -10.12,-43.35 -10.12,-43.35 C-10.12,-43.35 -11,-41.94 -11,-41.94 C-11,-41.94 -12.5,-41.94 -12.5,-41.94 C-12.5,-41.94 -11.62,-40.62 -11.62,-40.62 C-11.62,-40.62 -12.06,-38.94 -12.06,-38.94 C-12.06,-38.94 -10.65,-39.56 -10.65,-39.56 C-10.65,-39.56 -9.32,-38.5 -9.32,-38.5 C-9.32,-38.5 -9.41,-40.26 -9.41,-40.26 C-9.41,-40.26 -8.09,-41.23 -8.09,-41.23 C-8.09,-41.23 -9.59,-41.67 -9.59,-41.67c M97.74 -23.97 C97.74,-23.97 97.03,-26.35 97.03,-26.35 C97.03,-26.35 95.8,-24.32 95.8,-24.32 C95.8,-24.32 93.5,-24.32 93.5,-24.32 C93.5,-24.32 94.91,-22.38 94.91,-22.38 C94.91,-22.38 94.21,-20 94.21,-20 C94.21,-20 96.33,-20.88 96.33,-20.88 C96.33,-20.88 98.09,-19.38 98.09,-19.38 C98.09,-19.38 98.09,-21.85 98.09,-21.85 C98.09,-21.85 99.86,-23.26 99.86,-23.26 C99.86,-23.26 97.74,-23.97 97.74,-23.97c M167.29 43.28 C167.29,43.28 166.67,40.9 166.67,40.9 C166.67,40.9 165.35,42.93 165.35,42.93 C165.35,42.93 163.14,42.93 163.14,42.93 C163.14,42.93 164.47,44.87 164.47,44.87 C164.47,44.87 163.76,47.25 163.76,47.25 C163.76,47.25 165.88,46.37 165.88,46.37 C165.88,46.37 167.73,47.87 167.73,47.87 C167.73,47.87 167.65,45.4 167.65,45.4 C167.65,45.4 169.5,43.98 169.5,43.98 C169.5,43.98 167.29,43.28 167.29,43.28c M-1.1 -1.79 C-1.1,-1.79 -1.72,-4.08 -1.72,-4.08 C-1.72,-4.08 -3.05,-2.14 -3.05,-2.14 C-3.05,-2.14 -5.25,-2.14 -5.25,-2.14 C-5.25,-2.14 -3.93,-0.11 -3.93,-0.11 C-3.93,-0.11 -4.64,2.18 -4.64,2.18 C-4.64,2.18 -2.52,1.38 -2.52,1.38 C-2.52,1.38 -0.66,2.8 -0.66,2.8 C-0.66,2.8 -0.75,0.41 -0.75,0.41 C-0.75,0.41 1.1,-1.08 1.1,-1.08 C1.1,-1.08 -1.1,-1.79 -1.1,-1.79c M-60.89 -5.23 C-60.89,-5.23 -61.59,-7.61 -61.59,-7.61 C-61.59,-7.61 -62.83,-5.58 -62.83,-5.58 C-62.83,-5.58 -65.13,-5.58 -65.13,-5.58 C-65.13,-5.58 -63.71,-3.64 -63.71,-3.64 C-63.71,-3.64 -64.42,-1.26 -64.42,-1.26 C-64.42,-1.26 -62.39,-2.14 -62.39,-2.14 C-62.39,-2.14 -60.53,-0.64 -60.53,-0.64 C-60.53,-0.64 -60.62,-3.11 -60.62,-3.11 C-60.62,-3.11 -58.77,-4.52 -58.77,-4.52 C-58.77,-4.52 -60.89,-5.23 -60.89,-5.23c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-51.26 -42.98 C-51.26,-42.98 -54.09,-45.01 -54.09,-45.01 C-54.09,-45.01 -53.91,-41.57 -53.91,-41.57 C-53.91,-41.57 -56.65,-39.54 -56.65,-39.54 C-56.65,-39.54 -53.38,-38.57 -53.38,-38.57 C-53.38,-38.57 -52.32,-35.3 -52.32,-35.3 C-52.32,-35.3 -50.38,-38.13 -50.38,-38.13 C-50.38,-38.13 -46.94,-38.22 -46.94,-38.22 C-46.94,-38.22 -49.05,-40.86 -49.05,-40.86 C-49.05,-40.86 -47.99,-44.21 -47.99,-44.21 C-47.99,-44.21 -51.26,-42.98 -51.26,-42.98c M-92.06 -47.92 C-92.06,-47.92 -92.59,-49.59 -92.59,-49.59 C-92.59,-49.59 -93.47,-48.18 -93.47,-48.18 C-93.47,-48.18 -95.06,-48.18 -95.06,-48.18 C-95.06,-48.18 -94.09,-46.86 -94.09,-46.86 C-94.09,-46.86 -94.53,-45.18 -94.53,-45.18 C-94.53,-45.18 -93.12,-45.8 -93.12,-45.8 C-93.12,-45.8 -91.88,-44.74 -91.88,-44.74 C-91.88,-44.74 -91.88,-46.42 -91.88,-46.42 C-91.88,-46.42 -90.65,-47.47 -90.65,-47.47 C-90.65,-47.47 -92.06,-47.92 -92.06,-47.92c M62.83 -13.34 C62.83,-13.34 62.39,-14.93 62.39,-14.93 C62.39,-14.93 61.5,-13.52 61.5,-13.52 C61.5,-13.52 59.91,-13.52 59.91,-13.52 C59.91,-13.52 60.89,-12.2 60.89,-12.2 C60.89,-12.2 60.36,-10.52 60.36,-10.52 C60.36,-10.52 61.86,-11.14 61.86,-11.14 C61.86,-11.14 63.09,-10.08 63.09,-10.08 C63.09,-10.08 63.09,-11.84 63.09,-11.84 C63.09,-11.84 64.33,-12.81 64.33,-12.81 C64.33,-12.81 62.83,-13.34 62.83,-13.34c M-155.99 -40.95 C-155.99,-40.95 -156.43,-42.54 -156.43,-42.54 C-156.43,-42.54 -157.32,-41.13 -157.32,-41.13 C-157.32,-41.13 -158.91,-41.21 -158.91,-41.21 C-158.91,-41.21 -157.93,-39.8 -157.93,-39.8 C-157.93,-39.8 -158.46,-38.22 -158.46,-38.22 C-158.46,-38.22 -156.96,-38.74 -156.96,-38.74 C-156.96,-38.74 -155.73,-37.69 -155.73,-37.69 C-155.73,-37.69 -155.73,-39.45 -155.73,-39.45 C-155.73,-39.45 -154.49,-40.42 -154.49,-40.42 C-154.49,-40.42 -155.99,-40.95 -155.99,-40.95c M141.24 26.52 C141.24,26.52 140.71,24.85 140.71,24.85 C140.71,24.85 139.83,26.26 139.83,26.26 C139.83,26.26 138.33,26.26 138.33,26.26 C138.33,26.26 139.21,27.67 139.21,27.67 C139.21,27.67 138.77,29.26 138.77,29.26 C138.77,29.26 140.18,28.73 140.18,28.73 C140.18,28.73 141.51,29.7 141.51,29.7 C141.51,29.7 141.42,28.02 141.42,28.02 C141.42,28.02 142.74,27.05 142.74,27.05 C142.74,27.05 141.24,26.52 141.24,26.52c M111.4 -51.27 C111.4,-51.27 110.95,-52.94 110.95,-52.94 C110.95,-52.94 110.07,-51.53 110.07,-51.53 C110.07,-51.53 108.48,-51.53 108.48,-51.53 C108.48,-51.53 109.45,-50.21 109.45,-50.21 C109.45,-50.21 108.92,-48.53 108.92,-48.53 C108.92,-48.53 110.42,-49.15 110.42,-49.15 C110.42,-49.15 111.66,-48.09 111.66,-48.09 C111.66,-48.09 111.66,-49.86 111.66,-49.86 C111.66,-49.86 112.9,-50.83 112.9,-50.83 C112.9,-50.83 111.4,-51.27 111.4,-51.27c M-66.59 53.33 C-66.59,53.33 -67.03,51.65 -67.03,51.65 C-67.03,51.65 -67.91,53.06 -67.91,53.06 C-67.91,53.06 -69.5,53.06 -69.5,53.06 C-69.5,53.06 -68.53,54.47 -68.53,54.47 C-68.53,54.47 -69.06,56.06 -69.06,56.06 C-69.06,56.06 -67.56,55.53 -67.56,55.53 C-67.56,55.53 -66.32,56.5 -66.32,56.5 C-66.32,56.5 -66.32,54.82 -66.32,54.82 C-66.32,54.82 -65.08,53.77 -65.08,53.77 C-65.08,53.77 -66.59,53.33 -66.59,53.33c M-50.59 59.33 C-50.59,59.33 -51.12,57.65 -51.12,57.65 C-51.12,57.65 -52,59.06 -52,59.06 C-52,59.06 -53.5,59.06 -53.5,59.06 C-53.5,59.06 -52.62,60.38 -52.62,60.38 C-52.62,60.38 -53.06,62.06 -53.06,62.06 C-53.06,62.06 -51.65,61.53 -51.65,61.53 C-51.65,61.53 -50.32,62.5 -50.32,62.5 C-50.32,62.5 -50.41,60.82 -50.41,60.82 C-50.41,60.82 -49.08,59.77 -49.08,59.77 C-49.08,59.77 -50.59,59.33 -50.59,59.33c M29.98 -16.08 C29.98,-16.08 29.27,-18.46 29.27,-18.46 C29.27,-18.46 27.95,-16.43 27.95,-16.43 C27.95,-16.43 25.74,-16.43 25.74,-16.43 C25.74,-16.43 27.06,-14.49 27.06,-14.49 C27.06,-14.49 26.36,-12.11 26.36,-12.11 C26.36,-12.11 28.48,-12.9 28.48,-12.9 C28.48,-12.9 30.33,-11.49 30.33,-11.49 C30.33,-11.49 30.24,-13.96 30.24,-13.96 C30.24,-13.96 32.1,-15.37 32.1,-15.37 C32.1,-15.37 29.98,-16.08 29.98,-16.08c M81.28 55.98 C81.28,55.98 80.58,53.6 80.58,53.6 C80.58,53.6 79.25,55.63 79.25,55.63 C79.25,55.63 77.04,55.63 77.04,55.63 C77.04,55.63 78.37,57.57 78.37,57.57 C78.37,57.57 77.66,59.95 77.66,59.95 C77.66,59.95 79.78,59.07 79.78,59.07 C79.78,59.07 81.64,60.56 81.64,60.56 C81.64,60.56 81.55,58.1 81.55,58.1 C81.55,58.1 83.4,56.68 83.4,56.68 C83.4,56.68 81.28,55.98 81.28,55.98c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-74.05 21.76 C-74.05,21.76 -74.66,19.47 -74.66,19.47 C-74.66,19.47 -75.99,21.49 -75.99,21.49 C-75.99,21.49 -78.2,21.41 -78.2,21.41 C-78.2,21.41 -76.87,23.43 -76.87,23.43 C-76.87,23.43 -77.58,25.73 -77.58,25.73 C-77.58,25.73 -75.46,24.93 -75.46,24.93 C-75.46,24.93 -73.6,26.43 -73.6,26.43 C-73.6,26.43 -73.69,23.96 -73.69,23.96 C-73.69,23.96 -71.84,22.46 -71.84,22.46 C-71.84,22.46 -74.05,21.76 -74.05,21.76c M8.98 55.68 C8.98,55.68 6.15,53.65 6.15,53.65 C6.15,53.65 6.24,57.09 6.24,57.09 C6.24,57.09 3.5,59.12 3.5,59.12 C3.5,59.12 6.86,60.09 6.86,60.09 C6.86,60.09 7.92,63.35 7.92,63.35 C7.92,63.35 9.86,60.44 9.86,60.44 C9.86,60.44 13.3,60.44 13.3,60.44 C13.3,60.44 11.18,57.71 11.18,57.71 C11.18,57.71 12.15,54.44 12.15,54.44 C12.15,54.44 8.98,55.68 8.98,55.68c M124.89 -2.41 C124.89,-2.41 122.06,-4.35 122.06,-4.35 C122.06,-4.35 122.24,-0.91 122.24,-0.91 C122.24,-0.91 119.5,1.12 119.5,1.12 C119.5,1.12 122.77,2 122.77,2 C122.77,2 123.83,5.26 123.83,5.26 C123.83,5.26 125.77,2.44 125.77,2.44 C125.77,2.44 129.21,2.44 129.21,2.44 C129.21,2.44 127.09,-0.29 127.09,-0.29 C127.09,-0.29 128.15,-3.56 128.15,-3.56 C128.15,-3.56 124.89,-2.41 124.89,-2.41c M77.31 19.91 C77.31,19.91 74.57,17.88 74.57,17.88 C74.57,17.88 74.66,21.32 74.66,21.32 C74.66,21.32 71.92,23.35 71.92,23.35 C71.92,23.35 75.19,24.32 75.19,24.32 C75.19,24.32 76.34,27.58 76.34,27.58 C76.34,27.58 78.19,24.67 78.19,24.67 C78.19,24.67 81.64,24.67 81.64,24.67 C81.64,24.67 79.52,21.94 79.52,21.94 C79.52,21.94 80.58,18.67 80.58,18.67 C80.58,18.67 77.31,19.91 77.31,19.91c M-28.11 7.68 C-28.11,7.68 -30.94,5.65 -30.94,5.65 C-30.94,5.65 -30.76,9.09 -30.76,9.09 C-30.76,9.09 -33.5,11.12 -33.5,11.12 C-33.5,11.12 -30.23,12.09 -30.23,12.09 C-30.23,12.09 -29.17,15.35 -29.17,15.35 C-29.17,15.35 -27.23,12.44 -27.23,12.44 C-27.23,12.44 -23.79,12.44 -23.79,12.44 C-23.79,12.44 -25.91,9.71 -25.91,9.71 C-25.91,9.71 -24.85,6.44 -24.85,6.44 C-24.85,6.44 -28.11,7.68 -28.11,7.68c M-119.43 -20.22 C-119.43,-20.22 -122.26,-22.16 -122.26,-22.16 C-122.26,-22.16 -122.08,-18.72 -122.08,-18.72 C-122.08,-18.72 -124.82,-16.7 -124.82,-16.7 C-124.82,-16.7 -121.55,-15.81 -121.55,-15.81 C-121.55,-15.81 -120.49,-12.55 -120.49,-12.55 C-120.49,-12.55 -118.55,-15.37 -118.55,-15.37 C-118.55,-15.37 -115.11,-15.37 -115.11,-15.37 C-115.11,-15.37 -117.23,-18.11 -117.23,-18.11 C-117.23,-18.11 -116.17,-21.37 -116.17,-21.37 C-116.17,-21.37 -119.43,-20.22 -119.43,-20.22c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_L_2_G">
+ <group android:name="_R_G_L_1_G_L_2_G_L_2_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_1_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#e8eaed" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -95.63 C206,-95.63 206,42.37 206,42.37 C206,43.47 205.1,44.37 204,44.37 C204,44.37 -204,44.37 -204,44.37 C-205.1,44.37 -206,43.47 -206,42.37 C-206,42.37 -206,-95.63 -206,-95.63 C-206,-96.73 -205.1,-97.63 -204,-97.63 C-204,-97.63 204,-97.63 204,-97.63 C205.1,-97.63 206,-96.73 206,-95.63c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_2_G_L_1_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_1_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M109 -14 C109,-14 109,14 109,14 C109,15.1 108.1,16 107,16 C107,16 -107,16 -107,16 C-108.1,16 -109,15.1 -109,14 C-109,14 -109,-14 -109,-14 C-109,-15.1 -108.1,-16 -107,-16 C-107,-16 107,-16 107,-16 C108.1,-16 109,-15.1 109,-14c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_2_G_L_0_G" android:translateX="46" android:translateY="145">
+ <path android:name="_R_G_L_1_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M22 -14 C22,-14 22,14 22,14 C22,18.42 18.42,22 14,22 C14,22 -14,22 -14,22 C-18.42,22 -22,18.42 -22,14 C-22,14 -22,-14 -22,-14 C-22,-18.42 -18.42,-22 -14,-22 C-14,-22 14,-22 14,-22 C18.42,-22 22,-18.42 22,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_L_1_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_1_G_L_1_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_0_G">
+ <group android:name="_R_G_L_1_G_L_0_G_L_2_G" android:translateX="206" android:translateY="51">
+ <path android:name="_R_G_L_1_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -0.27 C206,-0.27 206,49.73 206,49.73 C206,49.73 -206,49.73 -206,49.73 C-206,49.73 -206,-0.27 -206,-0.27 C-206,-0.27 206,-0.27 206,-0.27c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_0_G_L_1_G" android:translateX="206" android:translateY="50.5">
+ <path android:name="_R_G_L_1_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -32.5 C206,-32.5 206,32.5 206,32.5 C206,42.43 197.93,50.5 188,50.5 C188,50.5 -188,50.5 -188,50.5 C-197.93,50.5 -206,42.43 -206,32.5 C-206,32.5 -206,-32.5 -206,-32.5 C-206,-42.43 -197.93,-50.5 -188,-50.5 C-188,-50.5 188,-50.5 188,-50.5 C197.93,-50.5 206,-42.43 206,-32.5c "/>
+ </group>
+ <group android:name="_R_G_L_1_G_L_0_G_L_0_G" android:translateX="206" android:translateY="66.5">
+ <path android:name="_R_G_L_1_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M190 0 C190,0 190,0 190,0 C190,10.21 181.71,18.5 171.5,18.5 C171.5,18.5 -171.5,18.5 -171.5,18.5 C-181.71,18.5 -190,10.21 -190,0 C-190,0 -190,0 -190,0 C-190,-10.21 -181.71,-18.5 -171.5,-18.5 C-171.5,-18.5 171.5,-18.5 171.5,-18.5 C181.71,-18.5 190,-10.21 190,0c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G" android:translateX="-30" android:translateY="658.997" android:pivotX="300" android:pivotY="64" android:rotation="-90" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_2_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M-166 64 C-130.65,64 -102,35.35 -102,0 C-102,-35.34 -130.65,-64 -166,-64 C-201.34,-64 -230,-35.34 -230,0 C-230,35.35 -201.34,64 -166,64c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_1_G" android:translateX="192" android:translateY="63.997" android:rotation="90" android:scaleX="-1" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_0_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0" android:translateX="-166" android:translateY="0">
+ <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 64 C35.35,64 64,35.35 64,0 C64,-35.34 35.35,-64 0,-64 C-35.34,-64 -64,-35.34 -64,0 C-64,35.35 -35.34,64 0,64c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_2_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="50" android:startOffset="1917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,776C 206,776 206,776 206,776">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="700" android:startOffset="1967" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,776C 206,776 206,797 206,797">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1967" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="700" android:startOffset="1917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 56,673C 56,673 56,706 56,706">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="700" android:startOffset="1917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 156,673C 156,673 156,706 156,706">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="700" android:startOffset="1917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 256,673C 256,673 256,706 256,706">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="700" android:startOffset="1917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 356,673C 356,673 356,706 356,706">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.27,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1917" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_1_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1533" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,446C 206,446 206,446 206,446">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.477,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="317" android:startOffset="1533" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,446C 206,446 206,354.603 206,354.603">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.477,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="300" android:startOffset="1850" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,354.603C 206,354.603 206,639 206,639">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.531,0.542 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_1_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="1533" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="1533" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="617" android:startOffset="1533" android:valueFrom="1" android:valueTo="0.16" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="617" android:startOffset="1533" android:valueFrom="1" android:valueTo="0.16" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.833,0.833 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="600" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1550" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="217" android:startOffset="1317" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="383" android:startOffset="1533" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M-0.01 363.74 C35.34,363.74 63.99,335.09 63.99,299.75 C63.99,299.75 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64.01,299.75 -64.01,299.75 C-64.01,335.09 -35.35,363.74 -0.01,363.74c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1550" android:valueFrom="0" android:valueTo="-1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2050" android:valueFrom="-1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="217" android:startOffset="1317" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -105.667,0 -226.333,0 -166,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="383" android:startOffset="1533" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -105.667,0 135.667,0 196,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.508,0 0.487,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="600" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2050" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1317" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2050" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="4017" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
diff --git a/quickstep/res/drawable/gesture_tutorial_overview.xml b/quickstep/res/drawable/gesture_tutorial_overview.xml
new file mode 100644
index 0000000..c4ca72f
--- /dev/null
+++ b/quickstep/res/drawable/gesture_tutorial_overview.xml
@@ -0,0 +1,823 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
+ <aapt:attr name="android:drawable">
+ <vector android:height="892dp" android:width="412dp" android:viewportHeight="892" android:viewportWidth="412">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_7_G" android:translateX="206" android:translateY="446">
+ <path android:name="_R_G_L_7_G_D_0_P_0" android:fillColor="#666666" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -446 C206,-446 206,446 206,446 C206,446 -206,446 -206,446 C-206,446 -206,-446 -206,-446 C-206,-446 206,-446 206,-446c "/>
+ </group>
+ <group android:name="_R_G_L_6_G">
+ <path android:name="_R_G_L_6_G_S" android:fillColor="#000000" android:pathData="M0,0 L412,0 L412,892 L0,892z"/>
+ </group>
+ <group android:name="_R_G_L_5_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_5_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_N_7_T_0" android:translateX="206" android:translateY="446" android:scaleX="1" android:scaleY="1">
+ <group android:name="_R_G_L_4_G" android:translateX="-206" android:translateY="-446">
+ <group android:name="_R_G_L_4_G_L_4_G">
+ <group android:name="_R_G_L_4_G_L_4_G_L_11_G" android:translateX="206" android:translateY="467">
+ <path android:name="_R_G_L_4_G_L_4_G_L_11_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -407 C206,-407 206,407 206,407 C206,416.93 197.93,425 188,425 C188,425 -188,425 -188,425 C-197.93,425 -206,416.93 -206,407 C-206,407 -206,-407 -206,-407 C-206,-416.93 -197.93,-425 -188,-425 C-188,-425 188,-425 188,-425 C197.93,-425 206,-416.93 206,-407c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_10_G" android:translateX="182.5" android:translateY="831">
+ <path android:name="_R_G_L_4_G_L_4_G_L_10_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_9_G" android:translateX="186" android:translateY="801">
+ <path android:name="_R_G_L_4_G_L_4_G_L_9_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -7 C162,-7 162,7 162,7 C162,9.21 160.21,11 158,11 C158,11 -158,11 -158,11 C-160.21,11 -162,9.21 -162,7 C-162,7 -162,-7 -162,-7 C-162,-9.21 -160.21,-11 -158,-11 C-158,-11 158,-11 158,-11 C160.21,-11 162,-9.21 162,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_8_G" android:translateX="119" android:translateY="755">
+ <path android:name="_R_G_L_4_G_L_4_G_L_8_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M95 -7 C95,-7 95,7 95,7 C95,9.21 93.21,11 91,11 C91,11 -91,11 -91,11 C-93.21,11 -95,9.21 -95,7 C-95,7 -95,-7 -95,-7 C-95,-9.21 -93.21,-11 -91,-11 C-91,-11 91,-11 91,-11 C93.21,-11 95,-9.21 95,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_7_G" android:translateX="182.5" android:translateY="725">
+ <path android:name="_R_G_L_4_G_L_4_G_L_7_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_6_G" android:translateX="197.5" android:translateY="695">
+ <path android:name="_R_G_L_4_G_L_4_G_L_6_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M173.5 -7 C173.5,-7 173.5,7 173.5,7 C173.5,9.21 171.71,11 169.5,11 C169.5,11 -169.5,11 -169.5,11 C-171.71,11 -173.5,9.21 -173.5,7 C-173.5,7 -173.5,-7 -173.5,-7 C-173.5,-9.21 -171.71,-11 -169.5,-11 C-169.5,-11 169.5,-11 169.5,-11 C171.71,-11 173.5,-9.21 173.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_5_G" android:translateX="192" android:translateY="665">
+ <path android:name="_R_G_L_4_G_L_4_G_L_5_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M168 -7 C168,-7 168,7 168,7 C168,9.21 166.21,11 164,11 C164,11 -164,11 -164,11 C-166.21,11 -168,9.21 -168,7 C-168,7 -168,-7 -168,-7 C-168,-9.21 -166.21,-11 -164,-11 C-164,-11 164,-11 164,-11 C166.21,-11 168,-9.21 168,-7c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_4_G" android:translateX="105.5" android:translateY="360">
+ <path android:name="_R_G_L_4_G_L_4_G_L_4_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_3_G" android:translateX="47.5" android:translateY="360">
+ <path android:name="_R_G_L_4_G_L_4_G_L_3_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_2_G" android:translateX="142.5" android:translateY="328">
+ <path android:name="_R_G_L_4_G_L_4_G_L_2_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M118.5 -14 C118.5,-14 118.5,14 118.5,14 C118.5,16.21 116.71,18 114.5,18 C114.5,18 -114.5,18 -114.5,18 C-116.71,18 -118.5,16.21 -118.5,14 C-118.5,14 -118.5,-14 -118.5,-14 C-118.5,-16.21 -116.71,-18 -114.5,-18 C-114.5,-18 114.5,-18 114.5,-18 C116.71,-18 118.5,-16.21 118.5,-14c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_1_G" android:translateX="186" android:translateY="284">
+ <path android:name="_R_G_L_4_G_L_4_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -14 C162,-14 162,14 162,14 C162,16.21 160.21,18 158,18 C158,18 -158,18 -158,18 C-160.21,18 -162,16.21 -162,14 C-162,14 -162,-14 -162,-14 C-162,-16.21 -160.21,-18 -158,-18 C-158,-18 158,-18 158,-18 C160.21,-18 162,-16.21 162,-14c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_4_G_L_0_G" android:translateX="155" android:translateY="240">
+ <path android:name="_R_G_L_4_G_L_4_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M131 -14 C131,-14 131,14 131,14 C131,16.21 129.21,18 127,18 C127,18 -127,18 -127,18 C-129.21,18 -131,16.21 -131,14 C-131,14 -131,-14 -131,-14 C-131,-16.21 -129.21,-18 -127,-18 C-127,-18 127,-18 127,-18 C129.21,-18 131,-16.21 131,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G" android:translateX="24" android:translateY="390">
+ <group android:name="_R_G_L_4_G_L_3_G_L_7_G" android:translateX="182" android:translateY="120"/>
+ <group android:name="_R_G_L_4_G_L_3_G_L_6_G" android:translateX="182" android:translateY="120">
+ <path android:name="_R_G_L_4_G_L_3_G_L_6_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M182 -116 C182,-116 182,116 182,116 C182,118.21 180.21,120 178,120 C178,120 -178,120 -178,120 C-180.21,120 -182,118.21 -182,116 C-182,116 -182,-116 -182,-116 C-182,-118.21 -180.21,-120 -178,-120 C-178,-120 178,-120 178,-120 C180.21,-120 182,-118.21 182,-116c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_5_G" android:translateX="77.322" android:translateY="150.552">
+ <path android:name="_R_G_L_4_G_L_3_G_L_5_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ <path android:name="_R_G_L_4_G_L_3_G_L_5_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_4_G" android:translateX="38.772" android:translateY="121.73">
+ <path android:name="_R_G_L_4_G_L_3_G_L_4_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ <path android:name="_R_G_L_4_G_L_3_G_L_4_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_3_G" android:translateX="183" android:translateY="222">
+ <path android:name="_R_G_L_4_G_L_3_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ <path android:name="_R_G_L_4_G_L_3_G_L_3_G_D_1_P_0" android:strokeColor="#9aa0a6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_2_G" android:translateX="265.619" android:translateY="162.331">
+ <path android:name="_R_G_L_4_G_L_3_G_L_2_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ <path android:name="_R_G_L_4_G_L_3_G_L_2_G_D_1_P_0" android:strokeColor="#a8cbfe" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_1_G" android:translateX="319.271" android:translateY="37.945">
+ <path android:name="_R_G_L_4_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#feefc3" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.42 2.99 C14.95,-4.17 9.93,-11.31 2.21,-12.96 C-0.9,-13.62 -3.97,-13.3 -6.64,-12.2 C-6.58,-12.19 -6.53,-12.18 -6.48,-12.17 C-1.03,-11.01 2.52,-5.97 1.44,-0.92 C0.36,4.13 -4.94,7.28 -10.4,6.12 C-11.6,5.86 -12.7,5.42 -13.69,4.83 C-11.9,8.78 -8.15,11.93 -3.34,12.96 C4.38,14.61 11.88,10.14 13.42,2.99c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_3_G_L_0_G" android:translateX="179.5" android:translateY="73.351">
+ <path android:name="_R_G_L_4_G_L_3_G_L_0_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M51.08 -40.95 C51.08,-40.95 50.55,-42.54 50.55,-42.54 C50.55,-42.54 49.67,-41.13 49.67,-41.13 C49.67,-41.13 48.17,-41.21 48.17,-41.21 C48.17,-41.21 49.05,-39.8 49.05,-39.8 C49.05,-39.8 48.61,-38.22 48.61,-38.22 C48.61,-38.22 50.02,-38.74 50.02,-38.74 C50.02,-38.74 51.35,-37.69 51.35,-37.69 C51.35,-37.69 51.26,-39.45 51.26,-39.45 C51.26,-39.45 52.59,-40.42 52.59,-40.42 C52.59,-40.42 51.08,-40.95 51.08,-40.95c M8.78 30.58 C8.78,30.58 8.25,28.99 8.25,28.99 C8.25,28.99 7.37,30.4 7.37,30.4 C7.37,30.4 5.87,30.31 5.87,30.31 C5.87,30.31 6.75,31.72 6.75,31.72 C6.75,31.72 6.31,33.31 6.31,33.31 C6.31,33.31 7.72,32.78 7.72,32.78 C7.72,32.78 9.05,33.84 9.05,33.84 C9.05,33.84 8.96,32.08 8.96,32.08 C8.96,32.08 10.29,31.11 10.29,31.11 C10.29,31.11 8.78,30.58 8.78,30.58c M19.38 -61.67 C19.38,-61.67 18.94,-63.35 18.94,-63.35 C18.94,-63.35 17.97,-61.94 17.97,-61.94 C17.97,-61.94 16.47,-61.94 16.47,-61.94 C16.47,-61.94 17.35,-60.62 17.35,-60.62 C17.35,-60.62 16.91,-58.94 16.91,-58.94 C16.91,-58.94 18.41,-59.56 18.41,-59.56 C18.41,-59.56 19.65,-58.5 19.65,-58.5 C19.65,-58.5 19.56,-60.18 19.56,-60.18 C19.56,-60.18 20.88,-61.23 20.88,-61.23 C20.88,-61.23 19.38,-61.67 19.38,-61.67c M-32.98 35.08 C-32.98,35.08 -33.51,33.4 -33.51,33.4 C-33.51,33.4 -34.4,34.81 -34.4,34.81 C-34.4,34.81 -35.9,34.81 -35.9,34.81 C-35.9,34.81 -35.01,36.22 -35.01,36.22 C-35.01,36.22 -35.45,37.81 -35.45,37.81 C-35.45,37.81 -34.04,37.28 -34.04,37.28 C-34.04,37.28 -32.72,38.25 -32.72,38.25 C-32.72,38.25 -32.81,36.58 -32.81,36.58 C-32.81,36.58 -31.48,35.6 -31.48,35.6 C-31.48,35.6 -32.98,35.08 -32.98,35.08c M45.34 7.56 C45.34,7.56 44.81,5.97 44.81,5.97 C44.81,5.97 43.93,7.38 43.93,7.38 C43.93,7.38 42.34,7.3 42.34,7.3 C42.34,7.3 43.31,8.71 43.31,8.71 C43.31,8.71 42.87,10.29 42.87,10.29 C42.87,10.29 44.28,9.77 44.28,9.77 C44.28,9.77 45.52,10.82 45.52,10.82 C45.52,10.82 45.52,9.06 45.52,9.06 C45.52,9.06 46.76,8.09 46.76,8.09 C46.76,8.09 45.34,7.56 45.34,7.56c M-9.59 -41.67 C-9.59,-41.67 -10.12,-43.35 -10.12,-43.35 C-10.12,-43.35 -11,-41.94 -11,-41.94 C-11,-41.94 -12.5,-41.94 -12.5,-41.94 C-12.5,-41.94 -11.62,-40.62 -11.62,-40.62 C-11.62,-40.62 -12.06,-38.94 -12.06,-38.94 C-12.06,-38.94 -10.65,-39.56 -10.65,-39.56 C-10.65,-39.56 -9.32,-38.5 -9.32,-38.5 C-9.32,-38.5 -9.41,-40.26 -9.41,-40.26 C-9.41,-40.26 -8.09,-41.23 -8.09,-41.23 C-8.09,-41.23 -9.59,-41.67 -9.59,-41.67c M97.74 -23.97 C97.74,-23.97 97.03,-26.35 97.03,-26.35 C97.03,-26.35 95.8,-24.32 95.8,-24.32 C95.8,-24.32 93.5,-24.32 93.5,-24.32 C93.5,-24.32 94.91,-22.38 94.91,-22.38 C94.91,-22.38 94.21,-20 94.21,-20 C94.21,-20 96.33,-20.88 96.33,-20.88 C96.33,-20.88 98.09,-19.38 98.09,-19.38 C98.09,-19.38 98.09,-21.85 98.09,-21.85 C98.09,-21.85 99.86,-23.26 99.86,-23.26 C99.86,-23.26 97.74,-23.97 97.74,-23.97c M167.29 43.28 C167.29,43.28 166.67,40.9 166.67,40.9 C166.67,40.9 165.35,42.93 165.35,42.93 C165.35,42.93 163.14,42.93 163.14,42.93 C163.14,42.93 164.47,44.87 164.47,44.87 C164.47,44.87 163.76,47.25 163.76,47.25 C163.76,47.25 165.88,46.37 165.88,46.37 C165.88,46.37 167.73,47.87 167.73,47.87 C167.73,47.87 167.65,45.4 167.65,45.4 C167.65,45.4 169.5,43.98 169.5,43.98 C169.5,43.98 167.29,43.28 167.29,43.28c M-1.1 -1.79 C-1.1,-1.79 -1.72,-4.08 -1.72,-4.08 C-1.72,-4.08 -3.05,-2.14 -3.05,-2.14 C-3.05,-2.14 -5.25,-2.14 -5.25,-2.14 C-5.25,-2.14 -3.93,-0.11 -3.93,-0.11 C-3.93,-0.11 -4.64,2.18 -4.64,2.18 C-4.64,2.18 -2.52,1.38 -2.52,1.38 C-2.52,1.38 -0.66,2.8 -0.66,2.8 C-0.66,2.8 -0.75,0.41 -0.75,0.41 C-0.75,0.41 1.1,-1.08 1.1,-1.08 C1.1,-1.08 -1.1,-1.79 -1.1,-1.79c M-60.89 -5.23 C-60.89,-5.23 -61.59,-7.61 -61.59,-7.61 C-61.59,-7.61 -62.83,-5.58 -62.83,-5.58 C-62.83,-5.58 -65.13,-5.58 -65.13,-5.58 C-65.13,-5.58 -63.71,-3.64 -63.71,-3.64 C-63.71,-3.64 -64.42,-1.26 -64.42,-1.26 C-64.42,-1.26 -62.39,-2.14 -62.39,-2.14 C-62.39,-2.14 -60.53,-0.64 -60.53,-0.64 C-60.53,-0.64 -60.62,-3.11 -60.62,-3.11 C-60.62,-3.11 -58.77,-4.52 -58.77,-4.52 C-58.77,-4.52 -60.89,-5.23 -60.89,-5.23c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-51.26 -42.98 C-51.26,-42.98 -54.09,-45.01 -54.09,-45.01 C-54.09,-45.01 -53.91,-41.57 -53.91,-41.57 C-53.91,-41.57 -56.65,-39.54 -56.65,-39.54 C-56.65,-39.54 -53.38,-38.57 -53.38,-38.57 C-53.38,-38.57 -52.32,-35.3 -52.32,-35.3 C-52.32,-35.3 -50.38,-38.13 -50.38,-38.13 C-50.38,-38.13 -46.94,-38.22 -46.94,-38.22 C-46.94,-38.22 -49.05,-40.86 -49.05,-40.86 C-49.05,-40.86 -47.99,-44.21 -47.99,-44.21 C-47.99,-44.21 -51.26,-42.98 -51.26,-42.98c M-92.06 -47.92 C-92.06,-47.92 -92.59,-49.59 -92.59,-49.59 C-92.59,-49.59 -93.47,-48.18 -93.47,-48.18 C-93.47,-48.18 -95.06,-48.18 -95.06,-48.18 C-95.06,-48.18 -94.09,-46.86 -94.09,-46.86 C-94.09,-46.86 -94.53,-45.18 -94.53,-45.18 C-94.53,-45.18 -93.12,-45.8 -93.12,-45.8 C-93.12,-45.8 -91.88,-44.74 -91.88,-44.74 C-91.88,-44.74 -91.88,-46.42 -91.88,-46.42 C-91.88,-46.42 -90.65,-47.47 -90.65,-47.47 C-90.65,-47.47 -92.06,-47.92 -92.06,-47.92c M62.83 -13.34 C62.83,-13.34 62.39,-14.93 62.39,-14.93 C62.39,-14.93 61.5,-13.52 61.5,-13.52 C61.5,-13.52 59.91,-13.52 59.91,-13.52 C59.91,-13.52 60.89,-12.2 60.89,-12.2 C60.89,-12.2 60.36,-10.52 60.36,-10.52 C60.36,-10.52 61.86,-11.14 61.86,-11.14 C61.86,-11.14 63.09,-10.08 63.09,-10.08 C63.09,-10.08 63.09,-11.84 63.09,-11.84 C63.09,-11.84 64.33,-12.81 64.33,-12.81 C64.33,-12.81 62.83,-13.34 62.83,-13.34c M-155.99 -40.95 C-155.99,-40.95 -156.43,-42.54 -156.43,-42.54 C-156.43,-42.54 -157.32,-41.13 -157.32,-41.13 C-157.32,-41.13 -158.91,-41.21 -158.91,-41.21 C-158.91,-41.21 -157.93,-39.8 -157.93,-39.8 C-157.93,-39.8 -158.46,-38.22 -158.46,-38.22 C-158.46,-38.22 -156.96,-38.74 -156.96,-38.74 C-156.96,-38.74 -155.73,-37.69 -155.73,-37.69 C-155.73,-37.69 -155.73,-39.45 -155.73,-39.45 C-155.73,-39.45 -154.49,-40.42 -154.49,-40.42 C-154.49,-40.42 -155.99,-40.95 -155.99,-40.95c M141.24 26.52 C141.24,26.52 140.71,24.85 140.71,24.85 C140.71,24.85 139.83,26.26 139.83,26.26 C139.83,26.26 138.33,26.26 138.33,26.26 C138.33,26.26 139.21,27.67 139.21,27.67 C139.21,27.67 138.77,29.26 138.77,29.26 C138.77,29.26 140.18,28.73 140.18,28.73 C140.18,28.73 141.51,29.7 141.51,29.7 C141.51,29.7 141.42,28.02 141.42,28.02 C141.42,28.02 142.74,27.05 142.74,27.05 C142.74,27.05 141.24,26.52 141.24,26.52c M111.4 -51.27 C111.4,-51.27 110.95,-52.94 110.95,-52.94 C110.95,-52.94 110.07,-51.53 110.07,-51.53 C110.07,-51.53 108.48,-51.53 108.48,-51.53 C108.48,-51.53 109.45,-50.21 109.45,-50.21 C109.45,-50.21 108.92,-48.53 108.92,-48.53 C108.92,-48.53 110.42,-49.15 110.42,-49.15 C110.42,-49.15 111.66,-48.09 111.66,-48.09 C111.66,-48.09 111.66,-49.86 111.66,-49.86 C111.66,-49.86 112.9,-50.83 112.9,-50.83 C112.9,-50.83 111.4,-51.27 111.4,-51.27c M-66.59 53.33 C-66.59,53.33 -67.03,51.65 -67.03,51.65 C-67.03,51.65 -67.91,53.06 -67.91,53.06 C-67.91,53.06 -69.5,53.06 -69.5,53.06 C-69.5,53.06 -68.53,54.47 -68.53,54.47 C-68.53,54.47 -69.06,56.06 -69.06,56.06 C-69.06,56.06 -67.56,55.53 -67.56,55.53 C-67.56,55.53 -66.32,56.5 -66.32,56.5 C-66.32,56.5 -66.32,54.82 -66.32,54.82 C-66.32,54.82 -65.08,53.77 -65.08,53.77 C-65.08,53.77 -66.59,53.33 -66.59,53.33c M-50.59 59.33 C-50.59,59.33 -51.12,57.65 -51.12,57.65 C-51.12,57.65 -52,59.06 -52,59.06 C-52,59.06 -53.5,59.06 -53.5,59.06 C-53.5,59.06 -52.62,60.38 -52.62,60.38 C-52.62,60.38 -53.06,62.06 -53.06,62.06 C-53.06,62.06 -51.65,61.53 -51.65,61.53 C-51.65,61.53 -50.32,62.5 -50.32,62.5 C-50.32,62.5 -50.41,60.82 -50.41,60.82 C-50.41,60.82 -49.08,59.77 -49.08,59.77 C-49.08,59.77 -50.59,59.33 -50.59,59.33c M29.98 -16.08 C29.98,-16.08 29.27,-18.46 29.27,-18.46 C29.27,-18.46 27.95,-16.43 27.95,-16.43 C27.95,-16.43 25.74,-16.43 25.74,-16.43 C25.74,-16.43 27.06,-14.49 27.06,-14.49 C27.06,-14.49 26.36,-12.11 26.36,-12.11 C26.36,-12.11 28.48,-12.9 28.48,-12.9 C28.48,-12.9 30.33,-11.49 30.33,-11.49 C30.33,-11.49 30.24,-13.96 30.24,-13.96 C30.24,-13.96 32.1,-15.37 32.1,-15.37 C32.1,-15.37 29.98,-16.08 29.98,-16.08c M81.28 55.98 C81.28,55.98 80.58,53.6 80.58,53.6 C80.58,53.6 79.25,55.63 79.25,55.63 C79.25,55.63 77.04,55.63 77.04,55.63 C77.04,55.63 78.37,57.57 78.37,57.57 C78.37,57.57 77.66,59.95 77.66,59.95 C77.66,59.95 79.78,59.07 79.78,59.07 C79.78,59.07 81.64,60.56 81.64,60.56 C81.64,60.56 81.55,58.1 81.55,58.1 C81.55,58.1 83.4,56.68 83.4,56.68 C83.4,56.68 81.28,55.98 81.28,55.98c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-74.05 21.76 C-74.05,21.76 -74.66,19.47 -74.66,19.47 C-74.66,19.47 -75.99,21.49 -75.99,21.49 C-75.99,21.49 -78.2,21.41 -78.2,21.41 C-78.2,21.41 -76.87,23.43 -76.87,23.43 C-76.87,23.43 -77.58,25.73 -77.58,25.73 C-77.58,25.73 -75.46,24.93 -75.46,24.93 C-75.46,24.93 -73.6,26.43 -73.6,26.43 C-73.6,26.43 -73.69,23.96 -73.69,23.96 C-73.69,23.96 -71.84,22.46 -71.84,22.46 C-71.84,22.46 -74.05,21.76 -74.05,21.76c M8.98 55.68 C8.98,55.68 6.15,53.65 6.15,53.65 C6.15,53.65 6.24,57.09 6.24,57.09 C6.24,57.09 3.5,59.12 3.5,59.12 C3.5,59.12 6.86,60.09 6.86,60.09 C6.86,60.09 7.92,63.35 7.92,63.35 C7.92,63.35 9.86,60.44 9.86,60.44 C9.86,60.44 13.3,60.44 13.3,60.44 C13.3,60.44 11.18,57.71 11.18,57.71 C11.18,57.71 12.15,54.44 12.15,54.44 C12.15,54.44 8.98,55.68 8.98,55.68c M124.89 -2.41 C124.89,-2.41 122.06,-4.35 122.06,-4.35 C122.06,-4.35 122.24,-0.91 122.24,-0.91 C122.24,-0.91 119.5,1.12 119.5,1.12 C119.5,1.12 122.77,2 122.77,2 C122.77,2 123.83,5.26 123.83,5.26 C123.83,5.26 125.77,2.44 125.77,2.44 C125.77,2.44 129.21,2.44 129.21,2.44 C129.21,2.44 127.09,-0.29 127.09,-0.29 C127.09,-0.29 128.15,-3.56 128.15,-3.56 C128.15,-3.56 124.89,-2.41 124.89,-2.41c M77.31 19.91 C77.31,19.91 74.57,17.88 74.57,17.88 C74.57,17.88 74.66,21.32 74.66,21.32 C74.66,21.32 71.92,23.35 71.92,23.35 C71.92,23.35 75.19,24.32 75.19,24.32 C75.19,24.32 76.34,27.58 76.34,27.58 C76.34,27.58 78.19,24.67 78.19,24.67 C78.19,24.67 81.64,24.67 81.64,24.67 C81.64,24.67 79.52,21.94 79.52,21.94 C79.52,21.94 80.58,18.67 80.58,18.67 C80.58,18.67 77.31,19.91 77.31,19.91c M-28.11 7.68 C-28.11,7.68 -30.94,5.65 -30.94,5.65 C-30.94,5.65 -30.76,9.09 -30.76,9.09 C-30.76,9.09 -33.5,11.12 -33.5,11.12 C-33.5,11.12 -30.23,12.09 -30.23,12.09 C-30.23,12.09 -29.17,15.35 -29.17,15.35 C-29.17,15.35 -27.23,12.44 -27.23,12.44 C-27.23,12.44 -23.79,12.44 -23.79,12.44 C-23.79,12.44 -25.91,9.71 -25.91,9.71 C-25.91,9.71 -24.85,6.44 -24.85,6.44 C-24.85,6.44 -28.11,7.68 -28.11,7.68c M-119.43 -20.22 C-119.43,-20.22 -122.26,-22.16 -122.26,-22.16 C-122.26,-22.16 -122.08,-18.72 -122.08,-18.72 C-122.08,-18.72 -124.82,-16.7 -124.82,-16.7 C-124.82,-16.7 -121.55,-15.81 -121.55,-15.81 C-121.55,-15.81 -120.49,-12.55 -120.49,-12.55 C-120.49,-12.55 -118.55,-15.37 -118.55,-15.37 C-118.55,-15.37 -115.11,-15.37 -115.11,-15.37 C-115.11,-15.37 -117.23,-18.11 -117.23,-18.11 C-117.23,-18.11 -116.17,-21.37 -116.17,-21.37 C-116.17,-21.37 -119.43,-20.22 -119.43,-20.22c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_4_G_L_2_G">
+ <group android:name="_R_G_L_4_G_L_2_G_L_2_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_4_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#e8eaed" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -95.63 C206,-95.63 206,42.37 206,42.37 C206,43.47 205.1,44.37 204,44.37 C204,44.37 -204,44.37 -204,44.37 C-205.1,44.37 -206,43.47 -206,42.37 C-206,42.37 -206,-95.63 -206,-95.63 C-206,-96.73 -205.1,-97.63 -204,-97.63 C-204,-97.63 204,-97.63 204,-97.63 C205.1,-97.63 206,-96.73 206,-95.63c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_2_G_L_1_G" android:translateX="206" android:translateY="145">
+ <path android:name="_R_G_L_4_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M109 -14 C109,-14 109,14 109,14 C109,15.1 108.1,16 107,16 C107,16 -107,16 -107,16 C-108.1,16 -109,15.1 -109,14 C-109,14 -109,-14 -109,-14 C-109,-15.1 -108.1,-16 -107,-16 C-107,-16 107,-16 107,-16 C108.1,-16 109,-15.1 109,-14c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_2_G_L_0_G" android:translateX="46" android:translateY="145">
+ <path android:name="_R_G_L_4_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M22 -14 C22,-14 22,14 22,14 C22,18.42 18.42,22 14,22 C14,22 -14,22 -14,22 C-18.42,22 -22,18.42 -22,14 C-22,14 -22,-14 -22,-14 C-22,-18.42 -18.42,-22 -14,-22 C-14,-22 14,-22 14,-22 C18.42,-22 22,-18.42 22,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_4_G_L_1_G" android:translateX="206" android:translateY="877">
+ <path android:name="_R_G_L_4_G_L_1_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_0_G">
+ <group android:name="_R_G_L_4_G_L_0_G_L_2_G" android:translateX="206" android:translateY="50.5">
+ <path android:name="_R_G_L_4_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -29.67 C206,-29.67 206,50.33 206,50.33 C206,50.33 -206,50.33 -206,50.33 C-206,50.33 -206,-29.67 -206,-29.67 C-206,-29.67 206,-29.67 206,-29.67c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_0_G_L_1_G" android:translateX="206" android:translateY="50.5">
+ <path android:name="_R_G_L_4_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -32.5 C206,-32.5 206,32.5 206,32.5 C206,42.43 197.93,50.5 188,50.5 C188,50.5 -188,50.5 -188,50.5 C-197.93,50.5 -206,42.43 -206,32.5 C-206,32.5 -206,-32.5 -206,-32.5 C-206,-42.43 -197.93,-50.5 -188,-50.5 C-188,-50.5 188,-50.5 188,-50.5 C197.93,-50.5 206,-42.43 206,-32.5c "/>
+ </group>
+ <group android:name="_R_G_L_4_G_L_0_G_L_0_G" android:translateX="206" android:translateY="66.5">
+ <path android:name="_R_G_L_4_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M190 0 C190,0 190,0 190,0 C190,10.21 181.71,18.5 171.5,18.5 C171.5,18.5 -171.5,18.5 -171.5,18.5 C-181.71,18.5 -190,10.21 -190,0 C-190,0 -190,0 -190,0 C-190,-10.21 -181.71,-18.5 -171.5,-18.5 C-171.5,-18.5 171.5,-18.5 171.5,-18.5 C181.71,-18.5 190,-10.21 190,0c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_3_G_N_3_T_0" android:translateX="206" android:translateY="395" android:scaleX="0.6" android:scaleY="0">
+ <group android:name="_R_G_L_3_G" android:translateX="-206" android:translateY="-446">
+ <group android:name="_R_G_L_3_G_L_4_G" android:scaleY="0">
+ <group android:name="_R_G_L_3_G_L_4_G_L_11_G" android:translateX="206" android:translateY="467" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_11_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -407 C206,-407 206,407 206,407 C206,416.93 197.93,425 188,425 C188,425 -188,425 -188,425 C-197.93,425 -206,416.93 -206,407 C-206,407 -206,-407 -206,-407 C-206,-416.93 -197.93,-425 -188,-425 C-188,-425 188,-425 188,-425 C197.93,-425 206,-416.93 206,-407c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_10_G" android:translateX="182.5" android:translateY="831" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_10_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_9_G" android:translateX="186" android:translateY="801" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_9_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -7 C162,-7 162,7 162,7 C162,9.21 160.21,11 158,11 C158,11 -158,11 -158,11 C-160.21,11 -162,9.21 -162,7 C-162,7 -162,-7 -162,-7 C-162,-9.21 -160.21,-11 -158,-11 C-158,-11 158,-11 158,-11 C160.21,-11 162,-9.21 162,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_8_G" android:translateX="119" android:translateY="755" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_8_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M95 -7 C95,-7 95,7 95,7 C95,9.21 93.21,11 91,11 C91,11 -91,11 -91,11 C-93.21,11 -95,9.21 -95,7 C-95,7 -95,-7 -95,-7 C-95,-9.21 -93.21,-11 -91,-11 C-91,-11 91,-11 91,-11 C93.21,-11 95,-9.21 95,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_7_G" android:translateX="182.5" android:translateY="725" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_7_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M158.5 -7 C158.5,-7 158.5,7 158.5,7 C158.5,9.21 156.71,11 154.5,11 C154.5,11 -154.5,11 -154.5,11 C-156.71,11 -158.5,9.21 -158.5,7 C-158.5,7 -158.5,-7 -158.5,-7 C-158.5,-9.21 -156.71,-11 -154.5,-11 C-154.5,-11 154.5,-11 154.5,-11 C156.71,-11 158.5,-9.21 158.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_6_G" android:translateX="197.5" android:translateY="695" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_6_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M173.5 -7 C173.5,-7 173.5,7 173.5,7 C173.5,9.21 171.71,11 169.5,11 C169.5,11 -169.5,11 -169.5,11 C-171.71,11 -173.5,9.21 -173.5,7 C-173.5,7 -173.5,-7 -173.5,-7 C-173.5,-9.21 -171.71,-11 -169.5,-11 C-169.5,-11 169.5,-11 169.5,-11 C171.71,-11 173.5,-9.21 173.5,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_5_G" android:translateX="192" android:translateY="665" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_5_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M168 -7 C168,-7 168,7 168,7 C168,9.21 166.21,11 164,11 C164,11 -164,11 -164,11 C-166.21,11 -168,9.21 -168,7 C-168,7 -168,-7 -168,-7 C-168,-9.21 -166.21,-11 -164,-11 C-164,-11 164,-11 164,-11 C166.21,-11 168,-9.21 168,-7c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_4_G" android:translateX="105.5" android:translateY="360" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_4_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_3_G" android:translateX="47.5" android:translateY="360" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_3_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M23.5 -2 C23.5,-2 23.5,2 23.5,2 C23.5,4.21 21.71,6 19.5,6 C19.5,6 -19.5,6 -19.5,6 C-21.71,6 -23.5,4.21 -23.5,2 C-23.5,2 -23.5,-2 -23.5,-2 C-23.5,-4.21 -21.71,-6 -19.5,-6 C-19.5,-6 19.5,-6 19.5,-6 C21.71,-6 23.5,-4.21 23.5,-2c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_2_G" android:translateX="142.5" android:translateY="328" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_2_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M118.5 -14 C118.5,-14 118.5,14 118.5,14 C118.5,16.21 116.71,18 114.5,18 C114.5,18 -114.5,18 -114.5,18 C-116.71,18 -118.5,16.21 -118.5,14 C-118.5,14 -118.5,-14 -118.5,-14 C-118.5,-16.21 -116.71,-18 -114.5,-18 C-114.5,-18 114.5,-18 114.5,-18 C116.71,-18 118.5,-16.21 118.5,-14c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_1_G" android:translateX="186" android:translateY="284" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_1_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M162 -14 C162,-14 162,14 162,14 C162,16.21 160.21,18 158,18 C158,18 -158,18 -158,18 C-160.21,18 -162,16.21 -162,14 C-162,14 -162,-14 -162,-14 C-162,-16.21 -160.21,-18 -158,-18 C-158,-18 158,-18 158,-18 C160.21,-18 162,-16.21 162,-14c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_4_G_L_0_G" android:translateX="155" android:translateY="240" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_4_G_L_0_G_D_0_P_0" android:fillColor="#bdc1c6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M131 -14 C131,-14 131,14 131,14 C131,16.21 129.21,18 127,18 C127,18 -127,18 -127,18 C-129.21,18 -131,16.21 -131,14 C-131,14 -131,-14 -131,-14 C-131,-16.21 -129.21,-18 -127,-18 C-127,-18 127,-18 127,-18 C129.21,-18 131,-16.21 131,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G" android:translateX="24" android:translateY="390" android:scaleY="0">
+ <group android:name="_R_G_L_3_G_L_3_G_L_7_G" android:translateX="182" android:translateY="120" android:scaleY="0"/>
+ <group android:name="_R_G_L_3_G_L_3_G_L_6_G" android:translateX="182" android:translateY="120" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_6_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M182 -116 C182,-116 182,116 182,116 C182,118.21 180.21,120 178,120 C178,120 -178,120 -178,120 C-180.21,120 -182,118.21 -182,116 C-182,116 -182,-116 -182,-116 C-182,-118.21 -180.21,-120 -178,-120 C-178,-120 178,-120 178,-120 C180.21,-120 182,-118.21 182,-116c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_5_G" android:translateX="77.322" android:translateY="150.552" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_5_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ <path android:name="_R_G_L_3_G_L_3_G_L_5_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 20.61 C0,20.61 -10.39,8.69 -10.39,8.69 M0 -6.11 C0,-6.11 -6.78,-15.61 -6.78,-15.61 M0 33.64 C0,33.64 8.26,17.67 8.26,17.67 M0 7.58 C0,7.58 8.26,-7.73 8.26,-7.73 M0 71.19 C0,71.19 0,-18.04 0,-18.04 M-30.22 37.18 C-30.22,37.18 0,-71.19 0,-71.19 C0,-71.19 30.22,37.18 30.22,37.18 C30.22,37.18 -30.22,37.18 -30.22,37.18c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_4_G" android:translateX="38.772" android:translateY="121.73" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_4_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ <path android:name="_R_G_L_3_G_L_3_G_L_4_G_D_1_P_0" android:strokeColor="#9adcb2" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M0 28.82 C0,28.82 -14.52,12.18 -14.52,12.18 M0 -8.58 C0,-8.58 -9.51,-21.75 -9.51,-21.75 M0 47.01 C0,47.01 11.57,24.7 11.57,24.7 M0 10.64 C0,10.64 11.57,-10.78 11.57,-10.78 M0 99.42 C0,99.42 0,-25.21 0,-25.21 M-31.92 51.94 C-31.92,51.94 0,-99.42 0,-99.42 C0,-99.42 31.92,51.94 31.92,51.94 C31.92,51.94 -31.92,51.94 -31.92,51.94c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_3_G" android:translateX="183" android:translateY="222" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_3_G_D_0_P_0" android:fillColor="#000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ <path android:name="_R_G_L_3_G_L_3_G_L_3_G_D_1_P_0" android:strokeColor="#9aa0a6" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="4" android:strokeAlpha="1" android:pathData=" M170 0 C170,0 -170,0 -170,0 "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_2_G" android:translateX="265.619" android:translateY="162.331" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_2_G_D_0_P_0" android:fillColor="#5f6368" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ <path android:name="_R_G_L_3_G_L_3_G_L_2_G_D_1_P_0" android:strokeColor="#a8cbfe" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-34.05 50.06 C-34.05,50.06 -34.05,-49.25 -34.05,-49.25 M-34.05 -49.55 C-34.05,-49.55 17.54,50.06 17.54,50.06 C17.54,50.06 84.62,50.06 84.62,50.06 C84.62,50.06 32.65,-50.06 32.65,-50.06 C32.65,-50.06 -34.05,-50.06 -34.05,-50.06 C-34.05,-50.06 -84.62,50.06 -84.62,50.06 C-84.62,50.06 17.54,50.06 17.54,50.06 "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_1_G" android:translateX="319.271" android:translateY="37.945" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#feefc3" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M13.42 2.99 C14.95,-4.17 9.93,-11.31 2.21,-12.96 C-0.9,-13.62 -3.97,-13.3 -6.64,-12.2 C-6.58,-12.19 -6.53,-12.18 -6.48,-12.17 C-1.03,-11.01 2.52,-5.97 1.44,-0.92 C0.36,4.13 -4.94,7.28 -10.4,6.12 C-11.6,5.86 -12.7,5.42 -13.69,4.83 C-11.9,8.78 -8.15,11.93 -3.34,12.96 C4.38,14.61 11.88,10.14 13.42,2.99c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_3_G_L_0_G" android:translateX="179.5" android:translateY="73.351" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_3_G_L_0_G_D_0_P_0" android:fillColor="#dadce0" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M51.08 -40.95 C51.08,-40.95 50.55,-42.54 50.55,-42.54 C50.55,-42.54 49.67,-41.13 49.67,-41.13 C49.67,-41.13 48.17,-41.21 48.17,-41.21 C48.17,-41.21 49.05,-39.8 49.05,-39.8 C49.05,-39.8 48.61,-38.22 48.61,-38.22 C48.61,-38.22 50.02,-38.74 50.02,-38.74 C50.02,-38.74 51.35,-37.69 51.35,-37.69 C51.35,-37.69 51.26,-39.45 51.26,-39.45 C51.26,-39.45 52.59,-40.42 52.59,-40.42 C52.59,-40.42 51.08,-40.95 51.08,-40.95c M8.78 30.58 C8.78,30.58 8.25,28.99 8.25,28.99 C8.25,28.99 7.37,30.4 7.37,30.4 C7.37,30.4 5.87,30.31 5.87,30.31 C5.87,30.31 6.75,31.72 6.75,31.72 C6.75,31.72 6.31,33.31 6.31,33.31 C6.31,33.31 7.72,32.78 7.72,32.78 C7.72,32.78 9.05,33.84 9.05,33.84 C9.05,33.84 8.96,32.08 8.96,32.08 C8.96,32.08 10.29,31.11 10.29,31.11 C10.29,31.11 8.78,30.58 8.78,30.58c M19.38 -61.67 C19.38,-61.67 18.94,-63.35 18.94,-63.35 C18.94,-63.35 17.97,-61.94 17.97,-61.94 C17.97,-61.94 16.47,-61.94 16.47,-61.94 C16.47,-61.94 17.35,-60.62 17.35,-60.62 C17.35,-60.62 16.91,-58.94 16.91,-58.94 C16.91,-58.94 18.41,-59.56 18.41,-59.56 C18.41,-59.56 19.65,-58.5 19.65,-58.5 C19.65,-58.5 19.56,-60.18 19.56,-60.18 C19.56,-60.18 20.88,-61.23 20.88,-61.23 C20.88,-61.23 19.38,-61.67 19.38,-61.67c M-32.98 35.08 C-32.98,35.08 -33.51,33.4 -33.51,33.4 C-33.51,33.4 -34.4,34.81 -34.4,34.81 C-34.4,34.81 -35.9,34.81 -35.9,34.81 C-35.9,34.81 -35.01,36.22 -35.01,36.22 C-35.01,36.22 -35.45,37.81 -35.45,37.81 C-35.45,37.81 -34.04,37.28 -34.04,37.28 C-34.04,37.28 -32.72,38.25 -32.72,38.25 C-32.72,38.25 -32.81,36.58 -32.81,36.58 C-32.81,36.58 -31.48,35.6 -31.48,35.6 C-31.48,35.6 -32.98,35.08 -32.98,35.08c M45.34 7.56 C45.34,7.56 44.81,5.97 44.81,5.97 C44.81,5.97 43.93,7.38 43.93,7.38 C43.93,7.38 42.34,7.3 42.34,7.3 C42.34,7.3 43.31,8.71 43.31,8.71 C43.31,8.71 42.87,10.29 42.87,10.29 C42.87,10.29 44.28,9.77 44.28,9.77 C44.28,9.77 45.52,10.82 45.52,10.82 C45.52,10.82 45.52,9.06 45.52,9.06 C45.52,9.06 46.76,8.09 46.76,8.09 C46.76,8.09 45.34,7.56 45.34,7.56c M-9.59 -41.67 C-9.59,-41.67 -10.12,-43.35 -10.12,-43.35 C-10.12,-43.35 -11,-41.94 -11,-41.94 C-11,-41.94 -12.5,-41.94 -12.5,-41.94 C-12.5,-41.94 -11.62,-40.62 -11.62,-40.62 C-11.62,-40.62 -12.06,-38.94 -12.06,-38.94 C-12.06,-38.94 -10.65,-39.56 -10.65,-39.56 C-10.65,-39.56 -9.32,-38.5 -9.32,-38.5 C-9.32,-38.5 -9.41,-40.26 -9.41,-40.26 C-9.41,-40.26 -8.09,-41.23 -8.09,-41.23 C-8.09,-41.23 -9.59,-41.67 -9.59,-41.67c M97.74 -23.97 C97.74,-23.97 97.03,-26.35 97.03,-26.35 C97.03,-26.35 95.8,-24.32 95.8,-24.32 C95.8,-24.32 93.5,-24.32 93.5,-24.32 C93.5,-24.32 94.91,-22.38 94.91,-22.38 C94.91,-22.38 94.21,-20 94.21,-20 C94.21,-20 96.33,-20.88 96.33,-20.88 C96.33,-20.88 98.09,-19.38 98.09,-19.38 C98.09,-19.38 98.09,-21.85 98.09,-21.85 C98.09,-21.85 99.86,-23.26 99.86,-23.26 C99.86,-23.26 97.74,-23.97 97.74,-23.97c M167.29 43.28 C167.29,43.28 166.67,40.9 166.67,40.9 C166.67,40.9 165.35,42.93 165.35,42.93 C165.35,42.93 163.14,42.93 163.14,42.93 C163.14,42.93 164.47,44.87 164.47,44.87 C164.47,44.87 163.76,47.25 163.76,47.25 C163.76,47.25 165.88,46.37 165.88,46.37 C165.88,46.37 167.73,47.87 167.73,47.87 C167.73,47.87 167.65,45.4 167.65,45.4 C167.65,45.4 169.5,43.98 169.5,43.98 C169.5,43.98 167.29,43.28 167.29,43.28c M-1.1 -1.79 C-1.1,-1.79 -1.72,-4.08 -1.72,-4.08 C-1.72,-4.08 -3.05,-2.14 -3.05,-2.14 C-3.05,-2.14 -5.25,-2.14 -5.25,-2.14 C-5.25,-2.14 -3.93,-0.11 -3.93,-0.11 C-3.93,-0.11 -4.64,2.18 -4.64,2.18 C-4.64,2.18 -2.52,1.38 -2.52,1.38 C-2.52,1.38 -0.66,2.8 -0.66,2.8 C-0.66,2.8 -0.75,0.41 -0.75,0.41 C-0.75,0.41 1.1,-1.08 1.1,-1.08 C1.1,-1.08 -1.1,-1.79 -1.1,-1.79c M-60.89 -5.23 C-60.89,-5.23 -61.59,-7.61 -61.59,-7.61 C-61.59,-7.61 -62.83,-5.58 -62.83,-5.58 C-62.83,-5.58 -65.13,-5.58 -65.13,-5.58 C-65.13,-5.58 -63.71,-3.64 -63.71,-3.64 C-63.71,-3.64 -64.42,-1.26 -64.42,-1.26 C-64.42,-1.26 -62.39,-2.14 -62.39,-2.14 C-62.39,-2.14 -60.53,-0.64 -60.53,-0.64 C-60.53,-0.64 -60.62,-3.11 -60.62,-3.11 C-60.62,-3.11 -58.77,-4.52 -58.77,-4.52 C-58.77,-4.52 -60.89,-5.23 -60.89,-5.23c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-51.26 -42.98 C-51.26,-42.98 -54.09,-45.01 -54.09,-45.01 C-54.09,-45.01 -53.91,-41.57 -53.91,-41.57 C-53.91,-41.57 -56.65,-39.54 -56.65,-39.54 C-56.65,-39.54 -53.38,-38.57 -53.38,-38.57 C-53.38,-38.57 -52.32,-35.3 -52.32,-35.3 C-52.32,-35.3 -50.38,-38.13 -50.38,-38.13 C-50.38,-38.13 -46.94,-38.22 -46.94,-38.22 C-46.94,-38.22 -49.05,-40.86 -49.05,-40.86 C-49.05,-40.86 -47.99,-44.21 -47.99,-44.21 C-47.99,-44.21 -51.26,-42.98 -51.26,-42.98c M-92.06 -47.92 C-92.06,-47.92 -92.59,-49.59 -92.59,-49.59 C-92.59,-49.59 -93.47,-48.18 -93.47,-48.18 C-93.47,-48.18 -95.06,-48.18 -95.06,-48.18 C-95.06,-48.18 -94.09,-46.86 -94.09,-46.86 C-94.09,-46.86 -94.53,-45.18 -94.53,-45.18 C-94.53,-45.18 -93.12,-45.8 -93.12,-45.8 C-93.12,-45.8 -91.88,-44.74 -91.88,-44.74 C-91.88,-44.74 -91.88,-46.42 -91.88,-46.42 C-91.88,-46.42 -90.65,-47.47 -90.65,-47.47 C-90.65,-47.47 -92.06,-47.92 -92.06,-47.92c M62.83 -13.34 C62.83,-13.34 62.39,-14.93 62.39,-14.93 C62.39,-14.93 61.5,-13.52 61.5,-13.52 C61.5,-13.52 59.91,-13.52 59.91,-13.52 C59.91,-13.52 60.89,-12.2 60.89,-12.2 C60.89,-12.2 60.36,-10.52 60.36,-10.52 C60.36,-10.52 61.86,-11.14 61.86,-11.14 C61.86,-11.14 63.09,-10.08 63.09,-10.08 C63.09,-10.08 63.09,-11.84 63.09,-11.84 C63.09,-11.84 64.33,-12.81 64.33,-12.81 C64.33,-12.81 62.83,-13.34 62.83,-13.34c M-155.99 -40.95 C-155.99,-40.95 -156.43,-42.54 -156.43,-42.54 C-156.43,-42.54 -157.32,-41.13 -157.32,-41.13 C-157.32,-41.13 -158.91,-41.21 -158.91,-41.21 C-158.91,-41.21 -157.93,-39.8 -157.93,-39.8 C-157.93,-39.8 -158.46,-38.22 -158.46,-38.22 C-158.46,-38.22 -156.96,-38.74 -156.96,-38.74 C-156.96,-38.74 -155.73,-37.69 -155.73,-37.69 C-155.73,-37.69 -155.73,-39.45 -155.73,-39.45 C-155.73,-39.45 -154.49,-40.42 -154.49,-40.42 C-154.49,-40.42 -155.99,-40.95 -155.99,-40.95c M141.24 26.52 C141.24,26.52 140.71,24.85 140.71,24.85 C140.71,24.85 139.83,26.26 139.83,26.26 C139.83,26.26 138.33,26.26 138.33,26.26 C138.33,26.26 139.21,27.67 139.21,27.67 C139.21,27.67 138.77,29.26 138.77,29.26 C138.77,29.26 140.18,28.73 140.18,28.73 C140.18,28.73 141.51,29.7 141.51,29.7 C141.51,29.7 141.42,28.02 141.42,28.02 C141.42,28.02 142.74,27.05 142.74,27.05 C142.74,27.05 141.24,26.52 141.24,26.52c M111.4 -51.27 C111.4,-51.27 110.95,-52.94 110.95,-52.94 C110.95,-52.94 110.07,-51.53 110.07,-51.53 C110.07,-51.53 108.48,-51.53 108.48,-51.53 C108.48,-51.53 109.45,-50.21 109.45,-50.21 C109.45,-50.21 108.92,-48.53 108.92,-48.53 C108.92,-48.53 110.42,-49.15 110.42,-49.15 C110.42,-49.15 111.66,-48.09 111.66,-48.09 C111.66,-48.09 111.66,-49.86 111.66,-49.86 C111.66,-49.86 112.9,-50.83 112.9,-50.83 C112.9,-50.83 111.4,-51.27 111.4,-51.27c M-66.59 53.33 C-66.59,53.33 -67.03,51.65 -67.03,51.65 C-67.03,51.65 -67.91,53.06 -67.91,53.06 C-67.91,53.06 -69.5,53.06 -69.5,53.06 C-69.5,53.06 -68.53,54.47 -68.53,54.47 C-68.53,54.47 -69.06,56.06 -69.06,56.06 C-69.06,56.06 -67.56,55.53 -67.56,55.53 C-67.56,55.53 -66.32,56.5 -66.32,56.5 C-66.32,56.5 -66.32,54.82 -66.32,54.82 C-66.32,54.82 -65.08,53.77 -65.08,53.77 C-65.08,53.77 -66.59,53.33 -66.59,53.33c M-50.59 59.33 C-50.59,59.33 -51.12,57.65 -51.12,57.65 C-51.12,57.65 -52,59.06 -52,59.06 C-52,59.06 -53.5,59.06 -53.5,59.06 C-53.5,59.06 -52.62,60.38 -52.62,60.38 C-52.62,60.38 -53.06,62.06 -53.06,62.06 C-53.06,62.06 -51.65,61.53 -51.65,61.53 C-51.65,61.53 -50.32,62.5 -50.32,62.5 C-50.32,62.5 -50.41,60.82 -50.41,60.82 C-50.41,60.82 -49.08,59.77 -49.08,59.77 C-49.08,59.77 -50.59,59.33 -50.59,59.33c M29.98 -16.08 C29.98,-16.08 29.27,-18.46 29.27,-18.46 C29.27,-18.46 27.95,-16.43 27.95,-16.43 C27.95,-16.43 25.74,-16.43 25.74,-16.43 C25.74,-16.43 27.06,-14.49 27.06,-14.49 C27.06,-14.49 26.36,-12.11 26.36,-12.11 C26.36,-12.11 28.48,-12.9 28.48,-12.9 C28.48,-12.9 30.33,-11.49 30.33,-11.49 C30.33,-11.49 30.24,-13.96 30.24,-13.96 C30.24,-13.96 32.1,-15.37 32.1,-15.37 C32.1,-15.37 29.98,-16.08 29.98,-16.08c M81.28 55.98 C81.28,55.98 80.58,53.6 80.58,53.6 C80.58,53.6 79.25,55.63 79.25,55.63 C79.25,55.63 77.04,55.63 77.04,55.63 C77.04,55.63 78.37,57.57 78.37,57.57 C78.37,57.57 77.66,59.95 77.66,59.95 C77.66,59.95 79.78,59.07 79.78,59.07 C79.78,59.07 81.64,60.56 81.64,60.56 C81.64,60.56 81.55,58.1 81.55,58.1 C81.55,58.1 83.4,56.68 83.4,56.68 C83.4,56.68 81.28,55.98 81.28,55.98c M-165.26 -10.97 C-165.26,-10.97 -165.97,-13.35 -165.97,-13.35 C-165.97,-13.35 -167.29,-11.32 -167.29,-11.32 C-167.29,-11.32 -169.5,-11.32 -169.5,-11.32 C-169.5,-11.32 -168.18,-9.38 -168.18,-9.38 C-168.18,-9.38 -168.88,-7 -168.88,-7 C-168.88,-7 -166.76,-7.79 -166.76,-7.79 C-166.76,-7.79 -164.91,-6.38 -164.91,-6.38 C-164.91,-6.38 -165,-8.85 -165,-8.85 C-165,-8.85 -163.14,-10.26 -163.14,-10.26 C-163.14,-10.26 -165.26,-10.97 -165.26,-10.97c M-74.05 21.76 C-74.05,21.76 -74.66,19.47 -74.66,19.47 C-74.66,19.47 -75.99,21.49 -75.99,21.49 C-75.99,21.49 -78.2,21.41 -78.2,21.41 C-78.2,21.41 -76.87,23.43 -76.87,23.43 C-76.87,23.43 -77.58,25.73 -77.58,25.73 C-77.58,25.73 -75.46,24.93 -75.46,24.93 C-75.46,24.93 -73.6,26.43 -73.6,26.43 C-73.6,26.43 -73.69,23.96 -73.69,23.96 C-73.69,23.96 -71.84,22.46 -71.84,22.46 C-71.84,22.46 -74.05,21.76 -74.05,21.76c M8.98 55.68 C8.98,55.68 6.15,53.65 6.15,53.65 C6.15,53.65 6.24,57.09 6.24,57.09 C6.24,57.09 3.5,59.12 3.5,59.12 C3.5,59.12 6.86,60.09 6.86,60.09 C6.86,60.09 7.92,63.35 7.92,63.35 C7.92,63.35 9.86,60.44 9.86,60.44 C9.86,60.44 13.3,60.44 13.3,60.44 C13.3,60.44 11.18,57.71 11.18,57.71 C11.18,57.71 12.15,54.44 12.15,54.44 C12.15,54.44 8.98,55.68 8.98,55.68c M124.89 -2.41 C124.89,-2.41 122.06,-4.35 122.06,-4.35 C122.06,-4.35 122.24,-0.91 122.24,-0.91 C122.24,-0.91 119.5,1.12 119.5,1.12 C119.5,1.12 122.77,2 122.77,2 C122.77,2 123.83,5.26 123.83,5.26 C123.83,5.26 125.77,2.44 125.77,2.44 C125.77,2.44 129.21,2.44 129.21,2.44 C129.21,2.44 127.09,-0.29 127.09,-0.29 C127.09,-0.29 128.15,-3.56 128.15,-3.56 C128.15,-3.56 124.89,-2.41 124.89,-2.41c M77.31 19.91 C77.31,19.91 74.57,17.88 74.57,17.88 C74.57,17.88 74.66,21.32 74.66,21.32 C74.66,21.32 71.92,23.35 71.92,23.35 C71.92,23.35 75.19,24.32 75.19,24.32 C75.19,24.32 76.34,27.58 76.34,27.58 C76.34,27.58 78.19,24.67 78.19,24.67 C78.19,24.67 81.64,24.67 81.64,24.67 C81.64,24.67 79.52,21.94 79.52,21.94 C79.52,21.94 80.58,18.67 80.58,18.67 C80.58,18.67 77.31,19.91 77.31,19.91c M-28.11 7.68 C-28.11,7.68 -30.94,5.65 -30.94,5.65 C-30.94,5.65 -30.76,9.09 -30.76,9.09 C-30.76,9.09 -33.5,11.12 -33.5,11.12 C-33.5,11.12 -30.23,12.09 -30.23,12.09 C-30.23,12.09 -29.17,15.35 -29.17,15.35 C-29.17,15.35 -27.23,12.44 -27.23,12.44 C-27.23,12.44 -23.79,12.44 -23.79,12.44 C-23.79,12.44 -25.91,9.71 -25.91,9.71 C-25.91,9.71 -24.85,6.44 -24.85,6.44 C-24.85,6.44 -28.11,7.68 -28.11,7.68c M-119.43 -20.22 C-119.43,-20.22 -122.26,-22.16 -122.26,-22.16 C-122.26,-22.16 -122.08,-18.72 -122.08,-18.72 C-122.08,-18.72 -124.82,-16.7 -124.82,-16.7 C-124.82,-16.7 -121.55,-15.81 -121.55,-15.81 C-121.55,-15.81 -120.49,-12.55 -120.49,-12.55 C-120.49,-12.55 -118.55,-15.37 -118.55,-15.37 C-118.55,-15.37 -115.11,-15.37 -115.11,-15.37 C-115.11,-15.37 -117.23,-18.11 -117.23,-18.11 C-117.23,-18.11 -116.17,-21.37 -116.17,-21.37 C-116.17,-21.37 -119.43,-20.22 -119.43,-20.22c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_3_G_L_2_G" android:scaleY="0">
+ <group android:name="_R_G_L_3_G_L_2_G_L_2_G" android:translateX="206" android:translateY="145" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_2_G_L_2_G_D_0_P_0" android:fillColor="#e8eaed" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -95.63 C206,-95.63 206,42.37 206,42.37 C206,43.47 205.1,44.37 204,44.37 C204,44.37 -204,44.37 -204,44.37 C-205.1,44.37 -206,43.47 -206,42.37 C-206,42.37 -206,-95.63 -206,-95.63 C-206,-96.73 -205.1,-97.63 -204,-97.63 C-204,-97.63 204,-97.63 204,-97.63 C205.1,-97.63 206,-96.73 206,-95.63c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_2_G_L_1_G" android:translateX="206" android:translateY="145" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_2_G_L_1_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M109 -14 C109,-14 109,14 109,14 C109,15.1 108.1,16 107,16 C107,16 -107,16 -107,16 C-108.1,16 -109,15.1 -109,14 C-109,14 -109,-14 -109,-14 C-109,-15.1 -108.1,-16 -107,-16 C-107,-16 107,-16 107,-16 C108.1,-16 109,-15.1 109,-14c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_2_G_L_0_G" android:translateX="46" android:translateY="145" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_2_G_L_0_G_D_0_P_0" android:fillColor="#80868b" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M22 -14 C22,-14 22,14 22,14 C22,18.42 18.42,22 14,22 C14,22 -14,22 -14,22 C-18.42,22 -22,18.42 -22,14 C-22,14 -22,-14 -22,-14 C-22,-18.42 -18.42,-22 -14,-22 C-14,-22 14,-22 14,-22 C18.42,-22 22,-18.42 22,-14c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_3_G_L_1_G" android:translateX="206" android:translateY="877" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_1_G_D_0_P_0" android:fillColor="#373737" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40 0 C40,0 40,0 40,0 C40,1.1 39.1,2 38,2 C38,2 -38,2 -38,2 C-39.1,2 -40,1.1 -40,0 C-40,0 -40,0 -40,0 C-40,-1.1 -39.1,-2 -38,-2 C-38,-2 38,-2 38,-2 C39.1,-2 40,-1.1 40,0c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_0_G" android:scaleY="0">
+ <group android:name="_R_G_L_3_G_L_0_G_L_2_G" android:translateX="206" android:translateY="50.5" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -29.67 C206,-29.67 206,50.33 206,50.33 C206,50.33 -206,50.33 -206,50.33 C-206,50.33 -206,-29.67 -206,-29.67 C-206,-29.67 206,-29.67 206,-29.67c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_0_G_L_1_G" android:translateX="206" android:translateY="50.5" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#202124" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M206 -32.5 C206,-32.5 206,32.5 206,32.5 C206,42.43 197.93,50.5 188,50.5 C188,50.5 -188,50.5 -188,50.5 C-197.93,50.5 -206,42.43 -206,32.5 C-206,32.5 -206,-32.5 -206,-32.5 C-206,-42.43 -197.93,-50.5 -188,-50.5 C-188,-50.5 188,-50.5 188,-50.5 C197.93,-50.5 206,-42.43 206,-32.5c "/>
+ </group>
+ <group android:name="_R_G_L_3_G_L_0_G_L_0_G" android:translateX="206" android:translateY="66.5" android:scaleY="0">
+ <path android:name="_R_G_L_3_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M190 0 C190,0 190,0 190,0 C190,10.21 181.71,18.5 171.5,18.5 C171.5,18.5 -171.5,18.5 -171.5,18.5 C-181.71,18.5 -190,10.21 -190,0 C-190,0 -190,0 -190,0 C-190,-10.21 -181.71,-18.5 -171.5,-18.5 C-171.5,-18.5 171.5,-18.5 171.5,-18.5 C181.71,-18.5 190,-10.21 190,0c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_2_G_N_3_T_0" android:translateX="206" android:translateY="395" android:scaleX="0.6" android:scaleY="0">
+ <group android:name="_R_G_L_2_G" android:translateY="-508.163" android:scaleX="0.68838" android:scaleY="0.68838">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#9aa0a6" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 25 C13.81,25 25,13.81 25,0 C25,-13.81 13.81,-25 0,-25 C-13.81,-25 -25,-13.81 -25,0 C-25,13.81 -13.81,25 0,25c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_N_3_T_0" android:translateX="206" android:translateY="395" android:scaleX="0.6" android:scaleY="0">
+ <group android:name="_R_G_L_1_G" android:translateX="-556.176" android:translateY="-7.307" android:scaleX="1.39" android:scaleY="1.39">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#3c4043" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M136.82 -315.36 C136.82,-315.36 -137.18,-315.36 -137.18,-315.36 C-137.18,-315.36 -137.18,326.29 -137.18,326.29 C-137.18,326.29 136.82,326.29 136.82,326.29 C136.82,326.29 136.82,-315.36 136.82,-315.36c "/>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G" android:translateX="-30" android:translateY="658.997" android:pivotX="300" android:pivotY="64" android:rotation="-90" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_2_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_2_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M-166 64 C-130.65,64 -102,35.35 -102,0 C-102,-35.34 -130.65,-64 -166,-64 C-201.34,-64 -230,-35.34 -230,0 C-230,35.35 -201.34,64 -166,64c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_1_G" android:translateX="192" android:translateY="63.997" android:rotation="90" android:scaleX="-1" android:scaleY="0">
+ <path android:name="_R_G_L_0_G_L_1_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="0.3" android:fillType="nonZero" android:pathData=" M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c "/>
+ </group>
+ <group android:name="_R_G_L_0_G_L_0_G" android:translateX="295.995" android:translateY="63.997" android:scaleY="0">
+ <group android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0" android:translateX="-166" android:translateY="0">
+ <path android:name="_R_G_L_0_G_L_0_G_D_0_P_0" android:fillColor="#baf29d" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M0 64 C35.35,64 64,35.35 64,0 C64,-35.34 35.35,-64 0,-64 C-35.34,-64 -64,-35.34 -64,0 C-64,35.35 -35.34,64 0,64c "/>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group"/>
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_4_G_N_7_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="1500" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,446C 206,446 206,446 206,446">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="950" android:startOffset="1500" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,446C 206,446 206,395 206,395">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_4_G_N_7_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="1500" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="1500" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="950" android:startOffset="1500" android:valueFrom="1" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="950" android:startOffset="1500" android:valueFrom="1" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_4_G_N_7_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_4_G_N_7_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_11_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_10_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_9_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_8_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_7_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_7_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_6_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_5_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_4_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_3_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_2_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_2_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_2_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="3400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,386.5 206,395">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="350" android:startOffset="3400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,437.5 206,446">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_3_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3400" android:valueFrom="0" android:valueTo="0.6" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="3883" android:startOffset="0" android:valueFrom="0.68838" android:valueTo="0.68838" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="3883" android:startOffset="0" android:valueFrom="0.68838" android:valueTo="0.68838" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="167" android:startOffset="3883" android:valueFrom="0.68838" android:valueTo="1.37677" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="167" android:startOffset="3883" android:valueFrom="0.68838" android:valueTo="1.37677" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="3400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,386.5 206,395">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="350" android:startOffset="3400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,437.5 206,446">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3883" android:valueFrom="0" android:valueTo="0.6" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="2667" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -556.176,-7.307C -556.176,-7.307 -556.176,-7.307 -556.176,-7.307">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.272,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="250" android:startOffset="2667" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -556.176,-7.307C -556.176,-7.307 -421.176,-7.307 -421.176,-7.307">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.272,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="417" android:startOffset="2917" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -421.176,-7.307C -421.176,-7.307 -429.51,-7.307 -429.51,-7.307">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="3400" android:startOffset="0" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,386.5 206,395">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="350" android:startOffset="3400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M 206,395C 206,403.5 206,437.5 206,446">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleX" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="3400" android:startOffset="0" android:valueFrom="0.6" android:valueTo="0.6" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="350" android:startOffset="3400" android:valueFrom="0.6" android:valueTo="0.72718" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.34,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleX" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="scaleY" android:duration="217" android:startOffset="3750" android:valueFrom="0.72718" android:valueTo="0.72" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.51,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="2667" android:valueFrom="0" android:valueTo="0.6" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1233" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_2_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1400" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="167" android:startOffset="1233" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="1050" android:startOffset="1400" android:valueFrom="M0 1.99 C35.34,1.99 64,-26.66 63.99,-62.01 C63.99,-62.01 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64,-62 -64,-62 C-64,-26.66 -35.35,1.99 0,1.99c " android:valueTo="M-0.01 229.99 C35.33,229.99 63.99,201.34 63.99,166 C63.99,166 64.01,-61.87 64.01,-61.87 C64.01,-97.21 35.35,-125.87 0.01,-125.87 C-35.34,-125.87 -63.99,-97.21 -63.99,-61.87 C-63.99,-61.87 -64.01,166 -64.01,166 C-64.01,201.34 -35.36,229.99 -0.01,229.99c " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1400" android:valueFrom="0" android:valueTo="-1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_1_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3483" android:valueFrom="-1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G_D_0_P_0_G_0_T_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateXY" android:duration="167" android:startOffset="1233" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -128,0 -204,0 -166,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateXY" android:duration="1050" android:startOffset="1400" android:propertyXName="translateX" android:propertyYName="translateY" android:pathData="M -166,0C -128,0 24,0 62,0">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.5,0 0.5,1 1.0,1.0"/>
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1233" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3483" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="1233" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="3483" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="5133" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/>
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
index 55400a7..a43296f 100644
--- a/quickstep/res/layout/fallback_recents_activity.xml
+++ b/quickstep/res/layout/fallback_recents_activity.xml
@@ -33,6 +33,12 @@
android:layout_height="match_parent"
android:clipChildren="false">
+ <com.android.launcher3.views.ScrimView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/scrim_view"
+ android:background="@android:color/transparent" />
+
<com.android.quickstep.fallback.FallbackRecentsView
android:id="@id/overview_panel"
android:layout_width="match_parent"
diff --git a/quickstep/res/layout/gesture_tutorial_dialog.xml b/quickstep/res/layout/gesture_tutorial_dialog.xml
new file mode 100644
index 0000000..59bf7b9
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_dialog.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/bg_sandbox_feedback"
+ android:paddingTop="24dp"
+ android:paddingBottom="24dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
+
+ <TextView
+ android:id="@+id/gesture_tutorial_dialog_title"
+ style="@style/TextAppearance.GestureTutorial.Dialog.Title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/skip_tutorial_dialog_title"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ <TextView
+ android:id="@+id/gesture_tutorial_dialog_subtitle"
+ style="@style/TextAppearance.GestureTutorial.Dialog.Subtitle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:text="@string/skip_tutorial_dialog_subtitle"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_dialog_title"/>
+
+ <!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
+ of elevation and shadow) which is replaced by ripple effect in android:foreground -->
+ <Button
+ android:id="@+id/gesture_tutorial_dialog_cancel_button"
+ style="@style/TextAppearance.GestureTutorial.CancelButtonLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="46dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:background="@drawable/gesture_tutorial_cancel_button_background"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:stateListAnimator="@null"
+ android:text="@string/gesture_tutorial_action_button_label_cancel"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_dialog_subtitle"/>
+
+ <Button
+ android:id="@+id/gesture_tutorial_dialog_confirm_button"
+ style="@style/TextAppearance.GestureTutorial.ButtonLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="46dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:background="@drawable/gesture_tutorial_action_button_background"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:stateListAnimator="@null"
+ android:text="@string/gesture_tutorial_action_button_label_skip"
+
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_dialog_subtitle"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 16b2c56..700dd1f 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -15,6 +15,7 @@
-->
<com.android.quickstep.interaction.RootSandboxLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false">
@@ -53,112 +54,93 @@
android:layout_height="match_parent"
android:background="@drawable/gesture_tutorial_ripple"/>
- <VideoView
+ <ImageView
android:id="@+id/gesture_tutorial_feedback_video"
- android:layout_width="0dp"
- android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
- android:layout_alignParentEnd="true"/>
-
- <ImageButton
- android:id="@+id/gesture_tutorial_fragment_close_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_marginStart="4dp"
- android:layout_marginTop="30dp"
- android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
- android:background="@android:color/transparent"
- android:contentDescription="@string/gesture_tutorial_close_button_content_description"
- android:padding="18dp"
- android:src="@drawable/gesture_tutorial_close_button"
- android:tint="?android:attr/textColorPrimary"
+ android:layout_alignParentEnd="true"
+ android:scaleType="fitXY"
android:visibility="gone"/>
- <LinearLayout
- android:id="@+id/gesture_tutorial_fragment_titles_container"
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_fragment_feedback_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- android:layout_marginTop="70dp"
- android:focusable="true"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/gesture_tutorial_fragment_title_view"
- style="@style/TextAppearance.GestureTutorial.Title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/gesture_tutorial_title_margin_start_end"
- android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"/>
-
- <TextView
- android:id="@+id/gesture_tutorial_fragment_subtitle_view"
- style="@style/TextAppearance.GestureTutorial.Subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"/>
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/gesture_tutorial_fragment_feedback_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
android:layout_marginTop="24dp"
android:padding="24dp"
- android:gravity="center_vertical"
android:background="@drawable/bg_sandbox_feedback">
+ <ImageButton
+ android:id="@+id/gesture_tutorial_fragment_close_button"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:src="@drawable/close_icon"
+ android:background="@drawable/bg_sandbox_close_button"
+ android:contentDescription="@string/gesture_tutorial_close_button_content_description"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"/>
+
<TextView
android:id="@+id/gesture_tutorial_fragment_feedback_title"
style="@style/TextAppearance.GestureTutorial.Feedback.Title"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"/>
+ android:layout_marginTop="16dp"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_close_button"/>
<TextView
android:id="@+id/gesture_tutorial_fragment_feedback_subtitle"
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_title"/>
+
+ <TextView
+ android:id="@+id/gesture_tutorial_fragment_feedback_tutorial_step"
+ style="@style/TextAppearance.GestureTutorial.Feedback.Subtext"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_fragment_action_button"
+ app:layout_constraintTop_toTopOf="@id/gesture_tutorial_fragment_action_button"
+ app:layout_constraintBottom_toBottomOf="@id/gesture_tutorial_fragment_action_button"/>
+
+ <!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
+ of elevation and shadow) which is replaced by ripple effect in android:foreground -->
+ <Button
+ android:id="@+id/gesture_tutorial_fragment_action_button"
+ style="@style/TextAppearance.GestureTutorial.ButtonLabel"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:background="@drawable/gesture_tutorial_action_button_background"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:stateListAnimator="@null"
+ android:visibility="invisible"
- <!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
- of elevation and shadow) which is replaced by ripple effect in android:foreground -->
- <Button
- android:id="@+id/gesture_tutorial_fragment_action_button"
- style="@style/TextAppearance.GestureTutorial.ButtonLabel"
- android:layout_width="142dp"
- android:layout_height="49dp"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true"
- android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
- android:layout_marginBottom="48dp"
- android:background="@drawable/gesture_tutorial_action_button_background"
- android:foreground="?android:attr/selectableItemBackgroundBorderless"
- android:stateListAnimator="@null"/>
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"/>
- <Button
- android:id="@+id/gesture_tutorial_fragment_action_text_button"
- style="@style/TextAppearance.GestureTutorial.TextButtonLabel"
- android:layout_width="142dp"
- android:layout_height="49dp"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
- android:layout_marginBottom="48dp"
- android:background="@null"
- android:foreground="?android:attr/selectableItemBackgroundBorderless"
- android:stateListAnimator="@null"/>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
</com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/task_menu.xml b/quickstep/res/layout/task_menu.xml
index 3916ff9..a219bca 100644
--- a/quickstep/res/layout/task_menu.xml
+++ b/quickstep/res/layout/task_menu.xml
@@ -16,7 +16,7 @@
-->
<com.android.quickstep.views.TaskMenuView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="@drawable/task_menu_bg"
@@ -35,12 +35,10 @@
<LinearLayout
android:id="@+id/menu_option_layout"
- style="@style/TaskMenu"
- android:divider="@drawable/all_apps_divider"
- android:showDividers="beginning"
- android:paddingStart="@dimen/task_card_menu_horizontal_padding"
- android:paddingEnd="@dimen/task_card_menu_horizontal_padding"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:divider="@drawable/all_apps_divider"
+ android:showDividers="beginning" />
</com.android.quickstep.views.TaskMenuView>
\ No newline at end of file
diff --git a/quickstep/res/layout/task_view_menu_option.xml b/quickstep/res/layout/task_view_menu_option.xml
index 102ae9b..a7d6e89 100644
--- a/quickstep/res/layout/task_view_menu_option.xml
+++ b/quickstep/res/layout/task_view_menu_option.xml
@@ -16,9 +16,8 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/TaskMenu.Option"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
android:orientation="vertical"
android:paddingTop="@dimen/task_card_menu_option_vertical_padding"
android:paddingBottom="@dimen/task_card_menu_option_vertical_padding"
@@ -29,22 +28,19 @@
android:id="@+id/icon"
android:layout_width="@dimen/system_shortcut_icon_size"
android:layout_height="@dimen/system_shortcut_icon_size"
- android:layout_marginTop="@dimen/system_shortcut_header_icon_padding"
- android:layout_marginBottom="@dimen/deep_shortcut_drawable_padding"
+ android:layout_marginStart="@dimen/task_menu_option_start_margin"
android:layout_gravity="center_horizontal"
android:backgroundTint="?android:attr/textColorTertiary"/>
<TextView
style="@style/BaseIcon"
android:id="@+id/text"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingBottom="@dimen/popup_padding_end"
+ android:layout_marginStart="@dimen/task_menu_option_start_margin"
android:textSize="12sp"
android:textColor="?android:attr/textColorPrimary"
android:fontFamily="sans-serif"
- android:gravity="center_horizontal"
- android:layout_gravity="center_horizontal"
android:focusable="false" />
</LinearLayout>
diff --git a/quickstep/res/raw/tips_nav_back_left.mp4 b/quickstep/res/raw/tips_nav_back_left.mp4
deleted file mode 100644
index f40b3b7..0000000
--- a/quickstep/res/raw/tips_nav_back_left.mp4
+++ /dev/null
Binary files differ
diff --git a/quickstep/res/raw/tips_nav_back_right.mp4 b/quickstep/res/raw/tips_nav_back_right.mp4
deleted file mode 100644
index 93841c7..0000000
--- a/quickstep/res/raw/tips_nav_back_right.mp4
+++ /dev/null
Binary files differ
diff --git a/quickstep/res/raw/tips_nav_home.mp4 b/quickstep/res/raw/tips_nav_home.mp4
deleted file mode 100644
index ce33df2..0000000
--- a/quickstep/res/raw/tips_nav_home.mp4
+++ /dev/null
Binary files differ
diff --git a/quickstep/res/raw/tips_nav_overview.mp4 b/quickstep/res/raw/tips_nav_overview.mp4
deleted file mode 100644
index 17f4b80..0000000
--- a/quickstep/res/raw/tips_nav_overview.mp4
+++ /dev/null
Binary files differ
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 6aed173..815ba04 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jou organisasie laat nie hierdie program toe nie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Slaan navigasietutoriaal oor?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Jy kan dit later in die <xliff:g id="NAME">%1$s</xliff:g>-program kry"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Kanselleer"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Slaan oor"</string>
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index dd4f76d..5a3df9d 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ይህ ድርጊት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"የአሰሳ አጋዥ ሥልጠናን ይዝለሉ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ይህን በኋላ በ<xliff:g id="NAME">%1$s</xliff:g> መተግበሪያው ውስጥ ማግኘት ይችላሉ"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ይቅር"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ዝለል"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index ee58f17..8205f89 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"هل تريد تخطي الدليل التوجيهي؟"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"يمكنك العثور على هذا الدليل التوجيهي لاحقًا في التطبيق <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"إلغاء"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"التخطي"</string>
</resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index be08f08..9b22c62 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"আজি <xliff:g id="TIME">%1$s</xliff:g> বাকী আছ"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"এপ চাজেশ্বন"</string>
<string name="all_apps_label" msgid="8542784161730910663">"সকলো এপ্"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"আপোনাৰ অনুমানিক এপ্"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"আপোনাৰ প্ৰয়োজন হ\'ব পৰা এপ্"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"আপোনাৰ গৃহ স্ক্ৰীনৰ একেবাৰে তলৰ শাৰীটোত এপৰ পৰামর্শসমূহ পাওক"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"আপোনাৰ গৃহ স্ক্ৰীনৰ প্ৰিয় সমলৰ শাৰীটোত এপৰ পৰামর্শসমূহ পাওক"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"আপোনাৰ সকলোতকৈ বেছিকৈ ব্যৱহৃত এপ্সমূহ গৃহ স্ক্ৰীনতে সহজে এক্সেছ কৰক। আপোনাৰ ৰুটিনসমূহৰ ভিত্তিত পৰামর্শসমূহ সলনি হ\'ব। একেবাৰে তলৰ শাৰীটোত থকা এপ্সমূহ ওপৰৰ আপোনাৰ গৃহ স্ক্ৰীনলৈ যাব।"</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এপ্টোৱে অথবা আপোনাৰ প্ৰতিষ্ঠানে এই কাৰ্যটোৰ অনুমতি নিদিয়ে"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশ্বনৰ টিউট’ৰিয়েল এৰিব বিচাৰে নেকি?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপুনি এয়া পাছত <xliff:g id="NAME">%1$s</xliff:g> এপ্টোত বিচাৰিব পাৰিব"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"বাতিল কৰক"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"এৰি যাওক"</string>
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 2c15eb0..bd88392 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekran şəkli"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu əməliyyata tətbiq və ya təşkilatınız tərəfindən icazə verilmir"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Naviqasiya dərsliyi ötürülsün?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu sonra <xliff:g id="NAME">%1$s</xliff:g> tətbiqində tapa bilərsiniz"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Ləğv edin"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ötürün"</string>
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 3d13a4d..21295fc 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili organizacija ne dozvoljavaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite da preskočite vodič za kretanje?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Možete da pronađete ovo kasnije u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Otkaži"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 930a296..d31468c 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Гэта дзеянне не дазволена праграмай ці вашай арганізацыяй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Прапусціць дапаможнік па навігацыі?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Знайсці дапаможнік можна ў праграме \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Скасаваць"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прапусціць"</string>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 3e8deda..d2554d5 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Това действие не е разрешено от приложението или организацията ви"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропускане на урока за навигиране?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Урокът е налице в приложението <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Отказ"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропускане"</string>
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index df706f9..48d2690 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশন টিউটোরিয়াল এড়িয়ে যেতে চান?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপনি <xliff:g id="NAME">%1$s</xliff:g> অ্যাপে পরে এটি খুঁজে পাবেন"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"বাতিল করুন"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"এড়িয়ে যান"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 5a99a14..18494a9 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ovu radnju ne dozvoljava aplikacija ili vaša organizacija"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Preskočiti vodič za navigiranje?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"To možete pronaći kasnije u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Otkaži"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index f7006b0..7c417ef 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'aplicació o la teva organització no permeten aquesta acció"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vols ometre el tutorial de navegació?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pots trobar-ho més tard a l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancel·la"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omet"</string>
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 23515ff..9d1b94e 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"dnes zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Návrhy aplikací"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Všechny aplikace"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Vaše předpovídané aplikace"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Návrhy aplikací pro vás"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Nechte si ve spodním řádku na ploše zobrazovat návrhy aplikací"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Nechte si na řádku oblíbených na ploše zobrazovat návrhy aplikací"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Mějte nejpoužívanější aplikace k dispozici přímo na ploše. Návrhy se budou měnit v závislosti na sledech činností. Aplikace ve spodním řádku se přesunou na vaši plochu."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikace nebo organizace zakazuje tuto akci"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Přeskočit výukový program k navigaci?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Program později najdete v aplikaci <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Zrušit"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Přeskočit"</string>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 8d1166b..42098dc 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller din organisation tillader ikke denne handling"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe selvstudiet for navigation over?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finde dette senere i appen <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annuller"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Spring over"</string>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index efee106..e7d9523 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -45,73 +45,40 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Funktion \"App-Vorschläge\" aktiviert"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Funktion \"App-Vorschläge\" deaktiviert"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Vorgeschlagene App: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for back_gesture_feedback_swipe_too_far_from_left_edge (340972404868601012) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_cancelled_left_edge (6671316150388702530) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_complete_left_edge (3220478647881674266) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_swipe_too_far_from_right_edge (4306700023773832353) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_cancelled_right_edge (4951916546256902552) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_complete (7261221999760772210) -->
- <skip />
- <!-- no translation found for back_gesture_feedback_swipe_in_nav_bar (1148198467090405643) -->
- <skip />
- <!-- no translation found for back_gesture_tutorial_confirm_subtitle (5181305411668713250) -->
- <skip />
- <!-- no translation found for back_gesture_intro_title (19551256430224428) -->
- <skip />
- <!-- no translation found for back_gesture_intro_subtitle (7912576483031802797) -->
- <skip />
- <!-- no translation found for home_gesture_feedback_swipe_too_far_from_edge (1446774096007065298) -->
- <skip />
- <!-- no translation found for home_gesture_feedback_overview_detected (1557523944897393013) -->
- <skip />
- <!-- no translation found for home_gesture_feedback_wrong_swipe_direction (6993979358080825438) -->
- <skip />
- <!-- no translation found for home_gesture_feedback_complete (2324789183070815517) -->
- <skip />
- <!-- no translation found for home_gesture_intro_title (836590312858441830) -->
- <skip />
- <!-- no translation found for home_gesture_intro_subtitle (2632238748497975326) -->
- <skip />
- <!-- no translation found for overview_gesture_feedback_swipe_too_far_from_edge (3032757898111577225) -->
- <skip />
- <!-- no translation found for overview_gesture_feedback_home_detected (1411130969354020489) -->
- <skip />
- <!-- no translation found for overview_gesture_feedback_wrong_swipe_direction (6725820500906747925) -->
- <skip />
- <!-- no translation found for overview_gesture_feedback_complete (5477014491632199169) -->
- <skip />
- <!-- no translation found for overview_gesture_intro_title (2902054412868489378) -->
- <skip />
- <!-- no translation found for overview_gesture_intro_subtitle (1579517193845186042) -->
- <skip />
- <!-- no translation found for gesture_tutorial_confirm_title (6201516182040074092) -->
- <skip />
- <!-- no translation found for gesture_tutorial_action_button_label_next (2556263116424738762) -->
- <skip />
- <!-- no translation found for gesture_tutorial_action_button_label_done (671834508127014231) -->
- <skip />
- <!-- no translation found for gesture_tutorial_action_button_label_settings (2923621047916486604) -->
- <skip />
- <!-- no translation found for gesture_tutorial_try_again (65962545858556697) -->
- <skip />
- <!-- no translation found for gesture_tutorial_nice (2936275692616928280) -->
- <skip />
- <!-- no translation found for gesture_tutorial_step (1279786122817620968) -->
- <skip />
+ <string name="back_gesture_feedback_swipe_too_far_from_left_edge" msgid="340972404868601012">"Wische vom äußersten linken Bildschirmrand."</string>
+ <string name="back_gesture_feedback_cancelled_left_edge" msgid="6671316150388702530">"Wische vom linken Bildschirmrand zur Bildschirmmitte und lass los."</string>
+ <string name="back_gesture_feedback_complete_left_edge" msgid="3220478647881674266">"Gut gemacht. Versuch es jetzt mal vom rechten Rand aus."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_right_edge" msgid="4306700023773832353">"Wische vom äußersten rechten Bildschirmrand."</string>
+ <string name="back_gesture_feedback_cancelled_right_edge" msgid="4951916546256902552">"Wische vom rechten Bildschirmrand zur Bildschirmmitte und lass los."</string>
+ <string name="back_gesture_feedback_complete" msgid="7261221999760772210">"Du hast die „Zurück“-Touch-Geste abgeschlossen. Nun lernst du, wie du zum Startbildschirm gelangst."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Wische nicht zu nah am unteren Bildschirmrand."</string>
+ <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Du kannst die Empfindlichkeit von „Zurück“ in den Einstellungen ändern"</string>
+ <string name="back_gesture_intro_title" msgid="19551256430224428">"Zum Zurückgehen wischen"</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Wenn du zum letzten Bildschirm zurückgehen möchtest, wische vom linken oder rechten Rand zur Mitte."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Wische vom unteren Bildschirmrand nach oben."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Achte darauf, nicht innezuhalten, bevor du loslässt."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Wische gerade nach oben."</string>
+ <string name="home_gesture_feedback_complete" msgid="2324789183070815517">"Du hast die „Startbildschirm“-Touch-Geste abgeschlossen. Als Nächstes lernst du, wie du zwischen Apps wechseln kannst."</string>
+ <string name="home_gesture_intro_title" msgid="836590312858441830">"Zum Startbildschirm gehen"</string>
+ <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Wenn du zum Startbildschirm gehen möchtest, wische einfach vom unteren Bildschirmrand nach oben."</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Wische vom unteren Bildschirmrand nach oben."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Versuche, das Fenster länger festzuhalten, bevor du es loslässt."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Wische gerade nach oben und halte dann inne."</string>
+ <string name="overview_gesture_feedback_complete" msgid="5477014491632199169">"Du hast die „Apps wechseln“-Touch-Geste abgeschlossen. Nun bist du bereit, dein Smartphone zu verwenden!"</string>
+ <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Zwischen Apps wechseln"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="1579517193845186042">"Wische auf dem Bildschirm von unten nach oben, halte ihn gedrückt und lass ihn dann los."</string>
+ <string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Fertig"</string>
+ <string name="gesture_tutorial_action_button_label_next" msgid="2556263116424738762">"Weiter"</string>
+ <string name="gesture_tutorial_action_button_label_done" msgid="671834508127014231">"Fertig"</string>
+ <string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Einstellungen"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Wiederholen"</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"Sehr gut!"</string>
+ <string name="gesture_tutorial_step" msgid="1279786122817620968">"Anleitung <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="action_share" msgid="2648470652637092375">"Teilen"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Die App oder deine Organisation lässt diese Aktion nicht zu"</string>
- <!-- no translation found for skip_tutorial_dialog_title (2725643161260038458) -->
- <skip />
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
- <!-- no translation found for gesture_tutorial_action_button_label_cancel (3809842569351264108) -->
- <skip />
- <!-- no translation found for gesture_tutorial_action_button_label_skip (394452764989751960) -->
- <skip />
+ <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigationstutorial überspringen?"</string>
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Das findest du später in der <xliff:g id="NAME">%1$s</xliff:g> App"</string>
+ <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Abbrechen"</string>
+ <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Überspringen"</string>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index baf1b87..21c2984 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Αυτή η ενέργεια δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Παράβλεψη οδηγού πλοήγησης;"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Βρείτε τον αργότερα στην εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Ακύρωση"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Παράβλεψη"</string>
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index a4cf4bd..478d1cd 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"La app o tu organización no permiten realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Omitir el instructivo de navegación?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes encontrarlo en la app de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancelar"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omitir"</string>
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 4dd7f02..454bea7 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"No puedes hacerlo porque la aplicación o tu organización no lo permiten"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Saltar tutorial de navegación?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes consultarlo en otro momento en la aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancelar"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Saltar"</string>
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index c0339b9..b729934 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Rakendus või teie organisatsioon on selle toimingu keelanud"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kas jätta navigeerimise õpetused vahele?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Leiate selle hiljem rakendusest <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Tühista"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Jäta vahele"</string>
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 7671e77..f6d3f23 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Atera pantaila-argazki bat"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikazioak edo erakundeak ez du eman ekintza hori gauzatzeko baimena"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Nabigazio-tutoriala saltatu nahi duzu?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tutorial hau <xliff:g id="NAME">%1$s</xliff:g> aplikazioan aurki dezakezu geroago"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Utzi"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Saltatu"</string>
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 60e31c5..8ca0f95 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"برنامه یا سازمان شما اجازه نمیدهد این کنش انجام شود."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"آموزش گامبهگام پیمایش رد شود؟"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"میتوانید آن را بعداً در برنامه <xliff:g id="NAME">%1$s</xliff:g> پیدا کنید"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"لغو"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"رد شدن"</string>
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 2f524b5..9ce7e6b 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Sovellus tai organisaatio ei salli tätä toimintoa"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ohitetaanko navigointiohje?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Löydät tämän myöhemmin sovelluksesta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Peru"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ohita"</string>
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 1277366..da73849 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'application ou votre organisation n\'autorise pas cette action"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel sur la navigation?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous trouverez le tutoriel dans l\'application <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annuler"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ignorer"</string>
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 5f9d6bb..b6abea7 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Cette action n\'est pas autorisée par l\'application ou par votre organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel de navigation ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous le retrouverez dans l\'appli <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annuler"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Passer"</string>
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index b158f31..9310d71 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"Tempo restante hoxe <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Suxestións de aplicacións"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Todas as aplicacións"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"As túas aplicacións preditas"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Previsión das túas aplicacións"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Recibe suxestións de aplicacións na fila inferior da pantalla de inicio"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Recibe suxestións de aplicacións na fila de Favoritos da pantalla de inicio"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accede facilmente desde a pantalla de inicio ás aplicacións que máis usas. As suxestións irán cambiando en función das túas rutinas. As aplicacións da fila inferior pasarán á pantalla de inicio."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"A aplicación ou a túa organización non permite realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Queres omitir o titorial de navegación?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Podes atopar isto máis tarde na aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancelar"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omitir"</string>
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 1ec2709..496d33b 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"તમે આને પછીથી <xliff:g id="NAME">%1$s</xliff:g> ઍપમાં જોઈ શકો છો"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"રદ કરો"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"છોડો"</string>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 51b8c13..a7711fe 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ऐप्लिकेशन या आपका संगठन इस कार्रवाई की अनुमति नहीं देता"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेविगेशन ट्यूटोरियल छोड़ना चाहते हैं?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"आप बाद में, <xliff:g id="NAME">%1$s</xliff:g> ऐप्लिकेशन पर इसे देख सकते हैं"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"अभी नहीं"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"छोड़ें"</string>
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 4b19eab..d5e4b9d 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili vaša organizacija ne dopuštaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite li preskočiti vodič za kretanje?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Kasnije ga možete pronaći u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Odustani"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
</resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 215023a..386ef3e 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Képernyőkép"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Az alkalmazás vagy az Ön szervezete nem engedélyezi ezt a műveletet"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kihagyja a navigáció bemutatóját?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ezt később megtalálhatja a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazásban"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Mégse"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Kihagyás"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index f9cf9eb..941bdb7 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Lewati tutorial navigasi?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda dapat menemukan tutorial ini di lain waktu di aplikasi <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Batal"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Lewati"</string>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 4e8cce7..6042b47 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Forritið eða fyrirtækið leyfir ekki þessa aðgerð"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Sleppa flettileiðsögn?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Þú getur fundið þetta síðar í forritinu <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Hætta við"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Sleppa"</string>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index a2877ac..6c81d17 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"Rimanente oggi: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"App suggerite"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Tutte le app"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Le app previste"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"App previste per te"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Visualizza app suggerite nella riga inferiore della schermata Home"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Visualizza app suggerite nella riga dei Preferiti della schermata Home"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accedi facilmente alle app più utilizzate direttamente dalla schermata Home. I suggerimenti varieranno in base alle tue routine. Le app nella riga inferiore verranno spostate più in alto sulla schermata Home."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Questa azione non è consentita dall\'app o dall\'organizzazione"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Saltare il tutorial di navigazione?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puoi trovarlo in un secondo momento nell\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annulla"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Salta"</string>
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 0532081..b77faeb 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"האפליקציה או הארגון שלך אינם מתירים את הפעולה הזאת"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"לדלג על המדריך לניווט?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ניתן למצוא את המדריך מאוחר יותר באפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ביטול"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"דילוג"</string>
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 87dbb95..1cbdf73 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"この操作はアプリまたは組織で許可されていません"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"操作チュートリアルをスキップしますか?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"これは後から <xliff:g id="NAME">%1$s</xliff:g> アプリで確認できます"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"キャンセル"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"スキップ"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index cdc70d6..5dd818d 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ეს მოქმედება არ არის დაშვებული აპის ან თქვენი ორგანიზაციის მიერ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"გსურთ, გამოტოვოთ ნავიგაციის სახელმძღვანელო?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ამის მოგვიანებით პოვნა <xliff:g id="NAME">%1$s</xliff:g> აპში შეგიძლიათ"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"გაუქმება"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"გამოტოვება"</string>
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index bd84c93..554d10d 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бұл әрекетке қолданба не ұйым рұқсат етпейді."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Қимылдар оқулығын өткізіп жіберу керек пе?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Мұны кейін <xliff:g id="NAME">%1$s</xliff:g> қолданбасынан таба аласыз."</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Бас тарту"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Өткізіп жіберу"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 31182b6..8fdba69 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"ಇಂದು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಉಳಿದಿದೆ"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"ಆ್ಯಪ್ ಸಲಹೆಗಳು"</string>
<string name="all_apps_label" msgid="8542784161730910663">"ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"ನಿಮ್ಮ ಸಂಭವನೀಯ ಆ್ಯಪ್ಗಳು"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"ನಿಮ್ಮ ಮುನ್ಸೂಚಿತ ಆ್ಯಪ್ಗಳು"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದ ಸಾಲಿನಲ್ಲಿ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನ ಮೆಚ್ಚಿನವುಗಳ ಸಾಲಿನಲ್ಲಿ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿಯೇ ನೀವು ಹೆಚ್ಚು ಬಳಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಸುಲಭವಾಗಿ ಪ್ರವೇಶಿಸಿ. ನಿಮ್ಮ ದಿನಚರಿಯನ್ನು ಆಧರಿಸಿ ಸಲಹೆಗಳು ಬದಲಾಗುತ್ತವೆ. ಕೆಳಭಾಗದ ಸಾಲಿನಲ್ಲಿನ ಆ್ಯಪ್ಗಳು ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಚಲಿಸುತ್ತವೆ."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಷನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಿ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್ನಲ್ಲಿ ಇದನ್ನು ನಂತರ ಕಾಣಬಹುದು"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ರದ್ದುಮಾಡಿ"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ಸ್ಕಿಪ್ ಮಾಡಿ"</string>
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 4138b0f..fbbddd6 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"이 작업은 앱 또는 조직에서 허용되지 않습니다."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"이동 방법 튜토리얼을 건너뛰시겠습니까?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"이 튜토리얼은 <xliff:g id="NAME">%1$s</xliff:g> 앱에서 다시 볼 수 있습니다"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"취소"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"건너뛰기"</string>
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 2ab089f..bd50eed 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бул аракетти аткарууга колдонмо же ишканаңыз тыюу салган"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Жаңсап өтүү үйрөткүчүн өт-рүп жибер-би?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Аны кийин <xliff:g id="NAME">%1$s</xliff:g> колдонмосунан табасыз"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Жокко чыгаруу"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Өтк-п жиберүү"</string>
</resources>
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
index 7cb01f6..668aea2 100644
--- a/quickstep/res/values-land/dimens.xml
+++ b/quickstep/res/values-land/dimens.xml
@@ -15,7 +15,5 @@
limitations under the License.
-->
<resources>
- <dimen name="task_card_menu_horizontal_padding">24dp</dimen>
-
<dimen name="overview_task_margin">8dp</dimen>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-land/styles.xml b/quickstep/res/values-land/styles.xml
deleted file mode 100644
index 0824b4f..0000000
--- a/quickstep/res/values-land/styles.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 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.
--->
-<resources>
- <!-- Task Menu layout styles. -->
- <style name="TaskMenu">
- <item name="android:orientation">horizontal</item>
- </style>
-
- <!-- Task Menu Option layout styles. -->
- <style name="TaskMenu.Option">
- <item name="android:layout_width">0dp</item>
- <item name="android:layout_weight">1</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 457db01..2f1db50 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jūsų organizacijoje arba naudojant šią programą neleidžiama atlikti šio veiksmo"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Praleisti naršymo mokymo programą?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tai galėsite rasti vėliau programoje „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Atšaukti"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Praleisti"</string>
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 2a117be..ce941bc 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lietotne vai jūsu organizācija neatļauj veikt šo darbību."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vai izlaist navigācijas mācības?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Varēsiet to vēlāk atrast lietotnē <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Atcelt"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Izlaist"</string>
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 120e63e..f9fd8b3 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликацијата или вашата организација не го дозволува дејствово"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Да се прескокне упатството за навигација?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ова може да го најдете подоцна во апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Откажи"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прескокни"</string>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index e8d7f4c..fc6bc82 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ഈ നടപടി എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"നാവിഗേഷൻ ട്യൂട്ടോറിയൽ ഒഴിവാക്കണോ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ആപ്പിൽ നിങ്ങൾക്ക് ഇത് പിന്നീട് കാണാനാകും"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"റദ്ദാക്കുക"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ഒഴിവാക്കുക"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 86237e1..48513eb 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Энэ үйлдлийг апп эсвэл танай байгууллага зөвшөөрдөггүй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Навигацын практик хичээлийг алгасах уу?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Та үүнийг дараа нь <xliff:g id="NAME">%1$s</xliff:g> аппаас олох боломжтой"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Цуцлах"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Алгасах"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index d31b03a..c576cf1 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"अॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्युटोरियल वगळायचे आहे का?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तुम्हाला हे नंतर <xliff:g id="NAME">%1$s</xliff:g> ॲपमध्ये मिळेल"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"रद्द करा"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"वगळा"</string>
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 6ec7a81..74b9d08 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak dibenarkan oleh apl atau organisasi anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Langkau tutorial navigasi?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda boleh mendapatkan tutorial ini kemudian dalam apl <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Batal"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Langkau"</string>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index d9c4cfb..919ad6e 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ဤလုပ်ဆောင်ချက်ကို အက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်ကို ကျော်မလား။"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"၎င်းကို နောက်မှ <xliff:g id="NAME">%1$s</xliff:g> အက်ပ်တွင် ရှာနိုင်သည်"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"မလုပ်တော့"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ကျော်ရန်"</string>
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 0b3117b..6e7e4a3 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisasjonen din tillater ikke denne handlingen"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du hoppe over navigeringsveiledning?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finne dette i <xliff:g id="NAME">%1$s</xliff:g>-appen senere"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Avbryt"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Hopp over"</string>
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 6d31422..99ad814 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"आज: <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"एपसम्बन्धी सुझावहरू"</string>
<string name="all_apps_label" msgid="8542784161730910663">"सबै एपहरू"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"तपाईंका पूर्वानुमानित एपहरू"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"तपाईंलाई चाहिने एपहरू"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"तपाईंको गृह स्क्रिनको पुछारको पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"आफ्नो होम स्क्रिनको मन पर्ने नामक पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू तपाईंको गृह स्क्रिनको सिरानमा सर्ने छन्।"</string>
@@ -108,8 +108,7 @@
<string name="blocked_by_policy" msgid="2071401072261365546">"यो एप वा तपाईंको सङ्गठनले यो कारबाही गर्ने अनुमति दिँदैन"</string>
<!-- no translation found for skip_tutorial_dialog_title (2725643161260038458) -->
<skip />
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तपाईं पछि <xliff:g id="NAME">%1$s</xliff:g> एपमा गई यो ट्युटोरियल भेट्टाउन सक्नुहुन्छ"</string>
<!-- no translation found for gesture_tutorial_action_button_label_cancel (3809842569351264108) -->
<skip />
<!-- no translation found for gesture_tutorial_action_button_label_skip (394452764989751960) -->
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index ecf22eb..be9329f 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Deze actie wordt niet toegestaan door de app of je organisatie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatietutorial overslaan?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Je vindt dit later terug in de app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annuleren"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Overslaan"</string>
</resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 08c22fc..8c36972 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ଆପ୍ କିମ୍ବା ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଏହି କାର୍ଯ୍ୟକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ନାଭିଗେସନ୍ ଟ୍ୟୁଟୋରିଆଲକୁ ବାଦ୍ ଦେବେ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ଆପଣ ପରେ ଏହାକୁ <xliff:g id="NAME">%1$s</xliff:g> ଆପରେ ପାଇପାରିବେ"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ବାଦ୍ ଦିଅନ୍ତୁ"</string>
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index d9fad16..227c060 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਕਾਰਵਾਈ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ਕੀ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਛੱਡਣਾ ਹੈ?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ਤੁਸੀਂ ਇਸਨੂੰ ਬਾਅਦ ਵਿੱਚ <xliff:g id="NAME">%1$s</xliff:g> ਐਪ ਵਿੱਚ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ਰੱਦ ਕਰੋ"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ਛੱਡੋ"</string>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 0df44ef..61d9b93 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Nie możesz wykonać tego działania, bo nie zezwala na to aplikacja lub Twoja organizacja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pominąć samouczek nawigacji?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Znajdziesz to później w aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Anuluj"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Pomiń"</string>
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 390596c..0feead7 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"Resta(m) <xliff:g id="TIME">%1$s</xliff:g> hoje."</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Sugestões de apps"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Todas as apps"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"As suas aplicações previstas"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"As suas apps previstas"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Obtenha sugestões de apps na última fila do ecrã principal"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Obtenha sugestões de apps na fila dos favoritos do ecrã principal"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Aceda facilmente às suas apps mais utilizadas, diretamente no ecrã principal. As sugestões mudam em função das suas rotinas. As apps na última fila passam para o ecrã principal."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Fazer captura de ecrã"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Esta ação não é permitida pela app ou a sua entidade."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorar o tutorial de navegação?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pode encontrar isto mais tarde na app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancelar"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ignorar"</string>
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 1252e60..f533bbc 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Essa ação não é permitida pelo app ou pela organização"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pular o tutorial de navegação?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Veja o tutorial mais tarde no app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Cancelar"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Pular"</string>
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 556acb5..37d2935 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Această acțiune nu este permisă de aplicație sau de organizația dvs."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Omiteți tutorialul de navigare?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Îl puteți găsi mai târziu în aplicația <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Anulați"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omiteți"</string>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 3039a9a..8d4c40a 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Это действие заблокировано приложением или организацией."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустить руководство по жестам?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Его можно найти в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\"."</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Отмена"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропустить"</string>
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 8ffb580..d526e13 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"මෙම ක්රියාව යෙදුම හෝ ඔබේ සංවිධානය මගින් ඉඩ නොදේ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"නිබන්ධනය සංචාලනය මඟ හරින්නද?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ඔබට මෙය පසුව <xliff:g id="NAME">%1$s</xliff:g> යෙදුම තුළ සොයා ගත හැකිය"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"අවලංගු කරන්න"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"මඟ හරින්න"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 86d0a8e..24a4ac9 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikácia alebo vaša organizácia túto akciu nepovoľuje"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Chcete preskočiť návod na navigáciu?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tento návod nájdete v aplikácii <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Zrušiť"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskočiť"</string>
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 0d1f015..fdc8a6a 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ali vaša organizacija ne dovoljuje tega dejanja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite preskočiti vadnico za krmarjenje?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"To lahko pozneje najdete v aplikaciji <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Prekliči"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index b50976f..36e0afc 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ky veprim nuk lejohet nga aplikacioni ose organizata jote"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Të kapërcehet udhëzuesi i navigimit?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Këtë mund ta gjesh më vonë tek aplikacioni <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Anulo"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Kapërce"</string>
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index c940c15..8a462f9 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликација или организација не дозвољавају ову радњу"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Желите да прескочите водич за кретање?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Можете да пронађете ово касније у апликацији <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Откажи"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прескочи"</string>
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index b72f102..bf69850 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisationen tillåter inte den här åtgärden"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vill du hoppa över självstudierna?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan hitta det här igen i <xliff:g id="NAME">%1$s</xliff:g>-appen"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Avbryt"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Hoppa över"</string>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 1f25cc9..089c95d 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ஆப்ஸோ உங்கள் நிறுவனமோ இந்த செயலை அனுமதிப்பதில்லை"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"வழிகாட்டுதல் பயிற்சியைத் தவிர்க்கவா?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ஆப்ஸில் பிறகு இதைக் கண்டறியலாம்"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ரத்துசெய்"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"தவிர்"</string>
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index d1e30a2..c73c83e 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్షాట్"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్ను స్కిప్ చేయాలా?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> యాప్లో మీరు తర్వాత కనుగొనవచ్చు"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"రద్దు చేయి"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"స్కిప్ చేయి"</string>
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 8ca076f..d706108 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"แอปหรือองค์กรของคุณไม่อนุญาตการดำเนินการนี้"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ข้ามบทแนะนำการนำทางไหม"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"คุณดูบทแนะนำนี้ได้ภายหลังในแอป <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ยกเลิก"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ข้าม"</string>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index be9dc95..5056481 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkilos na ito"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Laktawan ang tutorial sa pag-navigate?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Makikita mo ito sa <xliff:g id="NAME">%1$s</xliff:g> app sa ibang pagkakataon"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Kanselahin"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Laktawan"</string>
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 7df0136..a22247b 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekran görüntüsü"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Uygulamanız veya kuruluşunuz bu işleme izin vermiyor"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Gezinme eğitici içeriği atlansın mı?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu daha sonra <xliff:g id="NAME">%1$s</xliff:g> uygulamasında bulabilirsiniz"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"İptal"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Atla"</string>
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 6c11d95..c63cec4 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ця дія заборонена додатком або адміністратором організації"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустити посібник із навігації?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ви знайдете його пізніше в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Скасувати"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропустити"</string>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index bfcc897..5ce95ad 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"آپ اسے بعد میں <xliff:g id="NAME">%1$s</xliff:g> ایپ میں تلاش کر سکتے ہیں"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"منسوخ کریں"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"نظر انداز کریں"</string>
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 215125c..fc3ef3f 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ứng dụng hoặc tổ chức của bạn không cho phép thực hiện hành động này"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Bỏ qua phần hướng dẫn thao tác?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bạn có thể tìm lại phần hướng dẫn này trong ứng dụng <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Hủy"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Bỏ qua"</string>
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 22d8393..fe5e553d 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"今天还可使用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"应用建议"</string>
<string name="all_apps_label" msgid="8542784161730910663">"所有应用"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"您的预测应用"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"您可能想要使用的应用"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"在主屏幕底部获取应用建议"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"在主屏幕的收藏行获取应用建议"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"直接在主屏幕上轻松访问您最常用的应用。系统会根据您的日常安排提供不同的建议。最下面一排中的应用会向上移动到主屏幕中。"</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"该应用或您所在的单位不允许执行此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要跳过导航教程吗?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"您之后可以在“<xliff:g id="NAME">%1$s</xliff:g>”应用中找到此教程"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"取消"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"跳过"</string>
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index b6efec2..5522a67 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"應用程式或您的機構不允許此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"您之後可以在「<xliff:g id="NAME">%1$s</xliff:g>」應用程式找到這些說明"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"取消"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"略過"</string>
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 410e70a..20af2b4 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"擷取螢幕畫面"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"這個應用程式或貴機構不允許執行這個動作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"你之後可以在「<xliff:g id="NAME">%1$s</xliff:g>」應用程式找到這些說明"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"取消"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"略過"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 4df1a45..2ffaecf 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -30,7 +30,7 @@
<string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> esele namhlanje"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Iziphakamiso zohlelo lokusebenza"</string>
<string name="all_apps_label" msgid="8542784161730910663">"Zonke izinhlelo zokusebenza"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Izinhlelo zakho zokusebenza eziqagelwe"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Ama-app akho aqagelwe"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Thola iziphakamiso ze-app emgqeni ongezansi wesikrini sakho sasekhaya"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Thola iziphakamiso zohlelo lokusebenza kumugqa wezintandokazi Zesikrini sakho sasekhaya"</string>
<string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Finyelela kalula izinhlelo zakho zokusebenza ezisetshenziswa kakhulu khona kusikrini sasekhaya. Iziphakamiso zizoshintsha ngokususelwe kwimijikelezo yakho. Izinhlelo zokusebenza ezisemgqeni ongezansi zizoya phezulu kusikrini sakho sasekhaya."</string>
@@ -78,8 +78,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lesi senzo asivunyelwanga uhlelo lokusebenza noma inhlangano yakho"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Yeqa isifundo sokuzulazula?"</string>
- <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
- <skip />
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Lokhu ungakuthola kamuva ku-app ye-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Khansela"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Yeqa"</string>
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 99be502..9c0a083 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -67,7 +67,7 @@
in various configurations -->
<dimen name="task_card_menu_option_vertical_padding">8dp</dimen>
<dimen name="task_card_menu_shadow_height">3dp</dimen>
- <dimen name="task_card_menu_horizontal_padding">0dp</dimen>
+ <dimen name="task_menu_option_start_margin">12dp</dimen>
<!-- Copied from framework resource:
docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
<dimen name="multi_window_task_divider_size">10dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index eeb9e99..a0f1638 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -126,7 +126,7 @@
<!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is started too far from the edge. [CHAR LIMIT=100] -->
<string name="overview_gesture_feedback_swipe_too_far_from_edge">Make sure you swipe up from the bottom edge of the screen.</string>
- <!-- Feedback shown during interactive parts of Overview gesture tutorial when the Home gesture is detected. [CHAR LIMIT=100] -->
+ <!-- Feedback shown during interactive parts of Overview gesture tutorial when the Home gesture is detected. The window refers to the current app's window during the gesture. [CHAR LIMIT=100] -->
<string name="overview_gesture_feedback_home_detected">Try holding the window for longer before releasing.</string>
<!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is horizontal instead of vertical. [CHAR LIMIT=100] -->
<string name="overview_gesture_feedback_wrong_swipe_direction">Make sure you swipe straight up, then pause.</string>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 387d4ec..7c7d20a 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -15,16 +15,6 @@
limitations under the License.
-->
<resources>
- <!-- Task Menu layout styles. -->
- <style name="TaskMenu">
- <item name="android:orientation">vertical</item>
- </style>
-
- <!-- Task Menu Option layout styles. -->
- <style name="TaskMenu.Option">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">wrap_content</item>
- </style>
<style name="TextAppearance.GestureTutorial"
parent="android:TextAppearance.Material.Body1" />
@@ -57,6 +47,14 @@
<item name="android:lineHeight">42sp</item>
</style>
+ <style name="TextAppearance.GestureTutorial.Dialog.Title"
+ parent="TextAppearance.GestureTutorial.Feedback.Title">
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:lineHeight">32sp</item>
+ <item name="android:textSize">24sp</item>
+ </style>
+
<style name="TextAppearance.GestureTutorial.Feedback.Subtitle"
parent="TextAppearance.GestureTutorial">
<item name="android:gravity">start</item>
@@ -67,6 +65,21 @@
<item name="android:lineHeight">24sp</item>
</style>
+ <style name="TextAppearance.GestureTutorial.Dialog.Subtitle"
+ parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:fontFamily">google-sans-text</item>
+ <item name="android:letterSpacing">0.025</item>
+ <item name="android:lineHeight">20sp</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="TextAppearance.GestureTutorial.Feedback.Subtext"
+ parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
+ <item name="android:textSize">16sp</item>
+ <item name="android:textColor">#909090</item>
+ </style>
+
<style name="TextAppearance.GestureTutorial.ButtonLabel"
parent="TextAppearance.GestureTutorial.CallToAction">
<item name="android:gravity">center</item>
@@ -76,6 +89,11 @@
<item name="android:textAllCaps">false</item>
</style>
+ <style name="TextAppearance.GestureTutorial.CancelButtonLabel"
+ parent="TextAppearance.GestureTutorial.ButtonLabel">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
<style name="TextAppearance.GestureTutorial.TextButtonLabel"
parent="TextAppearance.GestureTutorial.ButtonLabel">
<item name="android:textColor">@color/gesture_tutorial_primary_color</item>
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index e771962..2b1b57c 100644
--- a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -17,17 +17,26 @@
package com.android.quickstep;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
+import android.hardware.display.DisplayManager;
import android.util.DisplayMetrics;
+import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
@@ -35,11 +44,11 @@
import com.android.launcher3.util.DisplayController;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class OrientationTouchTransformerTest {
@@ -284,11 +293,26 @@
}
private DisplayController.Info createDisplayInfo(ScreenSize screenSize, int rotation) {
+ Context context = RuntimeEnvironment.application;
+ Display display = spy(context.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY));
+
Point p = new Point(screenSize.mWidth, screenSize.mHeight);
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
- p = new Point(screenSize.mHeight, screenSize.mWidth);
+ p.set(screenSize.mHeight, screenSize.mWidth);
}
- return new DisplayController.Info(0, rotation, 0, p, p, p, null);
+
+ doReturn(rotation).when(display).getRotation();
+ doAnswer(i -> {
+ ((Point) i.getArgument(0)).set(p.x, p.y);
+ return null;
+ }).when(display).getRealSize(any(Point.class));
+ doAnswer(i -> {
+ ((Point) i.getArgument(0)).set(p.x, p.y);
+ ((Point) i.getArgument(1)).set(p.x, p.y);
+ return null;
+ }).when(display).getCurrentSizeRange(any(Point.class), any(Point.class));
+ return new DisplayController.Info(context, display);
}
private float generateTouchRegionHeight(ScreenSize screenSize, int rotation) {
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index 88079ae..fd93d98 100644
--- a/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/robolectric_tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -147,7 +147,7 @@
LauncherActivityInterface.INSTANCE);
tvs.setDp(mDeviceProfile);
- int launcherRotation = DisplayController.getDefaultDisplay(mContext).getInfo().rotation;
+ int launcherRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation;
if (mAppRotation < 0) {
mAppRotation = launcherRotation;
}
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 0524b21..7aae38c 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -19,13 +19,15 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_SIZE;
+import static com.android.launcher3.util.DisplayController.CHANGE_SIZE;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
+import android.app.ActivityOptions;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
@@ -37,6 +39,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.model.WellbeingModel;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
@@ -50,6 +53,7 @@
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SysUINavigationMode;
@@ -233,8 +237,9 @@
}
@Override
- public void onDisplayInfoChanged(DisplayController.Info info, int flags) {
- super.onDisplayInfoChanged(info, flags);
+ public void onDisplayInfoChanged(Context context, DisplayController.Info info,
+ int flags) {
+ super.onDisplayInfoChanged(context, info, flags);
if ((flags & CHANGE_SIZE) != 0) {
addTaskbarIfNecessary();
}
@@ -418,18 +423,38 @@
}
@Override
- public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
+ public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
ActivityOptionsWrapper activityOptions =
mAppTransitionManager.hasControlRemoteAppTransitionPermission()
? mAppTransitionManager.getActivityLaunchOptions(this, v)
- : super.getActivityLaunchOptions(v);
+ : super.getActivityLaunchOptions(v, item);
if (mLastTouchUpTime > 0) {
ActivityOptionsCompat.setLauncherSourceInfo(
activityOptions.options, mLastTouchUpTime);
}
+ addLaunchCookie(item, activityOptions.options);
return activityOptions;
}
+ /**
+ * Adds a new launch cookie for the activity launch of the given {@param info} if supported.
+ */
+ public void addLaunchCookie(ItemInfo info, ActivityOptions opts) {
+ if (info == null) {
+ return;
+ }
+ switch (info.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ // Fall through and continue if it's an app or shortcut
+ break;
+ default:
+ return;
+ }
+ opts.setLaunchCookie(ObjectWrapper.wrap(new Integer(info.id)));
+ }
+
public void setHintUserWillBeActive() {
addActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE);
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index b72cf39..fb67645 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -79,6 +79,7 @@
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.views.FloatingIconView;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskViewUtils;
@@ -86,6 +87,7 @@
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransactionApplier;
+import com.android.quickstep.views.FloatingWidgetView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
@@ -100,7 +102,9 @@
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
/**
* Manages the opening and closing app transitions from Launcher
@@ -160,6 +164,9 @@
private static final int MAX_NUM_TASKS = 5;
+ // Cross-fade duration between App Widget and App
+ private static final int WIDGET_CROSSFADE_DURATION_MILLIS = 125;
+
protected final BaseQuickstepLauncher mLauncher;
private final DragLayer mDragLayer;
@@ -172,6 +179,8 @@
private final float mClosingWindowTransY;
private final float mMaxShadowRadius;
+ private final StartingWindowListener mStartingWindowListener = new StartingWindowListener();
+
private DeviceProfile mDeviceProfile;
private RemoteAnimationProvider mRemoteAnimationProvider;
@@ -221,13 +230,9 @@
}
};
+ mStartingWindowListener.setTransitionManager(this);
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
- new IStartingWindowListener.Stub() {
- @Override
- public void onTaskLaunching(int taskId, int supportedType) {
- mTypeForTaskId.put(taskId, supportedType);
- }
- });
+ mStartingWindowListener);
}
}
@@ -351,6 +356,29 @@
}
}
+ private void composeWidgetLaunchAnimator(
+ @NonNull AnimatorSet anim,
+ @NonNull LauncherAppWidgetHostView v,
+ @NonNull RemoteAnimationTargetCompat[] appTargets,
+ @NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
+ @NonNull RemoteAnimationTargetCompat[] nonAppTargets) {
+ mLauncher.getStateManager().setCurrentAnimation(anim);
+
+ Rect windowTargetBounds = getWindowTargetBounds(appTargets, getRotationChange(appTargets));
+ anim.play(getOpeningWindowAnimatorsForWidget(v, appTargets, wallpaperTargets, nonAppTargets,
+ windowTargetBounds, areAllTargetsTranslucent(appTargets)));
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mLauncher.addOnResumeCallback(() ->
+ ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
+ mLauncher.getStateManager().getState().getDepth(
+ mLauncher)).start());
+ }
+ });
+ }
+
/**
* Return the window bounds of the opening target.
* In multiwindow mode, we need to get the final size of the opening app window target to help
@@ -459,32 +487,29 @@
alpha.setInterpolator(LINEAR);
launcherAnimator.play(alpha);
+ List<View> viewsToAnimate = new ArrayList<>();
+
Workspace workspace = mLauncher.getWorkspace();
- View currentPage = ((CellLayout) workspace.getChildAt(workspace.getCurrentPage()))
- .getShortcutsAndWidgets();
- View hotseat = mLauncher.getHotseat();
- View qsb = mLauncher.findViewById(R.id.search_container_all_apps);
+ workspace.getVisiblePages().forEach(
+ view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
- currentPage.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- qsb.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ viewsToAnimate.add(mLauncher.getHotseat());
+ // Add QSB
+ viewsToAnimate.add(mLauncher.findViewById(R.id.search_container_all_apps));
- launcherAnimator.play(ObjectAnimator.ofFloat(currentPage, View.TRANSLATION_Y, trans));
- launcherAnimator.play(ObjectAnimator.ofFloat(hotseat, View.TRANSLATION_Y, trans));
- launcherAnimator.play(ObjectAnimator.ofFloat(qsb, View.TRANSLATION_Y, trans));
+ viewsToAnimate.forEach(view -> {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ launcherAnimator.play(ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, trans));
+ });
// Pause page indicator animations as they lead to layer trashing.
mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
endListener = () -> {
- currentPage.setTranslationY(0);
- hotseat.setTranslationY(0);
- qsb.setTranslationY(0);
-
- currentPage.setLayerType(View.LAYER_TYPE_NONE, null);
- hotseat.setLayerType(View.LAYER_TYPE_NONE, null);
- qsb.setLayerType(View.LAYER_TYPE_NONE, null);
-
+ viewsToAnimate.forEach(view -> {
+ view.setTranslationY(0);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ });
mDragLayerAlpha.setValue(1f);
mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
};
@@ -566,7 +591,6 @@
// Set the crop here so we can calculate the corner radius below.
crop.set(left, top, right, bottom);
- RectF targetBounds = new RectF(windowTargetBounds);
RectF floatingIconBounds = new RectF();
RectF tmpRectF = new RectF();
Point tmpPos = new Point();
@@ -655,12 +679,8 @@
tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]);
tmpRectF.offset(mDx.value, mDy.value);
Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value);
- float windowTransX0 = tmpRectF.left - offsetX;
- float windowTransY0 = tmpRectF.top - offsetY;
- if (hasSplashScreen) {
- windowTransX0 -= crop.left * scale;
- windowTransY0 -= crop.top * scale;
- }
+ float windowTransX0 = tmpRectF.left - offsetX - crop.left * scale;
+ float windowTransY0 = tmpRectF.top - offsetY - crop.top * scale;
// Calculate the icon position.
floatingIconBounds.set(launcherIconBounds);
@@ -693,7 +713,7 @@
matrix.postTranslate(windowTransX0, windowTransY0);
}
- floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f,
+ floatingView.update(mIconAlpha.value, 255, floatingIconBounds, percent, 0f,
mWindowRadius.value * scale, true /* isOpening */);
builder.withMatrix(matrix)
.withWindowCrop(crop)
@@ -744,6 +764,112 @@
}
});
+ animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
+ return animatorSet;
+ }
+
+ private Animator getOpeningWindowAnimatorsForWidget(LauncherAppWidgetHostView v,
+ RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets,
+ RemoteAnimationTargetCompat[] nonAppTargets, Rect windowTargetBounds,
+ boolean appTargetsAreTranslucent) {
+ final RectF widgetBackgroundBounds = new RectF();
+ final Rect appWindowCrop = new Rect();
+ final Matrix matrix = new Matrix();
+
+ final float finalWindowRadius = mDeviceProfile.isMultiWindowMode
+ ? 0 : getWindowCornerRadius(mLauncher.getResources());
+ final FloatingWidgetView floatingView = FloatingWidgetView.getFloatingWidgetView(mLauncher,
+ v, widgetBackgroundBounds, windowTargetBounds, finalWindowRadius);
+ final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources())
+ ? floatingView.getInitialCornerRadius() : 0;
+
+ RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets,
+ wallpaperTargets, nonAppTargets, MODE_OPENING);
+ SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(floatingView);
+ openingTargets.addReleaseCheck(surfaceApplier);
+
+ AnimatorSet animatorSet = new AnimatorSet();
+ ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
+ appAnimator.setDuration(APP_LAUNCH_DURATION);
+ appAnimator.setInterpolator(LINEAR);
+ appAnimator.addListener(floatingView);
+ appAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ openingTargets.release();
+ }
+ });
+ floatingView.setFastFinishRunnable(animatorSet::end);
+
+ appAnimator.addUpdateListener(new MultiValueUpdateListener() {
+ float mAppWindowScale = 1;
+ final FloatProp mWidgetForegroundAlpha = new FloatProp(1 /* start */,
+ 0 /* end */, 0 /* delay */,
+ WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */, LINEAR);
+ final FloatProp mWidgetFallbackBackgroundAlpha = new FloatProp(0 /* start */,
+ 1 /* end */, 0 /* delay */, 75 /* duration */, LINEAR);
+ final FloatProp mPreviewAlpha = new FloatProp(0 /* start */, 1 /* end */,
+ WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* delay */,
+ WIDGET_CROSSFADE_DURATION_MILLIS / 2 /* duration */, LINEAR);
+ final FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius,
+ 0 /* start */, RADIUS_DURATION, LINEAR);
+ final FloatProp mCornerRadiusProgress = new FloatProp(0, 1, 0, RADIUS_DURATION, LINEAR);
+
+ // Window & widget background positioning bounds
+ final FloatProp mDx = new FloatProp(widgetBackgroundBounds.centerX(),
+ windowTargetBounds.centerX(), 0 /* delay */, APP_LAUNCH_CURVED_DURATION,
+ EXAGGERATED_EASE);
+ final FloatProp mDy = new FloatProp(widgetBackgroundBounds.centerY(),
+ windowTargetBounds.centerY(), 0 /* delay */, APP_LAUNCH_DURATION,
+ EXAGGERATED_EASE);
+ final FloatProp mWidth = new FloatProp(widgetBackgroundBounds.width(),
+ windowTargetBounds.width(), 0 /* delay */, APP_LAUNCH_DURATION,
+ EXAGGERATED_EASE);
+ final FloatProp mHeight = new FloatProp(widgetBackgroundBounds.height(),
+ windowTargetBounds.height(), 0 /* delay */, APP_LAUNCH_DURATION,
+ EXAGGERATED_EASE);
+
+ @Override
+ public void onUpdate(float percent) {
+ widgetBackgroundBounds.set(mDx.value - mWidth.value / 2f,
+ mDy.value - mHeight.value / 2f, mDx.value + mWidth.value / 2f,
+ mDy.value + mHeight.value / 2f);
+ // Set app window scaling factor to match widget background width
+ mAppWindowScale = widgetBackgroundBounds.width() / windowTargetBounds.width();
+ // Crop scaled app window to match widget
+ appWindowCrop.set(0 /* left */, 0 /* top */,
+ Math.round(windowTargetBounds.width()) /* right */,
+ Math.round(widgetBackgroundBounds.height() / mAppWindowScale) /* bottom */);
+ matrix.setTranslate(widgetBackgroundBounds.left, widgetBackgroundBounds.top);
+ matrix.postScale(mAppWindowScale, mAppWindowScale, widgetBackgroundBounds.left,
+ widgetBackgroundBounds.top);
+
+ SurfaceParams[] params = new SurfaceParams[appTargets.length];
+ float floatingViewAlpha = appTargetsAreTranslucent ? 1 - mPreviewAlpha.value : 1;
+ for (int i = appTargets.length - 1; i >= 0; i--) {
+ RemoteAnimationTargetCompat target = appTargets[i];
+ SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
+ if (target.mode == MODE_OPENING) {
+ floatingView.update(widgetBackgroundBounds, floatingViewAlpha,
+ mWidgetForegroundAlpha.value, mWidgetFallbackBackgroundAlpha.value,
+ mCornerRadiusProgress.value);
+ builder.withMatrix(matrix)
+ .withWindowCrop(appWindowCrop)
+ .withAlpha(mPreviewAlpha.value)
+ .withCornerRadius(mWindowRadius.value / mAppWindowScale);
+ }
+ params[i] = builder.build();
+ }
+ surfaceApplier.scheduleApply(params);
+ }
+ });
+
+ animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets));
+ return animatorSet;
+ }
+
+ private ObjectAnimator getBackgroundAnimator(RemoteAnimationTargetCompat[] appTargets) {
// When launching an app from overview that doesn't map to a task, we still want to just
// blur the wallpaper instead of the launcher surface as well
boolean allowBlurringLauncher = mLauncher.getStateManager().getState() != OVERVIEW;
@@ -761,9 +887,7 @@
}
});
}
-
- animatorSet.playTogether(appAnimator, backgroundRadiusAnim);
- return animatorSet;
+ return backgroundRadiusAnim;
}
/**
@@ -819,6 +943,7 @@
public void onActivityDestroyed() {
unregisterRemoteAnimations();
unregisterRemoteTransitions();
+ mStartingWindowListener.setTransitionManager(null);
SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
}
@@ -1126,9 +1251,13 @@
boolean launcherClosing =
launcherIsATargetWithMode(appTargets, MODE_CLOSING);
+ final boolean launchingFromWidget = mV instanceof LauncherAppWidgetHostView;
final boolean launchingFromRecents = isLaunchingFromRecents(mV, appTargets);
final boolean launchingFromTaskbar = mLauncher.isViewInTaskbar(mV);
- if (launchingFromRecents) {
+ if (launchingFromWidget) {
+ composeWidgetLaunchAnimator(anim, (LauncherAppWidgetHostView) mV, appTargets,
+ wallpaperTargets, nonAppTargets);
+ } else if (launchingFromRecents) {
composeRecentsLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets,
launcherClosing);
} else if (launchingFromTaskbar) {
@@ -1213,25 +1342,16 @@
alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION
: APP_LAUNCH_ALPHA_DOWN_DURATION;
- if (hasSplashScreen) {
- iconAlphaStart = 0;
+ iconAlphaStart = hasSplashScreen ? 0 : 1f;
- // TOOD: Share value from shell when available.
- final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
+ // TOOD: Share value from shell when available.
+ final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
- cropCenterXStart = windowTargetBounds.centerX();
- cropCenterYStart = windowTargetBounds.centerY();
+ cropCenterXStart = windowTargetBounds.centerX();
+ cropCenterYStart = windowTargetBounds.centerY();
- cropWidthStart = (int) windowIconSize;
- cropHeightStart = (int) windowIconSize;
- } else {
- iconAlphaStart = 1;
-
- cropWidthStart = cropHeightStart =
- Math.min(windowTargetBounds.width(), windowTargetBounds.height());
- cropCenterXStart = cropCenterYStart =
- Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY());
- }
+ cropWidthStart = (int) windowIconSize;
+ cropHeightStart = (int) windowIconSize;
cropWidthEnd = windowTargetBounds.width();
cropHeightEnd = windowTargetBounds.height();
@@ -1240,4 +1360,17 @@
cropCenterYEnd = windowTargetBounds.centerY();
}
}
+
+ private static class StartingWindowListener extends IStartingWindowListener.Stub {
+ private QuickstepTransitionManager mTransitionManager;
+
+ public void setTransitionManager(QuickstepTransitionManager transitionManager) {
+ mTransitionManager = transitionManager;
+ }
+
+ @Override
+ public void onTaskLaunching(int taskId, int supportedType) {
+ mTransitionManager.mTypeForTaskId.put(taskId, supportedType);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 249ef3a..59d0afa 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -158,11 +158,7 @@
* Sets the specified app target surface to apply the blur to.
*/
public void setSurfaceToApp(RemoteAnimationTargetCompat target) {
- if (target != null) {
- setSurface(target.leash);
- } else {
- setActivityStarted(mLauncher.isStarted());
- }
+ setSurface(target == null ? null : target.leash);
}
private void setSurface(SurfaceControlCompat surface) {
@@ -170,9 +166,6 @@
mSurface = surface;
if (surface != null) {
setDepth(mDepth);
- } else {
- // If there is no surface, then reset the ratio
- setDepth(0f);
}
}
}
@@ -192,8 +185,7 @@
@Override
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
PendingAnimation animation) {
- if (mSurface == null
- || config.hasAnimationFlag(SKIP_DEPTH_CONTROLLER)
+ if (config.hasAnimationFlag(SKIP_DEPTH_CONTROLLER)
|| mIgnoreStateChangesDuringMultiWindowAnimation) {
return;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index b4aa596..5ba1fe1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -15,12 +15,11 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.graphics.IconShape.getShape;
-
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
@@ -37,6 +36,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.graphics.IconPalette;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -58,9 +58,13 @@
private final DeviceProfile mDeviceProfile;
private final Paint mIconRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path mRingPath = new Path();
- private boolean mIsPinned = false;
- private final int mNormalizedIconRadius;
+ private final int mNormalizedIconSize;
+ private final Path mShapePath;
+ private final Matrix mTmpMatrix = new Matrix();
+
private final BlurMaskFilter mShadowFilter;
+
+ private boolean mIsPinned = false;
private int mPlateColor;
boolean mDrawForDrag = false;
@@ -75,24 +79,18 @@
public PredictedAppIcon(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDeviceProfile = ActivityContext.lookupContext(context).getDeviceProfile();
- mNormalizedIconRadius = IconNormalizer.getNormalizedCircleSize(getIconSize()) / 2;
+ mNormalizedIconSize = IconNormalizer.getNormalizedCircleSize(getIconSize());
int shadowSize = context.getResources().getDimensionPixelSize(
R.dimen.blur_size_thin_outline);
mShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.OUTER);
+ mShapePath = GraphicsUtils.getShapePath(mNormalizedIconSize);
}
@Override
public void onDraw(Canvas canvas) {
int count = canvas.save();
if (!mIsPinned) {
- boolean isBadged = false;
- if (getTag() instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
- isBadged = !Process.myUserHandle().equals(info.user)
- || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
- || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
- }
- drawEffect(canvas, isBadged);
+ drawEffect(canvas);
canvas.translate(getWidth() * RING_EFFECT_RATIO, getHeight() * RING_EFFECT_RATIO);
canvas.scale(1 - 2 * RING_EFFECT_RATIO, 1 - 2 * RING_EFFECT_RATIO);
}
@@ -161,33 +159,58 @@
}
private int getOutlineOffsetX() {
- return (getMeasuredWidth() / 2) - mNormalizedIconRadius;
+ return (getMeasuredWidth() - mNormalizedIconSize) / 2;
}
private int getOutlineOffsetY() {
if (mDisplay != DISPLAY_TASKBAR) {
return getPaddingTop() + mDeviceProfile.folderIconOffsetYPx;
}
- return (getMeasuredHeight() / 2) - mNormalizedIconRadius;
+ return (getMeasuredHeight() - mNormalizedIconSize) / 2;
}
- private void drawEffect(Canvas canvas, boolean isBadged) {
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ updateRingPath();
+ }
+
+ @Override
+ public void setTag(Object tag) {
+ super.setTag(tag);
+ updateRingPath();
+ }
+
+ private void updateRingPath() {
+ boolean isBadged = false;
+ if (getTag() instanceof WorkspaceItemInfo) {
+ WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
+ isBadged = !Process.myUserHandle().equals(info.user)
+ || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+ }
+
+ mRingPath.reset();
+ mTmpMatrix.setTranslate(getOutlineOffsetX(), getOutlineOffsetY());
+
+ mRingPath.addPath(mShapePath, mTmpMatrix);
+ if (isBadged) {
+ float outlineSize = mNormalizedIconSize * RING_EFFECT_RATIO;
+ float iconSize = getIconSize() * (1 - 2 * RING_EFFECT_RATIO);
+ float badgeSize = LauncherIcons.getBadgeSizeForIconSize((int) iconSize) + outlineSize;
+ float scale = badgeSize / mNormalizedIconSize;
+ mTmpMatrix.postTranslate(mNormalizedIconSize, mNormalizedIconSize);
+ mTmpMatrix.preScale(scale, scale);
+ mTmpMatrix.preTranslate(-mNormalizedIconSize, -mNormalizedIconSize);
+ mRingPath.addPath(mShapePath, mTmpMatrix);
+ }
+ }
+
+ private void drawEffect(Canvas canvas) {
// Don't draw ring effect if item is about to be dragged.
if (mDrawForDrag) {
return;
}
- mRingPath.reset();
- getShape().addToPath(mRingPath, getOutlineOffsetX(), getOutlineOffsetY(),
- mNormalizedIconRadius);
- if (isBadged) {
- float outlineSize = mNormalizedIconRadius * RING_EFFECT_RATIO * 2;
- float iconSize = getIconSize() * (1 - 2 * RING_EFFECT_RATIO);
- float badgeSize = LauncherIcons.getBadgeSizeForIconSize((int) iconSize) + outlineSize;
- float badgeInset = mNormalizedIconRadius * 2 - badgeSize;
- getShape().addToPath(mRingPath, getOutlineOffsetX() + badgeInset,
- getOutlineOffsetY() + badgeInset, badgeSize / 2);
-
- }
mIconRingPaint.setColor(RING_SHADOW_COLOR);
mIconRingPaint.setMaskFilter(mShadowFilter);
canvas.drawPath(mRingPath, mIconRingPaint);
@@ -249,8 +272,10 @@
*/
@Override
public void drawUnderItem(Canvas canvas) {
- getShape().drawShape(canvas, mIcon.getOutlineOffsetX(), mIcon.getOutlineOffsetY(),
- mIcon.mNormalizedIconRadius, mOutlinePaint);
+ canvas.save();
+ canvas.translate(mIcon.getOutlineOffsetX(), mIcon.getOutlineOffsetY());
+ canvas.drawPath(mIcon.mShapePath, mOutlinePaint);
+ canvas.restore();
}
/**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 9097c8b..0652d48 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -113,7 +113,7 @@
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
float splitPlaceholderAlpha = state.areElementsVisible(mLauncher, SPLIT_PLACHOLDER_VIEW) ?
- 0.7f : 0;
+ 0.85f : 0;
propertySetter.setFloat(mRecentsView.getSplitPlaceholder(), ALPHA_FLOAT,
splitPlaceholderAlpha, LINEAR);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java b/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java
deleted file mode 100644
index 1417995..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2018 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.launcher3.uioverrides;
-
-import static android.app.WallpaperManager.FLAG_SYSTEM;
-
-import android.annotation.TargetApi;
-import android.app.WallpaperColors;
-import android.app.WallpaperManager;
-import android.app.WallpaperManager.OnColorsChangedListener;
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.systemui.shared.system.TonalCompat;
-import com.android.systemui.shared.system.TonalCompat.ExtractionInfo;
-
-import java.util.ArrayList;
-
-@TargetApi(Build.VERSION_CODES.P)
-public class WallpaperColorInfo implements OnColorsChangedListener {
-
- private static final int MAIN_COLOR_LIGHT = 0xffdadce0;
- private static final int MAIN_COLOR_DARK = 0xff202124;
- private static final int MAIN_COLOR_REGULAR = 0xff000000;
-
- public static final MainThreadInitializedObject<WallpaperColorInfo> INSTANCE =
- new MainThreadInitializedObject<>(WallpaperColorInfo::new);
-
- private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
- private final WallpaperManager mWallpaperManager;
- private final TonalCompat mTonalCompat;
-
- private ExtractionInfo mExtractionInfo;
-
- private OnChangeListener[] mTempListeners = new OnChangeListener[0];
-
- private WallpaperColorInfo(Context context) {
- mWallpaperManager = context.getSystemService(WallpaperManager.class);
- mTonalCompat = new TonalCompat(context);
-
- mWallpaperManager.addOnColorsChangedListener(this, new Handler(Looper.getMainLooper()));
- update(mWallpaperManager.getWallpaperColors(FLAG_SYSTEM));
- }
-
- public int getMainColor() {
- return mExtractionInfo.mainColor;
- }
-
- public int getSecondaryColor() {
- return mExtractionInfo.secondaryColor;
- }
-
- public boolean isDark() {
- return mExtractionInfo.supportsDarkTheme;
- }
-
- public boolean supportsDarkText() {
- return mExtractionInfo.supportsDarkText;
- }
-
- public boolean isMainColorDark() {
- return mExtractionInfo.mainColor == MAIN_COLOR_DARK;
- }
-
- @Override
- public void onColorsChanged(WallpaperColors colors, int which) {
- if ((which & FLAG_SYSTEM) != 0) {
- update(colors);
- notifyChange();
- }
- }
-
- private void update(WallpaperColors wallpaperColors) {
- mExtractionInfo = mTonalCompat.extractDarkColors(wallpaperColors);
- }
-
- public void addOnChangeListener(OnChangeListener listener) {
- mListeners.add(listener);
- }
-
- public void removeOnChangeListener(OnChangeListener listener) {
- mListeners.remove(listener);
- }
-
- private void notifyChange() {
- // Create a new array to avoid concurrent modification when the activity destroys itself.
- mTempListeners = mListeners.toArray(mTempListeners);
- for (int i = mTempListeners.length - 1; i >= 0; --i) {
- final OnChangeListener listener = mTempListeners[i];
- if (listener != null) {
- listener.onExtractedColorsChanged(this);
- mTempListeners[i] = null;
- }
- }
- }
-
- public interface OnChangeListener {
- void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 4e03971..a81bdd5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -22,7 +22,9 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.util.Themes;
/**
* Definition for AllApps state
@@ -92,7 +94,7 @@
}
@Override
- public float getWorkspaceScrimAlpha(Launcher launcher) {
- return 1;
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index aa770d2..77c2611 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import android.content.Context;
+import android.graphics.Color;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -86,6 +87,11 @@
return 1f;
}
+ @Override
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Color.TRANSPARENT;
+ }
+
public static float[] getOverviewScaleAndOffsetForBackgroundState(
BaseDraggingActivity activity) {
return new float[] {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 30c07b0..135c478 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -29,6 +29,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.Themes;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -108,8 +109,8 @@
}
@Override
- public float getWorkspaceScrimAlpha(Launcher launcher) {
- return 1f;
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Themes.getAttrColor(launcher, R.attr.overviewScrimColor);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
index 53afd21..d36e76b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
/**
* State to indicate we are about to launch a recent task. Note that this state is only used when
@@ -39,6 +41,11 @@
}
@Override
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Themes.getAttrColor(launcher, R.attr.overviewScrimColor);
+ }
+
+ @Override
public float getVerticalProgress(Launcher launcher) {
// Don't move all apps shelf while quick-switching (just let it fade).
return 1f;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 74a253e..2d95ce2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -16,7 +16,7 @@
package com.android.launcher3.uioverrides.touchcontrollers;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
@@ -127,11 +127,11 @@
}
if (mFromState == NORMAL && mToState == HINT_STATE) {
- mNormalToHintOverviewScrimAnimator = ObjectAnimator.ofFloat(
+ mNormalToHintOverviewScrimAnimator = ObjectAnimator.ofArgb(
mLauncher.getScrimView(),
- VIEW_ALPHA,
- mFromState.getWorkspaceScrimAlpha(mLauncher),
- mToState.getWorkspaceScrimAlpha(mLauncher));
+ VIEW_BACKGROUND_COLOR,
+ mFromState.getWorkspaceScrimColor(mLauncher),
+ mToState.getWorkspaceScrimColor(mLauncher));
}
mStartedOverview = false;
mReachedOverview = false;
@@ -267,7 +267,7 @@
}
private float dpiFromPx(float pixels) {
- return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics());
+ return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics().densityDpi);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 77b0804..12de4a6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -232,8 +231,8 @@
// - OverviewScrim
PendingAnimation xAnim = new PendingAnimation((long) (mXRange * 2));
xAnim.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1], LINEAR);
- xAnim.setFloat(mLauncher.getScrimView(), VIEW_ALPHA,
- toState.getWorkspaceScrimAlpha(mLauncher), LINEAR);
+ xAnim.setViewBackgroundColor(mLauncher.getScrimView(),
+ toState.getWorkspaceScrimColor(mLauncher), LINEAR);
mXOverviewAnim = xAnim.createPlaybackController();
mXOverviewAnim.dispatchOnStart();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index 94a7442..3953e42 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -29,7 +29,7 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -143,10 +143,9 @@
if (tv != null) {
sysuiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
}
- mLauncher.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, sysuiFlags);
+ mLauncher.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, sysuiFlags);
} else {
- mLauncher.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, mOverviewPanel.hasLightBackground());
+ mLauncher.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
index c426329..b0d0b15 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
@@ -99,22 +99,34 @@
}
@Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ boolean intercept = super.onControllerInterceptTouchEvent(ev);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.TWO_BUTTON_NORMAL_NOT_OVERVIEW,
+ "2 button touch controller intercept touch? " + intercept);
+ }
+ return intercept;
+ }
+
+ @Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
- final LauncherState targetState;
if (mIsTransposed) {
boolean draggingFromNav =
mLauncher.getDeviceProfile().isSeascape() == isDragTowardPositive;
- targetState = draggingFromNav ? HINT_STATE_TWO_BUTTON : NORMAL;
+ return draggingFromNav ? HINT_STATE_TWO_BUTTON : NORMAL;
} else {
LauncherState startState = mStartState != null ? mStartState : fromState;
- targetState = isDragTowardPositive ^ (startState == OVERVIEW)
- ? HINT_STATE_TWO_BUTTON : NORMAL;
+ return isDragTowardPositive ^ (startState == OVERVIEW) ? HINT_STATE_TWO_BUTTON : NORMAL;
}
+ }
+
+ @Override
+ protected void onReinitToState(LauncherState newToState) {
+ super.onReinitToState(newToState);
if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.TWO_BUTTON_NORMAL_NOT_OVERVIEW, "Target state: " + targetState);
+ Log.d(TestProtocol.TWO_BUTTON_NORMAL_NOT_OVERVIEW, "onReinitToState: " + newToState);
}
- return targetState;
}
@Override
@@ -163,6 +175,9 @@
@Override
protected void onSwipeInteractionCompleted(LauncherState targetState) {
super.onSwipeInteractionCompleted(targetState);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.TWO_BUTTON_NORMAL_NOT_OVERVIEW, "Reached state: " + targetState);
+ }
if (!mIsTransposed) {
mContinuousTouchCount++;
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 7599234..61803aa 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -34,7 +34,7 @@
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
@@ -65,11 +65,14 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
+import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
import android.widget.Toast;
@@ -135,8 +138,11 @@
protected final BaseActivityInterface<S, T> mActivityInterface;
protected final InputConsumerProxy mInputConsumerProxy;
protected final ActivityInitListener mActivityInitListener;
+ private final Handler mHandler = new Handler();
// Callbacks to be made once the recents animation starts
private final ArrayList<Runnable> mRecentsAnimationStartCallbacks = new ArrayList<>();
+ private final OnScrollChangedListener mOnRecentsScrollListener = this::onRecentsViewScroll;
+
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
protected T mActivity;
@@ -144,6 +150,9 @@
protected Runnable mGestureEndCallback;
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
+ // One time flag set when onConsumerAboutToBeSwitched() is called, indicating that certain
+ // shared animations should not be canceled when this handler is invalidated
+ private boolean mConsumerIsSwitching;
private boolean mRecentsViewScrollLinked = false;
private static int getFlagForIndex(int index, String name) {
@@ -658,11 +667,10 @@
mRecentsAnimationController.setSplitScreenMinimized(swipeUpThresholdPassed);
if (swipeUpThresholdPassed) {
- mActivity.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, mRecentsView.hasLightBackground());
+ mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
} else {
mActivity.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, centermostTaskFlags);
+ UI_STATE_FULLSCREEN_TASK, centermostTaskFlags);
}
}
}
@@ -997,7 +1005,14 @@
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocity);
}
- private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
+ private int getLogGestureTaskIndex(@Nullable TaskView targetTask) {
+ return mRecentsView == null || targetTask == null
+ ? LOG_NO_OP_PAGE_INDEX
+ : mRecentsView.indexOfChild(targetTask);
+ }
+
+ private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask,
+ int pageIndex) {
StatsLogManager.EventEnum event;
switch (endTarget) {
case HOME:
@@ -1026,9 +1041,6 @@
// We probably never received an animation controller, skip logging.
return;
}
- int pageIndex = endTarget == LAST_TASK
- ? LOG_NO_OP_PAGE_INDEX
- : mRecentsView.getNextPage();
// TODO: set correct container using the pageIndex
logger.log(event);
}
@@ -1041,7 +1053,8 @@
interpolator, target, velocityPxPerMs));
}
- protected abstract HomeAnimationFactory createHomeAnimationFactory(long duration);
+ protected abstract HomeAnimationFactory createHomeAnimationFactory(
+ ArrayList<IBinder> launchCookies, long duration);
private final TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
@Override
@@ -1082,7 +1095,8 @@
final RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets != null
? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
: null;
- HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
+ HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(
+ runningTaskTarget.taskInfo.launchCookies, duration);
mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome()
&& runningTaskTarget != null
&& runningTaskTarget.taskInfo.pictureInPictureParams != null
@@ -1250,7 +1264,7 @@
HomeAnimationFactory homeAnimationFactory) {
RectFSpringAnim anim =
super.createWindowAnimationToHome(startProgress, homeAnimationFactory);
- anim.addOnUpdateListener((r, p) -> {
+ anim.addOnUpdateListener((v, r, p) -> {
updateSysUiFlags(Math.max(p, mCurrentShift.value));
});
anim.addAnimatorListener(new AnimationSuccessListener() {
@@ -1271,18 +1285,18 @@
}
public void onConsumerAboutToBeSwitched() {
+ mConsumerIsSwitching = true;
if (mActivity != null) {
// In the off chance that the gesture ends before Launcher is started, we should clear
// the callback here so that it doesn't update with the wrong state
mActivity.clearRunOnceOnStartCallback();
- resetLauncherListeners();
}
if (mGestureState.getEndTarget() != null && !mGestureState.isRunningAnimationToLauncher()) {
cancelCurrentAnimation();
} else {
mStateCallback.setStateOnUiThread(STATE_FINISH_WITH_NO_END);
- reset();
}
+ reset();
}
public boolean isCanceled() {
@@ -1293,13 +1307,14 @@
private void resumeLastTask() {
mRecentsAnimationController.finish(false /* toRecents */, null);
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
- doLogGesture(LAST_TASK, null);
+ doLogGesture(LAST_TASK, null, getLogGestureTaskIndex(null));
reset();
}
@UiThread
private void startNewTask() {
TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
+ int taskPageIndex = getLogGestureTaskIndex(taskToLaunch);
startNewTask(success -> {
if (!success) {
reset();
@@ -1308,7 +1323,7 @@
endLauncherTransitionController();
updateSysUiFlags(1 /* windowProgress == overview */);
}
- doLogGesture(NEW_TASK, taskToLaunch);
+ doLogGesture(NEW_TASK, taskToLaunch, taskPageIndex);
});
}
@@ -1342,27 +1357,38 @@
}
private void invalidateHandler() {
- if (!LIVE_TILE.get() || !mActivityInterface.isInLiveTileMode()
- || mGestureState.getEndTarget() != RECENTS) {
- mInputConsumerProxy.destroy();
- mTaskAnimationManager.setLiveTileCleanUpHandler(null);
+ if (!mConsumerIsSwitching) {
+ if (!LIVE_TILE.get() || !mActivityInterface.isInLiveTileMode()
+ || mGestureState.getEndTarget() != RECENTS) {
+ mInputConsumerProxy.destroy();
+ mTaskAnimationManager.setLiveTileCleanUpHandler(null);
+ }
+ endRunningWindowAnim(false /* cancel */);
+
+ if (mGestureEndCallback != null) {
+ mGestureEndCallback.run();
+ }
}
+
mInputConsumerProxy.unregisterCallback();
- endRunningWindowAnim(false /* cancel */);
-
- if (mGestureEndCallback != null) {
- mGestureEndCallback.run();
- }
-
mActivityInitListener.unregister();
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mActivityRestartListener);
mTaskSnapshot = null;
+ mHandler.post(() -> {
+ // Defer clearing the activity since invalidation can happen over multiple callbacks
+ // ie. invalidateHandlerWithLauncher()
+ mActivity = null;
+ mRecentsView = null;
+ });
}
private void invalidateHandlerWithLauncher() {
- endLauncherTransitionController();
+ if (!mConsumerIsSwitching) {
+ endLauncherTransitionController();
+ mRecentsView.onGestureAnimationEnd();
+ }
- mRecentsView.onGestureAnimationEnd();
+ mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener);
resetLauncherListeners();
}
@@ -1389,7 +1415,9 @@
mActivityInterface.onTransitionCancelled(wasVisible);
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
- mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ if (mActivity != null) {
+ mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ }
}
protected void switchToScreenshot() {
@@ -1485,7 +1513,8 @@
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
}
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
- doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
+ TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView();
+ doLogGesture(HOME, taskToLaunch, getLogGestureTaskIndex(taskToLaunch));
}
/**
@@ -1497,9 +1526,8 @@
SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome(
mSwipePipToHomeAnimator.getComponentName(),
mSwipePipToHomeAnimator.getDestinationBounds());
- mRecentsAnimationController.setFinishTaskBounds(
+ mRecentsAnimationController.setFinishTaskTransaction(
mSwipePipToHomeAnimator.getTaskId(),
- mSwipePipToHomeAnimator.getDestinationBounds(),
mSwipePipToHomeAnimator.getFinishTransaction());
mIsSwipingPipToHome = false;
}
@@ -1517,7 +1545,8 @@
}
SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
- doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView());
+ TaskView taskToLaunch = mRecentsView.getCurrentPageTaskView();
+ doLogGesture(RECENTS, taskToLaunch, getLogGestureTaskIndex(taskToLaunch));
reset();
}
@@ -1554,17 +1583,19 @@
mRecentsAnimationTargets.addReleaseCheck(applier));
});
- mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
- if (moveWindowWithRecentsScroll()) {
- updateFinalShift();
- }
- });
+ mRecentsView.addOnScrollChangedListener(mOnRecentsScrollListener);
runOnRecentsAnimationStart(() ->
mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
mRecentsAnimationTargets));
mRecentsViewScrollLinked = true;
}
+ private void onRecentsViewScroll() {
+ if (moveWindowWithRecentsScroll()) {
+ updateFinalShift();
+ }
+ }
+
protected void startNewTask(Consumer<Boolean> resultCallback) {
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (!mCanceled) {
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 147297a..7aa81d4 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -15,10 +15,12 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
+import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.SysUINavigationMode.getMode;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
@@ -28,9 +30,11 @@
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import android.animation.Animator;
+import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
@@ -51,6 +55,7 @@
import com.android.launcher3.taskbar.TaskbarController;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -344,15 +349,33 @@
}
/**
- * Called when the gesture ends and the animation starts towards the given target. No-op by
- * default, but subclasses can override to add an additional animation with the same duration.
+ * Called when the gesture ends and the animation starts towards the given target. Used to add
+ * an optional additional animation with the same duration.
*/
public @Nullable Animator getParallelAnimationToLauncher(
GestureState.GestureEndTarget endTarget, long duration) {
+ if (endTarget == RECENTS) {
+ ACTIVITY_TYPE activity = getCreatedActivity();
+ if (activity == null) {
+ return null;
+ }
+ STATE_TYPE state = stateFromGestureEndTarget(endTarget);
+ ScrimView scrimView = activity.getScrimView();
+ ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
+ getOverviewScrimColorForState(activity, state));
+ anim.setDuration(duration);
+ return anim;
+ }
return null;
}
/**
+ * Returns the color of the scrim behind overview when at rest in this state.
+ * Return {@link Color#TRANSPARENT} for no scrim.
+ */
+ protected abstract int getOverviewScrimColorForState(ACTIVITY_TYPE activity, STATE_TYPE state);
+
+ /**
* See {@link com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags}
* @param systemUiStateFlags The latest SystemUiStateFlags
*/
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 8168e88..9fa65d9 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -196,4 +196,9 @@
recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
rotationTouchHelper.getDisplayRotation());
}
+
+ @Override
+ protected int getOverviewScrimColorForState(RecentsActivity activity, RecentsState state) {
+ return state.getScrimColor(activity);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index ec1cc4a..9846ee7 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -38,6 +38,7 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -48,6 +49,7 @@
import android.view.SurfaceControl.Transaction;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
@@ -56,6 +58,7 @@
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsState;
+import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.TransformParams.BuilderProxy;
@@ -66,6 +69,7 @@
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
import java.util.UUID;
import java.util.function.Consumer;
@@ -124,7 +128,8 @@
}
@Override
- protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+ protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
+ long duration) {
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
Intent intent = new Intent(mGestureState.getHomeIntent());
@@ -298,7 +303,8 @@
}
@Override
- public void update(RectF currentRect, float progress, float radius) {
+ public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
+ float radius) {
if (mSurfaceControl != null) {
currentRect.roundOut(mTempRect);
Transaction t = new Transaction();
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 878f5c9..dffee7f 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -23,6 +23,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.Rect;
import android.view.MotionEvent;
@@ -271,11 +272,25 @@
public @Nullable Animator getParallelAnimationToLauncher(GestureEndTarget endTarget,
long duration) {
TaskbarController taskbarController = getTaskbarController();
+ Animator superAnimator = super.getParallelAnimationToLauncher(endTarget, duration);
if (taskbarController == null) {
- return null;
+ return superAnimator;
}
LauncherState toState = stateFromGestureEndTarget(endTarget);
- return taskbarController.createAnimToLauncher(toState, duration);
+ Animator taskbarAnimator = taskbarController.createAnimToLauncher(toState, duration);
+ if (superAnimator == null) {
+ return taskbarAnimator;
+ } else {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(superAnimator, taskbarAnimator);
+ return animatorSet;
+ }
+ }
+
+ @Override
+ protected int getOverviewScrimColorForState(BaseQuickstepLauncher launcher,
+ LauncherState state) {
+ return state.getWorkspaceScrimColor(launcher);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 311ac83..dd35d68 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -15,28 +15,51 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.Utilities.dpToPx;
+import static com.android.launcher3.Utilities.mapToRange;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
+import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.RectF;
+import android.os.IBinder;
import android.os.UserHandle;
import android.view.View;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.Workspace;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.DynamicResource;
+import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.views.FloatingIconView;
+import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.system.InputConsumerController;
+import java.util.ArrayList;
+
/**
* Temporary class to allow easier refactoring
*/
@@ -52,38 +75,47 @@
@Override
- protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+ protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
+ long duration) {
HomeAnimationFactory homeAnimFactory;
if (mActivity != null) {
- final TaskView runningTaskView = mRecentsView.getRunningTaskView();
- final View workspaceView;
- if (runningTaskView != null
- && !mIsSwipingPipToHome
- && runningTaskView.getTask().key.getComponent() != null) {
- workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
- runningTaskView.getTask().key.getComponent().getPackageName(),
- UserHandle.of(runningTaskView.getTask().key.userId));
- } else {
- workspaceView = null;
- }
- final RectF iconLocation = new RectF();
+ final View workspaceView = findWorkspaceView(launchCookies,
+ mRecentsView.getRunningTaskView());
boolean canUseWorkspaceView =
workspaceView != null && workspaceView.isAttachedToWindow();
- FloatingIconView floatingIconView = canUseWorkspaceView
- ? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
- true /* hideOriginal */, iconLocation, false /* isOpening */)
- : null;
mActivity.getRootView().setForceHideBackArrow(true);
mActivity.setHintUserWillBeActive();
if (canUseWorkspaceView) {
+ final ResourceProvider rp = DynamicResource.provider(mActivity);
+ final float transY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
+ float dpPerSecond = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp_per_s));
+ final float launcherAlphaMax =
+ rp.getFloat(R.dimen.swipe_up_launcher_alpha_max_progress);
+
+ RectF iconLocation = new RectF();
+ FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView,
+ true /* hideOriginal */, iconLocation, false /* isOpening */);
+
// We want the window alpha to be 0 once this threshold is met, so that the
// FolderIconView can be seen morphing into the icon shape.
float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
homeAnimFactory = new LauncherHomeAnimationFactory() {
+
+ // There is a delay in loading the icon, so we need to keep the window
+ // opaque until it is ready.
+ private boolean mIsFloatingIconReady = false;
+
+ private @Nullable ValueAnimator mBounceBackAnimator;
+
@Override
public RectF getWindowTargetRect() {
+ if (PROTOTYPE_APP_CLOSE.get()) {
+ // We want the target rect to be at this offset position, so that all
+ // launcher content can spring back upwards.
+ floatingIconView.setPositionOffsetY(transY);
+ }
return iconLocation;
}
@@ -92,17 +124,92 @@
anim.addAnimatorListener(floatingIconView);
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
floatingIconView.setFastFinishRunnable(anim::end);
+ if (PROTOTYPE_APP_CLOSE.get()) {
+ mBounceBackAnimator = bounceBackToRestingPosition();
+ // Use a spring to put drag layer translation back to 0.
+ anim.addAnimatorListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ floatingIconView.setPositionOffsetY(0);
+ mBounceBackAnimator.start();
+ }
+ });
+
+ Workspace workspace = mActivity.getWorkspace();
+ workspace.setPivotToScaleWithSelf(mActivity.getHotseat());
+ }
+ }
+
+ private ValueAnimator bounceBackToRestingPosition() {
+ DragLayer dl = mActivity.getDragLayer();
+ Workspace workspace = mActivity.getWorkspace();
+ Hotseat hotseat = mActivity.getHotseat();
+
+ final float startValue = transY;
+ final float endValue = 0;
+ // Ensures the velocity is always aligned with the direction.
+ float pixelPerSecond = Math.abs(dpPerSecond)
+ * Math.signum(endValue - transY);
+
+ ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
+ .setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
+ .setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
+ .setMinimumVisibleChange(1f)
+ .setStartValue(startValue)
+ .setEndValue(endValue)
+ .setStartVelocity(pixelPerSecond)
+ .build(dl, VIEW_TRANSLATE_Y);
+ springTransY.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dl.setTranslationY(0f);
+ dl.setAlpha(1f);
+ SCALE_PROPERTY.set(workspace, 1f);
+ SCALE_PROPERTY.set(hotseat, 1f);
+ }
+ });
+ return springTransY;
}
@Override
- public void update(RectF currentRect, float progress, float radius) {
- floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold,
- radius, false);
+ public boolean keepWindowOpaque() {
+ if (mIsFloatingIconReady || floatingIconView.isVisibleToUser()) {
+ mIsFloatingIconReady = true;
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void update(@Nullable AppCloseConfig config, RectF currentRect,
+ float progress, float radius) {
+ int fgAlpha = 255;
+ if (config != null && PROTOTYPE_APP_CLOSE.get()) {
+ DragLayer dl = mActivity.getDragLayer();
+ float translationY = config.getWorkspaceTransY();
+ dl.setTranslationY(translationY);
+
+ float alpha = mapToRange(progress, 0, launcherAlphaMax, 0, 1f, LINEAR);
+ dl.setAlpha(Math.min(alpha, 1f));
+
+ float scale = Math.min(1f, config.getWorkspaceScale());
+ SCALE_PROPERTY.set(mActivity.getWorkspace(), scale);
+ SCALE_PROPERTY.set(mActivity.getHotseat(), scale);
+ SCALE_PROPERTY.set(mActivity.getAppsView(), scale);
+
+ progress = config.getInterpolatedProgress();
+ fgAlpha = config.getFgAlpha();
+ }
+ floatingIconView.update(1f, fgAlpha, currentRect, progress,
+ windowAlphaThreshold, radius, false);
}
@Override
public void onCancel() {
floatingIconView.fastFinish();
+ if (mBounceBackAnimator != null) {
+ mBounceBackAnimator.cancel();
+ }
}
};
} else {
@@ -121,6 +228,37 @@
return homeAnimFactory;
}
+ /**
+ * Returns the associated view on the workspace matching one of the launch cookies, or the app
+ * associated with the running task.
+ */
+ @Nullable
+ private View findWorkspaceView(ArrayList<IBinder> launchCookies, TaskView runningTaskView) {
+ if (mIsSwipingPipToHome) {
+ // Disable if swiping to PIP
+ return null;
+ }
+ if (runningTaskView == null || runningTaskView.getTask() == null
+ || runningTaskView.getTask().key.getComponent() == null) {
+ // Disable if it's an invalid task
+ return null;
+ }
+
+ // Find the associated item info for the launch cookie (if available)
+ int launchCookieItemId = -1;
+ for (IBinder cookie : launchCookies) {
+ Integer itemId = ObjectWrapper.unwrap(cookie);
+ if (itemId != null) {
+ launchCookieItemId = itemId;
+ break;
+ }
+ }
+
+ return mActivity.getWorkspace().getFirstMatchForAppClose(launchCookieItemId,
+ runningTaskView.getTask().key.getComponent().getPackageName(),
+ UserHandle.of(runningTaskView.getTask().key.userId));
+ }
+
@Override
protected void finishRecentsControllerToHome(Runnable callback) {
mRecentsAnimationController.finish(
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 2a6e478..c47300c 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -92,7 +92,7 @@
};
private static final String TAG = "OrientationTouchTransformer";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
private static final int QUICKSTEP_ROTATION_UNINITIALIZED = -1;
@@ -163,6 +163,10 @@
void setNavigationMode(SysUINavigationMode.Mode newMode, Info info,
Resources newRes) {
+ if (DEBUG) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "setNavigationMode new: " + newMode
+ + " oldMode: " + mMode + " " + this);
+ }
if (mMode == newMode) {
return;
}
@@ -254,10 +258,18 @@
mCurrentDisplay = new CurrentDisplay(region.realSize, region.rotation);
OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
+ if (DEBUG) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "cached region: " + regionToKeep
+ + " mCurrentDisplay: " + mCurrentDisplay + " " + this);
+ }
if (regionToKeep == null) {
regionToKeep = createRegionForDisplay(region);
}
mSwipeTouchRegions.clear();
+ if (DEBUG) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "adding region: " + regionToKeep
+ + " mCurrentDisplay: " + mCurrentDisplay + " " + this);
+ }
mSwipeTouchRegions.put(mCurrentDisplay, regionToKeep);
updateAssistantRegions(regionToKeep);
}
@@ -273,7 +285,8 @@
private OrientationRectF createRegionForDisplay(Info display) {
if (DEBUG) {
- Log.d(TAG, "creating rotation region for: " + mCurrentDisplay.rotation);
+ Log.d(TAG, "creating rotation region for: " + mCurrentDisplay.rotation
+ + " with mode: " + mMode + " displayRotation: " + display.rotation);
}
Point size = display.realSize;
@@ -287,14 +300,19 @@
} else {
mAssistantLeftRegion.setEmpty();
mAssistantRightRegion.setEmpty();
+ int navbarSize = getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
+ if (DEBUG) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "else case mode: " + mMode
+ + " getNavbarSize: " + navbarSize + " rotation: " + rotation + " " + this);
+ }
switch (rotation) {
case Surface.ROTATION_90:
orientationRectF.left = orientationRectF.right
- - getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
+ - navbarSize;
break;
case Surface.ROTATION_270:
orientationRectF.right = orientationRectF.left
- + getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
+ + navbarSize;
break;
default:
orientationRectF.top = orientationRectF.bottom - touchHeight;
@@ -339,7 +357,7 @@
boolean touchInValidSwipeRegions(float x, float y) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_SWIPE_TO_HOME, "touchInValidSwipeRegions " + x + "," + y + " in "
- + mLastRectTouched);
+ + mLastRectTouched + " this: " + this);
}
if (mLastRectTouched != null) {
return mLastRectTouched.contains(x, y);
@@ -462,7 +480,8 @@
if (DEBUG) {
Log.d(TAG, "Transforming rotation due to forceTransform, "
+ "mCurrentRotation: " + mCurrentDisplay.rotation
- + "mRotation: " + mRotation);
+ + "mRotation: " + mRotation
+ + " this: " + this);
}
event.transform(mTmpMatrix);
return true;
@@ -473,9 +492,10 @@
if (DEBUG) {
Log.d(TAG, "original: " + event.getX() + ", " + event.getY()
- + " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
- + " rect: " + this + " forceTransform: " + forceTransform
- + " contains: " + contains(mTmpPoint[0], mTmpPoint[1]));
+ + " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
+ + " rect: " + this + " forceTransform: " + forceTransform
+ + " contains: " + contains(mTmpPoint[0], mTmpPoint[1])
+ + " this: " + this);
}
if (contains(mTmpPoint[0], mTmpPoint[1])) {
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 7c453e7..3b92779 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -37,6 +37,8 @@
import android.os.Looper;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -48,6 +50,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -56,7 +59,9 @@
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.views.ScrimView;
import com.android.quickstep.fallback.FallbackRecentsStateController;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsDragLayer;
@@ -86,6 +91,7 @@
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsDragLayer mDragLayer;
+ private ScrimView mScrimView;
private FallbackRecentsView mFallbackRecentsView;
private OverviewActionsView mActionsView;
@@ -103,6 +109,7 @@
inflateRootView(R.layout.fallback_recents_activity);
setContentView(getRootView());
mDragLayer = findViewById(R.id.drag_layer);
+ mScrimView = findViewById(R.id.scrim_view);
mFallbackRecentsView = findViewById(R.id.overview_panel);
mActionsView = findViewById(R.id.overview_actions_view);
@@ -161,6 +168,10 @@
return mDragLayer;
}
+ public ScrimView getScrimView() {
+ return mScrimView;
+ }
+
@Override
public <T extends View> T getOverviewPanel() {
return (T) mFallbackRecentsView;
@@ -177,9 +188,9 @@
}
@Override
- public ActivityOptionsWrapper getActivityLaunchOptions(final View v) {
+ public ActivityOptionsWrapper getActivityLaunchOptions(final View v, @Nullable ItemInfo item) {
if (!(v instanceof TaskView)) {
- return super.getActivityLaunchOptions(v);
+ return super.getActivityLaunchOptions(v, item);
}
final TaskView taskView = (TaskView) v;
@@ -266,7 +277,7 @@
setupViews();
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
- mFallbackRecentsView.hasLightBackground());
+ Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
ACTIVITY_TRACKER.handleCreate(this);
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 82e8a93..78da311 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -19,13 +19,13 @@
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import android.graphics.Rect;
import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.util.RunnableList;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -44,6 +44,8 @@
private boolean mUseLauncherSysBarFlags = false;
private boolean mSplitScreenMinimized = false;
+ private boolean mFinishRequested = false;
+ private RunnableList mPendingFinishCallbacks = new RunnableList();
public RecentsAnimationController(RecentsAnimationControllerCompat controller,
boolean allowMinimizeSplitScreen,
@@ -133,30 +135,36 @@
@UiThread
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
+ if (mFinishRequested) {
+ // If finishing, add to pending finish callbacks, otherwise, if finished, adding to the
+ // destroyed RunnableList will just trigger the callback to be called immediately
+ mPendingFinishCallbacks.add(callback);
+ return;
+ }
+
+ // Finish not yet requested
+ mFinishRequested = true;
mOnFinishedListener.accept(this);
+ mPendingFinishCallbacks.add(callback);
UI_HELPER_EXECUTOR.execute(() -> {
mController.finish(toRecents, sendUserLeaveHint);
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
- if (callback != null) {
- MAIN_EXECUTOR.execute(callback);
- }
+ MAIN_EXECUTOR.execute(mPendingFinishCallbacks::executeAllAndDestroy);
});
}
/**
- * Sets the final bounds on a Task. This is used by Launcher to notify the system that
- * animating Activity to PiP has completed and the associated task surface should be updated
- * accordingly. This should be called before `finish`
+ * Sets the final surface transaction on a Task. This is used by Launcher to notify the system
+ * that animating Activity to PiP has completed and the associated task surface should be
+ * updated accordingly. This should be called before `finish`
* @param taskId for which the leash should be updated
- * @param destinationBounds bounds of the final PiP window
* @param finishTransaction leash operations for the final transform.
*/
- public void setFinishTaskBounds(int taskId, Rect destinationBounds,
+ public void setFinishTaskTransaction(int taskId,
PictureInPictureSurfaceTransaction finishTransaction) {
UI_HELPER_EXECUTOR.execute(
- () -> mController.setFinishTaskBounds(taskId, destinationBounds,
- finishTransaction));
+ () -> mController.setFinishTaskTransaction(taskId, finishTransaction));
}
/**
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 23e35f6..ef09957 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -17,8 +17,8 @@
import static android.content.Intent.ACTION_USER_UNLOCKED;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_ALL;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_FRAME_DELAY;
+import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
+import static com.android.launcher3.util.DisplayController.CHANGE_FRAME_DELAY;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
@@ -54,6 +54,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
@@ -61,8 +62,8 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.DisplayHolder;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SettingsCache;
@@ -91,7 +92,7 @@
private final Context mContext;
private final SysUINavigationMode mSysUiNavMode;
- private final DisplayHolder mDisplayHolder;
+ private final DisplayController mDisplayController;
private final int mDisplayId;
private final RotationTouchHelper mRotationTouchHelper;
@@ -128,18 +129,27 @@
private boolean mIsUserSetupComplete;
public RecentsAnimationDeviceState(Context context) {
- this(context, DisplayController.getDefaultDisplay(context));
+ this(context, false);
}
- public RecentsAnimationDeviceState(Context context, DisplayHolder displayHolder) {
+ /**
+ * @param isInstanceForTouches {@code true} if this is the persistent instance being used for
+ * gesture touch handling
+ */
+ public RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches) {
mContext = context;
- mDisplayHolder = displayHolder;
+ mDisplayController = DisplayController.INSTANCE.get(context);
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
- mDisplayId = mDisplayHolder.getInfo().id;
+ mDisplayId = mDisplayController.getInfo().id;
mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
- runOnDestroy(() -> mDisplayHolder.removeChangeListener(this));
- mRotationTouchHelper = new RotationTouchHelper(context, mDisplayHolder);
- runOnDestroy(mRotationTouchHelper::destroy);
+ runOnDestroy(() -> mDisplayController.removeChangeListener(this));
+ mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context);
+ if (isInstanceForTouches) {
+ // rotationTouchHelper doesn't get initialized after being destroyed, so only destroy
+ // if primary TouchInteractionService instance needs to be destroyed.
+ mRotationTouchHelper.init();
+ runOnDestroy(mRotationTouchHelper::destroy);
+ }
// Register for user unlocked if necessary
mIsUserUnlocked = context.getSystemService(UserManager.class)
@@ -219,6 +229,7 @@
* Cleans up all the registered listeners and receivers.
*/
public void destroy() {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "destroying RADS", new Throwable());
for (Runnable r : mOnDestroyActions) {
r.run();
}
@@ -244,9 +255,9 @@
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
- mDisplayHolder.removeChangeListener(this);
- mDisplayHolder.addChangeListener(this);
- onDisplayInfoChanged(mDisplayHolder.getInfo(), CHANGE_ALL);
+ mDisplayController.removeChangeListener(this);
+ mDisplayController.addChangeListener(this);
+ onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
if (newMode == NO_BUTTON) {
mExclusionListener.register();
@@ -254,12 +265,12 @@
mExclusionListener.unregister();
}
- mNavBarPosition = new NavBarPosition(newMode, mDisplayHolder.getInfo());
+ mNavBarPosition = new NavBarPosition(newMode, mDisplayController.getInfo());
mMode = newMode;
}
@Override
- public void onDisplayInfoChanged(Info info, int flags) {
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
if (info.id != getDisplayId() || flags == CHANGE_FRAME_DELAY) {
// ignore displays that aren't running launcher and frame refresh rate changes
return;
@@ -556,11 +567,11 @@
}
if (mIsOneHandedModeEnabled || mIsSwipeToNotificationEnabled) {
- final Info displayInfo = mDisplayHolder.getInfo();
+ final Info displayInfo = mDisplayController.getInfo();
return (mRotationTouchHelper.touchInOneHandedModeRegion(ev)
&& displayInfo.rotation != Surface.ROTATION_90
&& displayInfo.rotation != Surface.ROTATION_270
- && displayInfo.metrics.densityDpi < DisplayMetrics.DENSITY_600);
+ && displayInfo.densityDpi < DisplayMetrics.DENSITY_600);
}
return false;
}
diff --git a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
index a1af77d..edc3ab2 100644
--- a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
@@ -17,6 +17,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
+
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.ArrayList;
@@ -97,6 +99,10 @@
}
public void release() {
+ if (ENABLE_SHELL_TRANSITIONS) {
+ mReleaseChecks.clear();
+ return;
+ }
if (mReleased) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 2cf3212..fd0de42 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -17,20 +17,22 @@
import static android.view.Surface.ROTATION_0;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_ALL;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_FRAME_DELAY;
+import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
+import static com.android.launcher3.util.DisplayController.CHANGE_FRAME_DELAY;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
import android.content.Context;
import android.content.res.Resources;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.DisplayController.DisplayHolder;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -43,10 +45,13 @@
SysUINavigationMode.NavigationModeChangeListener,
DisplayInfoChangeListener {
- private final OrientationTouchTransformer mOrientationTouchTransformer;
- private final DisplayHolder mDisplayHolder;
- private final SysUINavigationMode mSysUiNavMode;
- private final int mDisplayId;
+ public static final MainThreadInitializedObject<RotationTouchHelper> INSTANCE =
+ new MainThreadInitializedObject<>(RotationTouchHelper::new);
+
+ private OrientationTouchTransformer mOrientationTouchTransformer;
+ private DisplayController mDisplayController;
+ private SysUINavigationMode mSysUiNavMode;
+ private int mDisplayId;
private int mDisplayRotation;
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
@@ -117,25 +122,46 @@
*/
private boolean mInOverview;
private boolean mTaskListFrozen;
-
-
private final Context mContext;
- public RotationTouchHelper(Context context, DisplayHolder displayHolder) {
+ /**
+ * Keeps track of whether destroy has been called for this instance. Mainly used for TAPL tests
+ * where multiple instances of RotationTouchHelper are being created. b/177316094
+ */
+ private boolean mNeedsInit = true;
+
+ private RotationTouchHelper(Context context) {
mContext = context;
- mDisplayHolder = displayHolder;
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "RotationTouchHelper ctor init? " + mNeedsInit
+ + " " + this);
+ if (mNeedsInit) {
+ init();
+ }
+ }
+
+ public void init() {
+ if (!mNeedsInit) {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "Did not need init? " + " " + this);
+ return;
+ }
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "RotationTouchHelper init() " + this,
+ new Throwable());
+ mDisplayController = DisplayController.INSTANCE.get(mContext);
Resources resources = mContext.getResources();
- mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
- mDisplayId = mDisplayHolder.getInfo().id;
+ mSysUiNavMode = SysUINavigationMode.INSTANCE.get(mContext);
+ mDisplayId = mDisplayController.getInfo().id;
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
() -> QuickStepContract.getWindowCornerRadius(resources));
// Register for navigation mode changes
- onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(this));
+ SysUINavigationMode.Mode newMode = mSysUiNavMode.addModeChangeListener(this);
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "AddedModeChangeListener: " + this +
+ " currentMode: " + newMode);
+ onNavigationModeChanged(newMode);
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
- mOrientationListener = new OrientationEventListener(context) {
+ mOrientationListener = new OrientationEventListener(mContext) {
@Override
public void onOrientationChanged(int degrees) {
int newRotation = RecentsOrientedState.getRotationForUserDegreesRotated(degrees,
@@ -154,6 +180,7 @@
}
}
};
+ mNeedsInit = false;
}
private void setupOrientationSwipeHandler() {
@@ -176,9 +203,11 @@
* Cleans up all the registered listeners and receivers.
*/
public void destroy() {
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "destroying " + this);
for (Runnable r : mOnDestroyActions) {
r.run();
}
+ mNeedsInit = true;
}
public boolean isTaskListFrozen() {
@@ -201,7 +230,7 @@
return;
}
- mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayHolder.getInfo());
+ mOrientationTouchTransformer.createOrAddTouchRegion(mDisplayController.getInfo());
}
/**
@@ -223,11 +252,12 @@
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
- mDisplayHolder.removeChangeListener(this);
- mDisplayHolder.addChangeListener(this);
- onDisplayInfoChanged(mDisplayHolder.getInfo(), CHANGE_ALL);
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "nav mode changed: " + newMode);
+ mDisplayController.removeChangeListener(this);
+ mDisplayController.addChangeListener(this);
+ onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
- mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayHolder.getInfo(),
+ mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
mContext.getResources());
if (!mMode.hasGestures && newMode.hasGestures) {
setupOrientationSwipeHandler();
@@ -243,7 +273,7 @@
}
@Override
- public void onDisplayInfoChanged(Info info, int flags) {
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
if (info.id != mDisplayId|| flags == CHANGE_FRAME_DELAY) {
// ignore displays that aren't running launcher and frame refresh rate changes
return;
@@ -276,8 +306,8 @@
* Sets the gestural height.
*/
void setGesturalHeight(int newGesturalHeight) {
- mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDisplayHolder.getInfo(),
- mContext.getResources());
+ mOrientationTouchTransformer.setGesturalHeight(
+ newGesturalHeight, mDisplayController.getInfo(), mContext.getResources());
}
/**
@@ -293,7 +323,7 @@
}
private void enableMultipleRegions(boolean enable) {
- mOrientationTouchTransformer.enableMultipleRegions(enable, mDisplayHolder.getInfo());
+ mOrientationTouchTransformer.enableMultipleRegions(enable, mDisplayController.getInfo());
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getQuickStepStartingRotation());
if (enable && !mInOverview && !TestProtocol.sDisableSensorRotation) {
// Clear any previous state from sensor manager
@@ -356,7 +386,7 @@
* notifies system UI of the primary rotation the user is interacting with
*/
private void toggleSecondaryNavBarsForRotation() {
- mOrientationTouchTransformer.setSingleActiveRegion(mDisplayHolder.getInfo());
+ mOrientationTouchTransformer.setSingleActiveRegion(mDisplayController.getInfo());
notifySysuiOfCurrentRotation(mOrientationTouchTransformer.getCurrentActiveRotation());
}
@@ -374,4 +404,8 @@
pw.println(" displayRotation=" + getDisplayRotation());
mOrientationTouchTransformer.dump(pw);
}
+
+ public OrientationTouchTransformer getOrientationTouchTransformer() {
+ return mOrientationTouchTransformer;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index a8c09dc..0f34a72 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
import android.animation.Animator;
import android.content.Context;
@@ -26,6 +27,7 @@
import android.graphics.RectF;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.DeviceProfile;
@@ -35,7 +37,9 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.RectFSpringAnim2;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.TransformParams.BuilderProxy;
@@ -149,7 +153,10 @@
public void setAnimation(RectFSpringAnim anim) { }
- public void update(RectF currentRect, float progress, float radius) { }
+ public boolean keepWindowOpaque() { return false; }
+
+ public void update(@Nullable AppCloseConfig config, RectF currentRect, float progress,
+ float radius) { }
public void onCancel() { }
@@ -199,7 +206,14 @@
homeToWindowPositionMap.invert(windowToHomePositionMap);
windowToHomePositionMap.mapRect(startRect);
- RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
+ RectFSpringAnim anim;
+ if (PROTOTYPE_APP_CLOSE.get()) {
+ anim = new RectFSpringAnim2(startRect, targetRect, mContext,
+ mTaskViewSimulator.getCurrentCornerRadius(),
+ cropRectF.width() / 2f);
+ } else {
+ anim = new RectFSpringAnim(startRect, targetRect, mContext);
+ }
homeAnimationFactory.setAnimation(anim);
SpringAnimationRunner runner = new SpringAnimationRunner(
@@ -259,18 +273,26 @@
}
@Override
- public void onUpdate(RectF currentRect, float progress) {
+ public void onUpdate(@Nullable AppCloseConfig config, RectF currentRect, float progress) {
mHomeAnim.setPlayFraction(progress);
mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect);
mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL);
float cornerRadius = Utilities.mapRange(progress, mStartRadius, mEndRadius);
+ float alpha = getWindowAlpha(progress);
+ if (config != null && PROTOTYPE_APP_CLOSE.get()) {
+ alpha = config.getWindowAlpha();
+ cornerRadius = config.getCornerRadius();
+ }
+ if (mAnimationFactory.keepWindowOpaque()) {
+ alpha = 1f;
+ }
mTransformParams
- .setTargetAlpha(getWindowAlpha(progress))
+ .setTargetAlpha(alpha)
.setCornerRadius(cornerRadius);
-
mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
- mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
+ mAnimationFactory.update(config, currentRect, progress,
+ mMatrix.mapRadius(cornerRadius));
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index b6dad2d..c87cd17 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -86,6 +86,7 @@
@UiThread
public RecentsAnimationCallbacks startRecentsAnimation(GestureState gestureState,
Intent intent, RecentsAnimationCallbacks.RecentsAnimationListener listener) {
+ Log.d("b/186444448", "startRecentsAnimation");
// Notify if recents animation is still running
if (mController != null) {
String msg = "New recents animation started before old animation completed";
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index cbb2a66..a59ba51 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -209,7 +209,7 @@
// RecentsView never updates the display rotation until swipe-up so the value may
// be stale. Use the display value instead.
- int displayRotation = DisplayController.getDefaultDisplay(context).getInfo().rotation;
+ int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
tsv.getOrientationState().update(displayRotation, displayRotation);
tsv.setPreview(targets.apps[targets.apps.length - 1]);
@@ -437,7 +437,7 @@
// RecentsView never updates the display rotation until swipe-up so the value may
// be stale. Use the display value instead.
- int displayRotation = DisplayController.getDefaultDisplay(recentsView.getContext())
+ int displayRotation = DisplayController.INSTANCE.get(recentsView.getContext())
.getInfo().rotation;
tvs.getOrientationState().update(displayRotation, displayRotation);
@@ -500,23 +500,25 @@
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- recentsView.post(() -> {
- stateManager.moveToRestState();
- stateManager.reapplyState();
+ recentsView.finishRecentsAnimation(false /* toRecents */, () -> {
+ recentsView.post(() -> {
+ stateManager.moveToRestState();
+ stateManager.reapplyState();
+ });
});
}
};
} else {
AnimatorPlaybackController controller =
- stateManager.createAnimationToNewWorkspace(NORMAL,
- RECENTS_LAUNCH_DURATION);
+ stateManager.createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION);
controller.dispatchOnStart();
childStateAnimation = controller.getTarget();
launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- stateManager.goToState(NORMAL, false);
+ recentsView.finishRecentsAnimation(false /* toRecents */,
+ () -> stateManager.goToState(NORMAL, false));
}
};
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index e9d2eb4..4fc9770 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -149,6 +149,8 @@
@BinderThread
public void onInitialize(Bundle bundle) {
+ Log.d(TAG + " b/182478748", "TouchInteractionService.onInitialize: user="
+ + getUserId());
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
IPip pip = IPip.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_PIP));
@@ -298,7 +300,9 @@
// Everything else should be initialized in onUserUnlocked() below.
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
- mDeviceState = new RecentsAnimationDeviceState(this);
+ mDeviceState = new RecentsAnimationDeviceState(this, true);
+ Log.d(TestProtocol.NO_SWIPE_TO_HOME, "RADS OTT instance: " +
+ mDeviceState.getRotationTouchHelper().getOrientationTouchTransformer());
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
@@ -310,6 +314,8 @@
}
private void disposeEventHandlers() {
+ Log.d(TAG + " b/182478748", "TouchInteractionService.disposeEventHandlers: user="
+ + getUserId());
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
@@ -321,6 +327,8 @@
}
private void initInputMonitor() {
+ Log.d(TAG + " b/182478748", "TouchInteractionService.initInputMonitor: user="
+ + getUserId());
disposeEventHandlers();
if (TestProtocol.sDebugTracing) {
@@ -329,9 +337,11 @@
}
if (mDeviceState.isButtonNavMode()) {
+ Log.d(TAG + " b/182478748", "isButtonNav: user=" + getUserId());
return;
}
+ Log.d(TAG + " b/182478748", "create swipe-up input monitor: user=" + getUserId());
mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
mMainChoreographer, this::onInputEvent);
@@ -448,6 +458,7 @@
@Override
public void onDestroy() {
+ Log.d(TAG, "Touch service destroyed: user=" + getUserId());
sIsInitialized = false;
if (mDeviceState.isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
@@ -469,7 +480,7 @@
@Override
public IBinder onBind(Intent intent) {
- Log.d(TAG, "Touch service connected");
+ Log.d(TAG, "Touch service connected: user=" + getUserId());
return mMyBinder;
}
@@ -506,7 +517,8 @@
}
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
- if (mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
+ if (!mDeviceState.isOneHandedModeActive()
+ && mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_SWIPE_TO_HOME,
"TouchInteractionService.onInputEvent:isInSwipeUpTouchRegion");
@@ -535,8 +547,7 @@
InputConsumer.NO_OP, mInputMonitorCompat,
mDeviceState,
event);
- } else if (mDeviceState.canTriggerOneHandedAction(event)
- && !mDeviceState.isOneHandedModeActive()) {
+ } else if (mDeviceState.canTriggerOneHandedAction(event)) {
// Consume gesture event for triggering one handed feature.
mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
InputConsumer.NO_OP, mInputMonitorCompat);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index a4a7bd3..9d9ef94 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -43,7 +43,7 @@
SysUINavigationMode.Mode sysUINavigationMode = SysUINavigationMode.getMode(mActivity);
if (sysUINavigationMode == SysUINavigationMode.Mode.NO_BUTTON) {
NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
- DisplayController.getDefaultDisplay(mActivity).getInfo());
+ DisplayController.INSTANCE.get(mActivity).getInfo());
mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
true /* disableHorizontalSwipe */, navBarPosition,
null /* onInterceptTouch */, this);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 8962ec9..7067dbc 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCRIM_FADE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
@@ -95,5 +96,8 @@
setter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, state.isFullScreen() ? 1 : 0, LINEAR);
setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS,
state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()) ? 1f : 0f, LINEAR);
+
+ setter.setViewBackgroundColor(mActivity.getScrimView(), state.getScrimColor(mActivity),
+ config.getInterpolator(ANIM_WORKSPACE_SCRIM_FADE, LINEAR));
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java b/quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java
index a00015a..29c3dc8 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java
@@ -16,11 +16,8 @@
package com.android.quickstep.fallback;
import android.content.Context;
-import android.graphics.Rect;
import android.util.AttributeSet;
-import com.android.launcher3.R;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsActivity;
@@ -41,12 +38,4 @@
new FallbackNavBarTouchController(mActivity),
};
}
-
- @Override
- public void setInsets(Rect insets) {
- super.setInsets(insets);
- setBackground(insets.top == 0 || !mAllowSysuiScrims
- ? null
- : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim));
- }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index bbe279e..b3d6cfa 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -19,10 +19,13 @@
import static com.android.launcher3.uioverrides.states.OverviewModalTaskState.getOverviewScaleAndOffsetForModalState;
import android.content.Context;
+import android.graphics.Color;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.BaseState;
+import com.android.launcher3.util.Themes;
import com.android.quickstep.RecentsActivity;
/**
@@ -35,12 +38,13 @@
private static final int FLAG_FULL_SCREEN = BaseState.getFlag(2);
private static final int FLAG_OVERVIEW_ACTIONS = BaseState.getFlag(3);
private static final int FLAG_SHOW_AS_GRID = BaseState.getFlag(4);
+ private static final int FLAG_SCRIM = BaseState.getFlag(5);
public static final RecentsState DEFAULT = new RecentsState(0,
- FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID);
+ FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID | FLAG_SCRIM);
public static final RecentsState MODAL_TASK = new ModalState(1,
FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_MODAL
- | FLAG_SHOW_AS_GRID);
+ | FLAG_SHOW_AS_GRID | FLAG_SCRIM);
public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN);
public static final RecentsState HOME = new RecentsState(3, 0);
@@ -103,6 +107,14 @@
return hasFlag(FLAG_OVERVIEW_ACTIONS);
}
+ /**
+ * For this state, what color scrim should be drawn behind overview.
+ */
+ public int getScrimColor(RecentsActivity activity) {
+ return hasFlag(FLAG_SCRIM) ? Themes.getAttrColor(activity, R.attr.overviewScrimColor)
+ : Color.TRANSPARENT;
+ }
+
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
return new float[] { NO_SCALE, NO_OFFSET };
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 85ecab1..9c64794 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -116,7 +116,7 @@
R.dimen.device_locked_y_offset);
// Do not use DeviceProfile as the user data might be locked
- mDisplaySize = DisplayController.getDefaultDisplay(context).getInfo().realSize;
+ mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().realSize;
// Init states
mStateCallback = new MultiStateCallback(STATE_NAMES);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
index cd69cf1..d82d43d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
@@ -44,12 +44,10 @@
*/
public class OneHandedModeInputConsumer extends DelegateInputConsumer {
- private static final String TAG = "OneHandedModeInputConsumer";
private static final int ANGLE_MAX = 150;
private static final int ANGLE_MIN = 30;
private final Context mContext;
- private final DisplayController.DisplayHolder mDisplayHolder;
private final Point mDisplaySize;
private final RecentsAnimationDeviceState mDeviceState;
@@ -68,12 +66,11 @@
InputConsumer delegate, InputMonitorCompat inputMonitor) {
super(delegate, inputMonitor);
mContext = context;
- mDisplayHolder = DisplayController.getDefaultDisplay(mContext);
mDeviceState = deviceState;
mDragDistThreshold = context.getResources().getDimensionPixelSize(
R.dimen.gestures_onehanded_drag_threshold);
mSquaredSlop = Utilities.squaredTouchSlop(context);
- mDisplaySize = mDisplayHolder.getInfo().realSize;
+ mDisplaySize = DisplayController.INSTANCE.get(mContext).getInfo().realSize;
mNavBarSize = ResourceUtils.getNavbarSize(NAVBAR_BOTTOM_GESTURE_SIZE,
mContext.getResources());
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
index 7c293c3..957f776 100644
--- a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialController.java
@@ -32,33 +32,6 @@
}
@Override
- Integer getTitleStringId() {
- switch (mTutorialType) {
- case ASSISTANT:
- return R.string.assistant_gesture_tutorial_playground_title;
- case ASSISTANT_COMPLETE:
- return R.string.gesture_tutorial_confirm_title;
- }
- return null;
- }
-
- @Override
- Integer getSubtitleStringId() {
- if (mTutorialType == TutorialType.ASSISTANT) {
- return R.string.assistant_gesture_tutorial_playground_subtitle;
- }
- return null;
- }
-
- @Override
- Integer getActionButtonStringId() {
- if (mTutorialType == ASSISTANT_COMPLETE) {
- return R.string.gesture_tutorial_action_button_label_done;
- }
- return null;
- }
-
- @Override
public void onBackGestureAttempted(BackGestureResult result) {
switch (mTutorialType) {
case ASSISTANT:
@@ -96,14 +69,8 @@
break;
case ASSISTANT_COMPLETED:
hideFeedback(true);
- showRippleEffect(
- () -> {
- if (mTutorialFragment.isTutorialComplete()) {
- mTutorialFragment.changeController(ASSISTANT_COMPLETE);
- } else {
- mTutorialFragment.continueTutorial();
- }
- });
+ showRippleEffect(null);
+ showFeedback(R.string.assistant_gesture_tutorial_playground_subtitle);
break;
case ASSISTANT_NOT_STARTED_BAD_ANGLE:
showFeedback(R.string.assistant_gesture_feedback_swipe_not_diagonal);
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 300ca7d..c396eec 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -36,58 +36,24 @@
super(fragment, tutorialType);
}
- @Override
- Integer getTitleStringId() {
- switch (mTutorialType) {
- case RIGHT_EDGE_BACK_NAVIGATION:
- case LEFT_EDGE_BACK_NAVIGATION:
- return R.string.back_gesture_intro_title;
- case BACK_NAVIGATION_COMPLETE:
- return R.string.gesture_tutorial_confirm_title;
- }
- return null;
- }
-
- @Override
- Integer getSubtitleStringId() {
- switch (mTutorialType) {
- case RIGHT_EDGE_BACK_NAVIGATION:
- case LEFT_EDGE_BACK_NAVIGATION:
- return R.string.back_gesture_intro_subtitle;
- case BACK_NAVIGATION_COMPLETE:
- return R.string.back_gesture_tutorial_confirm_subtitle;
- }
- return null;
- }
-
- @Override
- Integer getActionButtonStringId() {
- if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
- return R.string.gesture_tutorial_action_button_label_done;
- }
- return null;
- }
-
- @Override
- Integer getActionTextButtonStringId() {
- if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
- return R.string.gesture_tutorial_action_button_label_settings;
- }
- return null;
- }
-
- @Override
- void onActionTextButtonClicked(View button) {
- mTutorialFragment.startSystemNavigationSetting();
- }
-
@Nullable
- @Override
public View getMockLauncherView() {
return null;
}
@Override
+ public Integer getIntroductionTitle() {
+ return mTutorialType == LEFT_EDGE_BACK_NAVIGATION
+ ? R.string.back_gesture_intro_title : null;
+ }
+
+ @Override
+ public Integer getIntroductionSubtitle() {
+ return mTutorialType == LEFT_EDGE_BACK_NAVIGATION
+ ? R.string.back_gesture_intro_subtitle : null;
+ }
+
+ @Override
public void onBackGestureAttempted(BackGestureResult result) {
switch (mTutorialType) {
case RIGHT_EDGE_BACK_NAVIGATION:
@@ -112,8 +78,7 @@
mFakeTaskView.setBackground(AppCompatResources.getDrawable(mContext,
R.drawable.sandbox_fake_google_search));
showRippleEffect(null);
- showFeedback(R.string.back_gesture_feedback_complete,
- mTutorialFragment::continueTutorial);
+ showFeedback(R.string.back_gesture_feedback_complete, true);
break;
case BACK_CANCELLED_FROM_RIGHT:
showFeedback(R.string.back_gesture_feedback_cancelled_right_edge);
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
index b3eb1c0..71d00f0 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
@@ -29,8 +29,8 @@
@Override
Integer getFeedbackVideoResId() {
return mTutorialType == TutorialType.RIGHT_EDGE_BACK_NAVIGATION
- ? R.raw.tips_nav_back_right
- : R.raw.tips_nav_back_left;
+ ? R.drawable.gesture_tutorial_back_right
+ : R.drawable.gesture_tutorial_back_left;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index ebb4bfc..c3b342b 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -41,8 +41,12 @@
private static final String KEY_TUTORIAL_STEPS = "tutorial_steps";
private Deque<TutorialType> mTutorialSteps;
+ private TutorialType mCurrentTutorialStep;
private TutorialFragment mFragment;
+ private int mCurrentStep;
+ private int mNumSteps;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -51,7 +55,10 @@
Bundle args = savedInstanceState == null ? getIntent().getExtras() : savedInstanceState;
mTutorialSteps = getTutorialSteps(args);
- mFragment = TutorialFragment.newInstance(mTutorialSteps.pop());
+ mCurrentStep = 1;
+ mNumSteps = mTutorialSteps.size();
+ mCurrentTutorialStep = mTutorialSteps.pop();
+ mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.commit();
@@ -89,6 +96,21 @@
return mTutorialSteps.isEmpty();
}
+ public int getCurrentStep() {
+ return mCurrentStep;
+ }
+
+ public int getNumSteps() {
+ return mNumSteps;
+ }
+
+ /**
+ * Closes the tutorial and this activity.
+ */
+ public void closeTutorial() {
+ mFragment.closeTutorial();
+ }
+
/**
* Replaces the current TutorialFragment, continuing to the next tutorial step if there is one.
*
@@ -99,17 +121,20 @@
mFragment.closeTutorial();
return;
}
- mFragment = TutorialFragment.newInstance(mTutorialSteps.pop());
+ mCurrentTutorialStep = mTutorialSteps.pop();
+ mFragment = TutorialFragment.newInstance(mCurrentTutorialStep);
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mFragment)
.runOnCommit(() -> mFragment.onAttachedToWindow())
.commit();
+ mCurrentStep++;
}
private String[] getTutorialStepNames() {
- String[] tutorialStepNames = new String[mTutorialSteps.size()];
+ String[] tutorialStepNames = new String[mTutorialSteps.size() + 1];
- int i = 0;
+ int i = 1;
+ tutorialStepNames[0] = mCurrentTutorialStep.name();
for (TutorialType tutorialStep : mTutorialSteps) {
tutorialStepNames[i++] = tutorialStep.name();
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index d0f21c2..2e580af 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep.interaction;
-import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
-
import android.annotation.TargetApi;
import android.graphics.PointF;
import android.os.Build;
@@ -34,30 +32,13 @@
}
@Override
- Integer getTitleStringId() {
- switch (mTutorialType) {
- case HOME_NAVIGATION:
- return R.string.home_gesture_intro_title;
- case HOME_NAVIGATION_COMPLETE:
- return R.string.gesture_tutorial_confirm_title;
- }
- return null;
+ public Integer getIntroductionTitle() {
+ return R.string.home_gesture_intro_title;
}
@Override
- Integer getSubtitleStringId() {
- if (mTutorialType == TutorialType.HOME_NAVIGATION) {
- return R.string.home_gesture_intro_subtitle;
- }
- return null;
- }
-
- @Override
- Integer getActionButtonStringId() {
- if (mTutorialType == HOME_NAVIGATION_COMPLETE) {
- return R.string.gesture_tutorial_action_button_label_done;
- }
- return null;
+ public Integer getIntroductionSubtitle() {
+ return R.string.home_gesture_intro_subtitle;
}
@Override
@@ -92,8 +73,9 @@
switch (result) {
case HOME_GESTURE_COMPLETED: {
animateFakeTaskViewHome(finalVelocity, null);
+ showActionButton();
showFeedback(R.string.home_gesture_feedback_complete,
- mTutorialFragment::continueTutorial);
+ true);
break;
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
index 31e0351..ebddc69 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
@@ -25,7 +25,7 @@
@Nullable
@Override
Integer getFeedbackVideoResId() {
- return R.raw.tips_nav_home;
+ return R.drawable.gesture_tutorial_home;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 66e6a0d..3c59ed3 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -43,30 +43,13 @@
}
@Override
- Integer getTitleStringId() {
- switch (mTutorialType) {
- case OVERVIEW_NAVIGATION:
- return R.string.overview_gesture_intro_title;
- case OVERVIEW_NAVIGATION_COMPLETE:
- return R.string.gesture_tutorial_confirm_title;
- }
- return null;
+ public Integer getIntroductionTitle() {
+ return R.string.overview_gesture_intro_title;
}
@Override
- Integer getSubtitleStringId() {
- if (mTutorialType == TutorialType.OVERVIEW_NAVIGATION) {
- return R.string.overview_gesture_intro_subtitle;
- }
- return null;
- }
-
- @Override
- Integer getActionButtonStringId() {
- if (mTutorialType == OVERVIEW_NAVIGATION_COMPLETE) {
- return R.string.gesture_tutorial_action_button_label_done;
- }
- return null;
+ public Integer getIntroductionSubtitle() {
+ return R.string.overview_gesture_intro_subtitle;
}
@Nullable
@@ -124,8 +107,7 @@
animset.start();
mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
onMotionPaused(true /*arbitrary value*/);
- showFeedback(R.string.overview_gesture_feedback_complete,
- mTutorialFragment::continueTutorial);
+ showFeedback(R.string.overview_gesture_feedback_complete, true);
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
case HOME_OR_OVERVIEW_CANCELLED:
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index c6213e3..86344ab 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -25,7 +25,7 @@
@Nullable
@Override
Integer getFeedbackVideoResId() {
- return R.raw.tips_nav_overview;
+ return R.drawable.gesture_tutorial_overview;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
index 3a6d434..4e4b81a 100644
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
@@ -17,8 +17,6 @@
import android.graphics.PointF;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.R;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
@@ -30,24 +28,6 @@
super(fragment, tutorialType);
}
- @Nullable
- @Override
- Integer getTitleStringId() {
- return R.string.sandbox_mode_title;
- }
-
- @Nullable
- @Override
- Integer getSubtitleStringId() {
- return R.string.sandbox_mode_subtitle;
- }
-
- @Nullable
- @Override
- Integer getActionButtonStringId() {
- return null;
- }
-
@Override
public void onBackGestureAttempted(BackGestureResult result) {
switch (result) {
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 8fc453d..1aa64fa 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -52,6 +52,7 @@
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.SwipeUpAnimationLogic;
import com.android.quickstep.SwipeUpAnimationLogic.RunningWindowAnim;
+import com.android.quickstep.util.AppCloseConfig;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -306,11 +307,12 @@
}
@Override
- public void update(RectF rect, float progress, float radius) {
+ public void update(@Nullable AppCloseConfig config, RectF rect, float progress,
+ float radius) {
mFakeIconView.setVisibility(View.VISIBLE);
mFakeIconView.update(rect, progress,
1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
- radius,
+ radius, 255,
false, /* isOpening */
mFakeIconView, mDp,
false /* isVerticalBarLayout */);
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index cbab4f9..6f82f85 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -16,19 +16,25 @@
package com.android.quickstep.interaction;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
+import android.util.Log;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
-import android.widget.VideoView;
import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources;
import com.android.launcher3.InvariantDeviceProfile;
@@ -41,6 +47,11 @@
abstract class TutorialController implements BackGestureAttemptCallback,
NavBarGestureAttemptCallback {
+ private static final String TAG = "TutorialController";
+
+ private static final String PIXEL_TIPS_APP_PACKAGE_NAME = "com.google.android.apps.tips";
+ private static final CharSequence DEFAULT_PIXEL_TIPS_APP_NAME = "Pixel Tips";
+
private static final int FEEDBACK_VISIBLE_MS = 2500;
private static final int FEEDBACK_ANIMATION_MS = 250;
private static final int RIPPLE_VISIBLE_MS = 300;
@@ -50,20 +61,19 @@
final Context mContext;
final ImageButton mCloseButton;
- final TextView mTitleTextView;
- final TextView mSubtitleTextView;
final ViewGroup mFeedbackView;
- final VideoView mFeedbackVideoView;
+ final ImageView mFeedbackVideoView;
final ImageView mFakeLauncherView;
final ClipIconView mFakeIconView;
final View mFakeTaskView;
final View mFakePreviousTaskView;
final View mRippleView;
final RippleDrawable mRippleDrawable;
- final Button mActionTextButton;
final Button mActionButton;
+ final TextView mTutorialStepView;
private final Runnable mHideFeedbackRunnable;
Runnable mHideFeedbackEndAction;
+ private final AlertDialog mSkipTutorialDialog;
TutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
mTutorialFragment = tutorialFragment;
@@ -72,9 +82,7 @@
RootSandboxLayout rootView = tutorialFragment.getRootView();
mCloseButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
- mCloseButton.setOnClickListener(button -> mTutorialFragment.closeTutorial());
- mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
- mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
+ mCloseButton.setOnClickListener(button -> showSkipTutorialDialog());
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
mFeedbackVideoView = rootView.findViewById(R.id.gesture_tutorial_feedback_video);
mFakeLauncherView = rootView.findViewById(R.id.gesture_tutorial_fake_launcher_view);
@@ -84,9 +92,10 @@
rootView.findViewById(R.id.gesture_tutorial_fake_previous_task_view);
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
mRippleDrawable = (RippleDrawable) mRippleView.getBackground();
- mActionTextButton =
- rootView.findViewById(R.id.gesture_tutorial_fragment_action_text_button);
mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
+ mTutorialStepView =
+ rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_tutorial_step);
+ mSkipTutorialDialog = createSkipTutorialDialog();
mHideFeedbackRunnable =
() -> mFeedbackView.animate()
@@ -95,30 +104,16 @@
.withEndAction(this::hideFeedbackEndAction).start();
}
+ private void showSkipTutorialDialog() {
+ if (mSkipTutorialDialog != null) {
+ mSkipTutorialDialog.show();
+ }
+ }
+
void setTutorialType(TutorialType tutorialType) {
mTutorialType = tutorialType;
}
- @Nullable
- Integer getTitleStringId() {
- return null;
- }
-
- @Nullable
- Integer getSubtitleStringId() {
- return null;
- }
-
- @Nullable
- Integer getActionButtonStringId() {
- return null;
- }
-
- @Nullable
- Integer getActionTextButtonStringId() {
- return null;
- }
-
@DrawableRes
protected int getMockLauncherResId() {
return R.drawable.default_sandbox_mock_launcher;
@@ -155,13 +150,39 @@
mFakeTaskView.animate().alpha(0).setListener(AnimationSuccessListener.forRunnable(r));
}
+ @StringRes
+ public Integer getIntroductionTitle() {
+ return null;
+ }
+
+ @StringRes
+ public Integer getIntroductionSubtitle() {
+ return null;
+ }
+
/**
* Show feedback reflecting a failed gesture attempt.
*
* @param subtitleResId Resource of the text to display.
**/
void showFeedback(int subtitleResId) {
- showFeedback(subtitleResId, null);
+ showFeedback(subtitleResId, false);
+ }
+
+ /**
+ * Show feedback reflecting a failed gesture attempt.
+ *
+ * @param showActionButton Whether the tutorial feedback's action button should be shown.
+ **/
+ void showFeedback(int subtitleResId, boolean showActionButton) {
+ showFeedback(subtitleResId, showActionButton ? () -> {} : null, showActionButton);
+ }
+
+ /**
+ * Show feedback reflecting a failed gesture attempt.
+ **/
+ void showFeedback(int subtitleResId, @Nullable Runnable successEndAction) {
+ showFeedback(subtitleResId, successEndAction, false);
}
/**
@@ -170,32 +191,73 @@
* @param successEndAction Non-null iff the gesture was successful; this is run after the
* feedback is shown (i.e. to go to the next step)
**/
- void showFeedback(int subtitleResId, @Nullable Runnable successEndAction) {
+ void showFeedback(
+ int subtitleResId, @Nullable Runnable successEndAction, boolean showActionButton) {
+ showFeedback(
+ successEndAction == null
+ ? R.string.gesture_tutorial_try_again
+ : R.string.gesture_tutorial_nice,
+ subtitleResId,
+ successEndAction,
+ showActionButton);
+ }
+ void showFeedback(
+ int titleResId,
+ int subtitleResId,
+ @Nullable Runnable successEndAction,
+ boolean showActionButton) {
if (mHideFeedbackEndAction != null) {
return;
}
- int visibleDuration = FEEDBACK_VISIBLE_MS;
- if (mTutorialFragment.getFeedbackVideoResId() != null) {
+ TextView title = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_title);
+ title.setText(titleResId);
+ TextView subtitle =
+ mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
+ subtitle.setText(subtitleResId);
+ if (showActionButton) {
+ showActionButton();
+ }
+ mHideFeedbackEndAction = successEndAction;
+
+ AnimatedVectorDrawable tutorialAnimation = mTutorialFragment.getTutorialAnimation();
+ if (tutorialAnimation != null) {
if (successEndAction == null) {
- if (mFeedbackVideoView.isPlaying()) {
- mFeedbackVideoView.seekTo(1);
- } else {
- mFeedbackVideoView.start();
+ if (tutorialAnimation.isRunning()) {
+ tutorialAnimation.reset();
}
+ tutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+
+ @Override
+ public void onAnimationStart(Drawable drawable) {
+ super.onAnimationStart(drawable);
+
+ mFeedbackView.setTranslationY(
+ -mFeedbackView.getHeight() - mFeedbackView.getTop());
+ mFeedbackView.setVisibility(View.VISIBLE);
+ mFeedbackView.animate()
+ .setDuration(FEEDBACK_ANIMATION_MS)
+ .translationY(0)
+ .start();
+ }
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ super.onAnimationEnd(drawable);
+
+ mFeedbackView.removeCallbacks(mHideFeedbackRunnable);
+ mFeedbackView.post(mHideFeedbackRunnable);
+
+ tutorialAnimation.unregisterAnimationCallback(this);
+ }
+ });
+
+ tutorialAnimation.start();
mFeedbackVideoView.setVisibility(View.VISIBLE);
- visibleDuration = mTutorialFragment.getFeedbackVideoDuration();
+ return;
} else {
mTutorialFragment.releaseFeedbackVideoView();
}
}
- TextView title = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_title);
- title.setText(successEndAction == null
- ? R.string.gesture_tutorial_try_again
- : R.string.gesture_tutorial_nice);
- TextView subtitle =
- mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
- subtitle.setText(subtitleResId);
- mHideFeedbackEndAction = successEndAction;
mFeedbackView.setTranslationY(-mFeedbackView.getHeight() - mFeedbackView.getTop());
mFeedbackView.setVisibility(View.VISIBLE);
mFeedbackView.animate()
@@ -203,7 +265,9 @@
.translationY(0)
.start();
mFeedbackView.removeCallbacks(mHideFeedbackRunnable);
- mFeedbackView.postDelayed(mHideFeedbackRunnable, visibleDuration);
+ if (!showActionButton) {
+ mFeedbackView.postDelayed(mHideFeedbackRunnable, FEEDBACK_VISIBLE_MS);
+ }
}
void hideFeedback(boolean releaseFeedbackVideo) {
@@ -239,16 +303,14 @@
}
void onActionButtonClicked(View button) {
- mTutorialFragment.closeTutorial();
+ mTutorialFragment.continueTutorial();
}
- void onActionTextButtonClicked(View button) {}
-
@CallSuper
void transitToController() {
hideFeedback(false);
- updateTitles();
- updateActionButtons();
+ hideActionButton();
+ updateSubtext();
updateDrawables();
if (mFakeLauncherView != null) {
@@ -256,39 +318,33 @@
}
}
- private void updateTitles() {
- updateTitleView(mTitleTextView, getTitleStringId(),
- R.style.TextAppearance_GestureTutorial_Title);
- updateTitleView(mSubtitleTextView, getSubtitleStringId(),
- R.style.TextAppearance_GestureTutorial_Subtitle);
+ void hideActionButton() {
+ // Invisible to maintain the layout.
+ mActionButton.setVisibility(View.INVISIBLE);
+ mActionButton.setOnClickListener(null);
}
- private void updateTitleView(TextView textView, @Nullable Integer stringId, int styleId) {
- if (stringId == null) {
- textView.setVisibility(View.GONE);
- return;
+ void showActionButton() {
+ int stringResId = -1;
+
+ if (mContext instanceof GestureSandboxActivity) {
+ GestureSandboxActivity sandboxActivity = (GestureSandboxActivity) mContext;
+
+ stringResId = sandboxActivity.isTutorialComplete()
+ ? R.string.gesture_tutorial_action_button_label_done
+ : R.string.gesture_tutorial_action_button_label_next;
}
- textView.setVisibility(View.VISIBLE);
- textView.setText(stringId);
- textView.setTextAppearance(styleId);
+ mActionButton.setText(stringResId == -1 ? null : mContext.getString(stringResId));
+ mActionButton.setVisibility(View.VISIBLE);
+ mActionButton.setOnClickListener(this::onActionButtonClicked);
}
- private void updateActionButtons() {
- updateButton(mActionButton, getActionButtonStringId(), this::onActionButtonClicked);
- updateButton(
- mActionTextButton, getActionTextButtonStringId(), this::onActionTextButtonClicked);
- }
-
- private void updateButton(Button button, @Nullable Integer stringId, OnClickListener listener) {
- if (stringId == null) {
- button.setVisibility(View.INVISIBLE);
- return;
- }
-
- button.setVisibility(View.VISIBLE);
- button.setText(stringId);
- button.setOnClickListener(listener);
+ private void updateSubtext() {
+ mTutorialStepView.setText(mContext.getString(
+ R.string.gesture_tutorial_step,
+ mTutorialFragment.getCurrentStep(),
+ mTutorialFragment.getNumSteps()));
}
private void updateDrawables() {
@@ -309,11 +365,67 @@
}
}
- private boolean isComplete() {
- return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
- || mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
- || mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
- || mTutorialType == TutorialType.ASSISTANT_COMPLETE;
+ private AlertDialog createSkipTutorialDialog() {
+ if (mContext instanceof GestureSandboxActivity) {
+ GestureSandboxActivity sandboxActivity = (GestureSandboxActivity) mContext;
+ View contentView = View.inflate(
+ sandboxActivity, R.layout.gesture_tutorial_dialog, null);
+ AlertDialog tutorialDialog = new AlertDialog
+ .Builder(sandboxActivity, R.style.Theme_AppCompat_Dialog_Alert)
+ .setView(contentView)
+ .create();
+
+ PackageManager packageManager = mContext.getPackageManager();
+ CharSequence tipsAppName = DEFAULT_PIXEL_TIPS_APP_NAME;
+
+ try {
+ tipsAppName = packageManager.getApplicationLabel(
+ packageManager.getApplicationInfo(
+ PIXEL_TIPS_APP_PACKAGE_NAME, PackageManager.GET_META_DATA));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG,
+ "Could not find app label for package name: "
+ + PIXEL_TIPS_APP_PACKAGE_NAME
+ + ". Defaulting to 'Pixel Tips.'",
+ e);
+ }
+
+ TextView subtitleTextView = (TextView) contentView.findViewById(
+ R.id.gesture_tutorial_dialog_subtitle);
+ if (subtitleTextView != null) {
+ subtitleTextView.setText(
+ mContext.getString(R.string.skip_tutorial_dialog_subtitle, tipsAppName));
+ } else {
+ Log.w(TAG, "No subtitle view in the skip tutorial dialog to update.");
+ }
+
+ Button cancelButton = (Button) contentView.findViewById(
+ R.id.gesture_tutorial_dialog_cancel_button);
+ if (cancelButton != null) {
+ cancelButton.setOnClickListener(
+ v -> tutorialDialog.dismiss());
+ } else {
+ Log.w(TAG, "No cancel button in the skip tutorial dialog to update.");
+ }
+
+ Button confirmButton = contentView.findViewById(
+ R.id.gesture_tutorial_dialog_confirm_button);
+ if (confirmButton != null) {
+ confirmButton.setOnClickListener(v -> {
+ sandboxActivity.closeTutorial();
+ tutorialDialog.dismiss();
+ });
+ } else {
+ Log.w(TAG, "No confirm button in the skip tutorial dialog to update.");
+ }
+
+ tutorialDialog.getWindow().setBackgroundDrawable(
+ new ColorDrawable(sandboxActivity.getColor(android.R.color.transparent)));
+
+ return tutorialDialog;
+ }
+
+ return null;
}
/** Denotes the type of the tutorial. */
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 6e30ad0..b6663b8 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -16,9 +16,12 @@
package com.android.quickstep.interaction;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Insets;
-import android.net.Uri;
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
@@ -27,7 +30,7 @@
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowInsets;
-import android.widget.VideoView;
+import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -35,7 +38,6 @@
import androidx.fragment.app.FragmentActivity;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.quickstep.interaction.TutorialController.TutorialType;
abstract class TutorialFragment extends Fragment implements OnTouchListener {
@@ -48,8 +50,10 @@
RootSandboxLayout mRootView;
EdgeBackGestureHandler mEdgeBackGestureHandler;
NavBarGestureHandler mNavBarGestureHandler;
- private VideoView mFeedbackVideoView;
- private int mFeedbackVideoDuration;
+ private ImageView mFeedbackVideoView;
+
+ @Nullable private AnimatedVectorDrawable mTutorialAnimation = null;
+ private boolean mIntroductionShown = false;
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@@ -92,6 +96,11 @@
return null;
}
+ @Nullable
+ AnimatedVectorDrawable getTutorialAnimation() {
+ return mTutorialAnimation;
+ }
+
abstract TutorialController createController(TutorialType type);
abstract Class<? extends TutorialController> getControllerClass();
@@ -130,12 +139,6 @@
}
@Override
- public void onStart() {
- super.onStart();
- initializeFeedbackVideoView();
- }
-
- @Override
public void onStop() {
super.onStop();
releaseFeedbackVideoView();
@@ -143,20 +146,18 @@
void initializeFeedbackVideoView() {
if (!updateFeedbackVideo()) {
- mFeedbackVideoView.setVisibility(View.INVISIBLE);
return;
- } else {
- mFeedbackVideoView.setVisibility(View.VISIBLE);
}
- int heightPixels = getResources().getDisplayMetrics().heightPixels;
- int heightPixelsWithMargin = heightPixels + Utilities.dpToPx(80);
- int widthPixels = getResources().getDisplayMetrics().widthPixels - Utilities.dpToPx(12);
- mFeedbackVideoView.setScaleY((float) heightPixelsWithMargin / heightPixels);
- mFeedbackVideoView.setScaleX((float) heightPixelsWithMargin / widthPixels);
- mFeedbackVideoView.start();
- mFeedbackVideoView.setOnPreparedListener(
- mp -> mFeedbackVideoDuration = mFeedbackVideoView.getDuration());
- mFeedbackVideoView.setOnCompletionListener(mp -> releaseFeedbackVideoView());
+
+ if (!mIntroductionShown && mTutorialController != null) {
+ Integer introTileStringResId = mTutorialController.getIntroductionTitle();
+ Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
+ if (introTileStringResId != null && introSubtitleResId != null) {
+ mTutorialController.showFeedback(introTileStringResId,
+ introSubtitleResId, null, false);
+ mIntroductionShown = true;
+ }
+ }
}
boolean updateFeedbackVideo() {
@@ -164,19 +165,37 @@
if (feedbackVideoResId == null || getContext() == null) {
return false;
}
- Uri uri = Uri.parse("android.resource://" + getContext().getPackageName() + "/"
- + feedbackVideoResId);
- mFeedbackVideoView.setVideoURI(uri);
+ mTutorialAnimation = (AnimatedVectorDrawable) getContext().getDrawable(feedbackVideoResId);
+
+ if (mTutorialAnimation != null) {
+ mTutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+
+ @Override
+ public void onAnimationStart(Drawable drawable) {
+ super.onAnimationStart(drawable);
+
+ mFeedbackVideoView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ super.onAnimationEnd(drawable);
+
+ releaseFeedbackVideoView();
+ }
+ });
+ }
+ mFeedbackVideoView.setImageDrawable(mTutorialAnimation);
+
return true;
}
void releaseFeedbackVideoView() {
- mFeedbackVideoView.stopPlayback();
- mFeedbackVideoView.setVisibility(View.INVISIBLE);
- }
+ if (mTutorialAnimation != null && mTutorialAnimation.isRunning()) {
+ mTutorialAnimation.stop();
+ }
- int getFeedbackVideoDuration() {
- return mFeedbackVideoDuration;
+ mFeedbackVideoView.setVisibility(View.GONE);
}
@Override
@@ -217,6 +236,7 @@
mEdgeBackGestureHandler.registerBackGestureAttemptCallback(mTutorialController);
mNavBarGestureHandler.registerNavBarGestureAttemptCallback(mTutorialController);
mTutorialType = tutorialType;
+ initializeFeedbackVideoView();
}
@Override
@@ -230,11 +250,7 @@
}
void continueTutorial() {
- if (!(getContext() instanceof GestureSandboxActivity)) {
- closeTutorial();
- return;
- }
- GestureSandboxActivity gestureSandboxActivity = (GestureSandboxActivity) getContext();
+ GestureSandboxActivity gestureSandboxActivity = getGestureSandboxActivity();
if (gestureSandboxActivity == null) {
closeTutorial();
@@ -255,12 +271,22 @@
startActivity(new Intent("com.android.settings.GESTURE_NAVIGATION_SETTINGS"));
}
- boolean isTutorialComplete() {
- if (!(getContext() instanceof GestureSandboxActivity)) {
- return true;
- }
- GestureSandboxActivity gestureSandboxActivity = (GestureSandboxActivity) getContext();
+ int getCurrentStep() {
+ GestureSandboxActivity gestureSandboxActivity = getGestureSandboxActivity();
- return gestureSandboxActivity == null || gestureSandboxActivity.isTutorialComplete();
+ return gestureSandboxActivity == null ? -1 : gestureSandboxActivity.getCurrentStep();
+ }
+
+ int getNumSteps() {
+ GestureSandboxActivity gestureSandboxActivity = getGestureSandboxActivity();
+
+ return gestureSandboxActivity == null ? -1 : gestureSandboxActivity.getNumSteps();
+ }
+
+ @Nullable
+ private GestureSandboxActivity getGestureSandboxActivity() {
+ Context context = getContext();
+
+ return context instanceof GestureSandboxActivity ? (GestureSandboxActivity) context : null;
}
}
diff --git a/quickstep/src/com/android/quickstep/util/AppCloseConfig.java b/quickstep/src/com/android/quickstep/util/AppCloseConfig.java
new file mode 100644
index 0000000..bec3379
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AppCloseConfig.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.quickstep.util;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+
+/*
+ * Adds getter methods to {@link MultiValueUpdateListener} specific to app close animation,
+ * so that the entire animation can be defined in one place.
+ */
+public abstract class AppCloseConfig extends MultiValueUpdateListener {
+
+ /**
+ * Returns the translation y of the workspace contents.
+ */
+ public abstract float getWorkspaceTransY();
+
+ /*
+ * Returns the scale of the workspace contents.
+ */
+ public abstract float getWorkspaceScale();
+
+ /*
+ * Returns the alpha of the window.
+ */
+ public abstract @FloatRange(from = 0, to = 1) float getWindowAlpha();
+
+ /*
+ * Returns the alpha of the foreground layer of an adaptive icon.
+ */
+ public abstract @IntRange(from = 0, to = 255) int getFgAlpha();
+
+ /*
+ * Returns the corner radius of the window and icon.
+ */
+ public abstract float getCornerRadius();
+
+ /*
+ * Returns the interpolated progress of the animation.
+ */
+ public abstract float getInterpolatedProgress();
+
+}
diff --git a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
index 351adf4..c527be3 100644
--- a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
+++ b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
@@ -46,7 +46,8 @@
}
public boolean get() {
- return mBasePredicate.get() && mSupported && mObserver.isHomeAndOverviewSame();
+ return mBasePredicate.get() && mSupported && mObserver != null
+ && mObserver.isHomeAndOverviewSame();
}
public void initialize(Context context) {
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index e5d2c53..02ec68a 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -20,6 +20,7 @@
import android.graphics.PointF;
import android.graphics.RectF;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
@@ -241,7 +242,7 @@
mCurrentCenterX + currentWidth / 2, mCurrentY + currentHeight);
}
for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
- onUpdateListener.onUpdate(mCurrentRect, mCurrentScaleProgress);
+ onUpdateListener.onUpdate(null, mCurrentRect, mCurrentScaleProgress);
}
}
}
@@ -266,7 +267,7 @@
}
public interface OnUpdateListener {
- void onUpdate(RectF currentRect, float progress);
+ void onUpdate(@Nullable AppCloseConfig values, RectF currentRect, float progress);
default void onCancel() { }
}
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java
new file mode 100644
index 0000000..95d56aa
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim2.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2021 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.quickstep.util;
+
+import static com.android.launcher3.Utilities.dpToPx;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.util.PathParser;
+import android.util.Property;
+import android.view.animation.Interpolator;
+
+import androidx.core.view.animation.PathInterpolatorCompat;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+import androidx.dynamicanimation.animation.SpringAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.DynamicResource;
+import com.android.systemui.plugins.ResourceProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Applies spring forces to animate from a starting rect to a target rect,
+ * while providing update callbacks to the caller.
+ */
+public class RectFSpringAnim2 extends RectFSpringAnim {
+
+ private static final FloatPropertyCompat<RectFSpringAnim2> RECT_CENTER_X =
+ new FloatPropertyCompat<RectFSpringAnim2>("rectCenterXSpring") {
+ @Override
+ public float getValue(RectFSpringAnim2 anim) {
+ return anim.mCurrentCenterX;
+ }
+
+ @Override
+ public void setValue(RectFSpringAnim2 anim, float currentCenterX) {
+ anim.mCurrentCenterX = currentCenterX;
+ anim.onUpdate();
+ }
+ };
+
+ private static final FloatPropertyCompat<RectFSpringAnim2> RECT_Y =
+ new FloatPropertyCompat<RectFSpringAnim2>("rectYSpring") {
+ @Override
+ public float getValue(RectFSpringAnim2 anim) {
+ return anim.mCurrentY;
+ }
+
+ @Override
+ public void setValue(RectFSpringAnim2 anim, float y) {
+ anim.mCurrentY = y;
+ anim.onUpdate();
+ }
+ };
+
+ private static final Property<RectFSpringAnim2, Float> PROGRESS =
+ new Property<RectFSpringAnim2, Float>(Float.class, "rectFProgress") {
+ @Override
+ public Float get(RectFSpringAnim2 rectFSpringAnim) {
+ return rectFSpringAnim.mProgress;
+ }
+
+ @Override
+ public void set(RectFSpringAnim2 rectFSpringAnim, Float progress) {
+ rectFSpringAnim.mProgress = progress;
+ rectFSpringAnim.onUpdate();
+ }
+ };
+
+ private final RectF mStartRect;
+ private final RectF mTargetRect;
+ private final RectF mCurrentRect = new RectF();
+ private final List<OnUpdateListener> mOnUpdateListeners = new ArrayList<>();
+ private final List<Animator.AnimatorListener> mAnimatorListeners = new ArrayList<>();
+
+ private float mCurrentCenterX;
+ private float mCurrentY;
+
+ private float mTargetX;
+ private float mTargetY;
+
+ // If true, tracking the bottom of the rects, else tracking the top.
+ private final boolean mTrackingBottomY;
+ private float mProgress;
+ private SpringAnimation mRectXAnim;
+ private SpringAnimation mRectYAnim;
+ private ValueAnimator mRectScaleAnim;
+ private boolean mAnimsStarted;
+ private boolean mRectXAnimEnded;
+ private boolean mRectYAnimEnded;
+ private boolean mRectScaleAnimEnded;
+
+ private final float mXDamping;
+ private final float mXStiffness;
+
+ private final float mYDamping;
+ private float mYStiffness;
+
+ private long mDuration;
+
+ private final Interpolator mCloseInterpolator;
+
+ private AppCloseConfig mValues;
+ final float mStartRadius;
+ final float mEndRadius;
+
+ final float mHomeTransYEnd;
+ final float mScaleStart;
+
+ public RectFSpringAnim2(RectF startRect, RectF targetRect, Context context, float startRadius,
+ float endRadius) {
+ super(startRect, targetRect, context);
+ mStartRect = startRect;
+ mTargetRect = targetRect;
+
+ mTrackingBottomY = startRect.bottom < targetRect.bottom;
+ mCurrentY = mTrackingBottomY ? mStartRect.bottom : mStartRect.top;
+ mCurrentCenterX = mStartRect.centerX();
+
+ mTargetY = mTrackingBottomY ? mTargetRect.bottom : mTargetRect.top;
+ mTargetX = mTargetRect.centerX();
+
+ ResourceProvider rp = DynamicResource.provider(context);
+ mXDamping = rp.getFloat(R.dimen.swipe_up_rect_2_x_damping_ratio);
+ mXStiffness = rp.getFloat(R.dimen.swipe_up_rect_2_x_stiffness);
+
+ mYDamping = rp.getFloat(R.dimen.swipe_up_rect_2_y_damping_ratio);
+ mYStiffness = rp.getFloat(R.dimen.swipe_up_rect_2_y_stiffness);
+ mDuration = Math.round(rp.getFloat(R.dimen.swipe_up_duration));
+
+ mHomeTransYEnd = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
+ mScaleStart = rp.getFloat(R.dimen.swipe_up_scale_start);
+
+
+ if (!mTrackingBottomY) {
+ mYStiffness *= rp.getFloat(R.dimen.swipe_up_rect_2_y_stiffness_low_swipe_multiplier);
+ mDuration *= rp.getFloat(R.dimen.swipe_up_low_swipe_duration_multiplier);
+ }
+
+ mCloseInterpolator = getAppCloseInterpolator(context);
+
+ // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
+ // rounding at the end of the animation.
+ mStartRadius = startRadius;
+ mEndRadius = endRadius;
+
+ setCanRelease(true);
+ }
+
+ public void onTargetPositionChanged() {
+ if (mRectXAnim != null && mTargetX != mTargetRect.centerX()) {
+ mTargetX = mTargetRect.centerX();
+ mRectXAnim.animateToFinalPosition(mTargetX);
+ }
+
+ if (mRectYAnim != null) {
+ if (mTrackingBottomY && mTargetY != mTargetRect.bottom) {
+ mTargetY = mTargetRect.bottom;
+ mRectYAnim.animateToFinalPosition(mTargetY);
+ } else if (!mTrackingBottomY && mTargetY != mTargetRect.top) {
+ mTargetY = mTargetRect.top;
+ mRectYAnim.animateToFinalPosition(mTargetY);
+ }
+ }
+ }
+
+ public void addOnUpdateListener(OnUpdateListener onUpdateListener) {
+ mOnUpdateListeners.add(onUpdateListener);
+ }
+
+ public void addAnimatorListener(Animator.AnimatorListener animatorListener) {
+ mAnimatorListeners.add(animatorListener);
+ }
+
+ /**
+ * Starts the fling/spring animation.
+ * @param context The activity context.
+ * @param velocityPxPerMs Velocity of swipe in px/ms.
+ */
+ public void start(Context context, PointF velocityPxPerMs) {
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context);
+
+ mRectXAnim = new SpringAnimation(this, RECT_CENTER_X)
+ .setStartValue(mCurrentCenterX)
+ .setMinValue(Math.min(0, mCurrentCenterX))
+ .setMaxValue(Math.max(dp.widthPx, mCurrentCenterX))
+ .setStartVelocity(velocityPxPerMs.x * 1000)
+ .setSpring(new SpringForce(mTargetX)
+ .setStiffness(mXStiffness)
+ .setDampingRatio(mXDamping));
+ mRectXAnim.addEndListener(((animation, canceled, centerX, velocityX) -> {
+ mRectXAnimEnded = true;
+ maybeOnEnd();
+ }));
+
+ mRectYAnim = new SpringAnimation(this, RECT_Y)
+ .setStartValue(mCurrentY)
+ .setMinValue(Math.min(0, mCurrentY))
+ .setMaxValue(Math.max(dp.heightPx, mCurrentY))
+ .setStartVelocity(velocityPxPerMs.y * 1000)
+ .setSpring(new SpringForce(mTargetY)
+ .setStiffness(mYStiffness)
+ .setDampingRatio(mYDamping));
+ mRectYAnim.addEndListener(((animation, canceled, centerY, velocityY) -> {
+ mRectYAnimEnded = true;
+ maybeOnEnd();
+ }));
+
+ mRectScaleAnim = ObjectAnimator.ofFloat(this, PROGRESS, 0, 1f)
+ .setDuration(mDuration);
+ mRectScaleAnim.setInterpolator(mCloseInterpolator);
+ mRectScaleAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mRectScaleAnimEnded = true;
+ maybeOnEnd();
+ }
+ });
+
+ mValues = buildConfig();
+ mRectScaleAnim.addUpdateListener(mValues);
+
+ setCanRelease(false);
+ mAnimsStarted = true;
+
+ mRectXAnim.start();
+ mRectYAnim.start();
+ mRectScaleAnim.start();
+ for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
+ animatorListener.onAnimationStart(null);
+ }
+ }
+
+ private AppCloseConfig buildConfig() {
+ return new AppCloseConfig() {
+ FloatProp mHomeTransY = new FloatProp(0, mHomeTransYEnd, 0, mDuration, LINEAR);
+ FloatProp mHomeScale = new FloatProp(mScaleStart, 1f, 0, mDuration, LINEAR);
+ FloatProp mWindowFadeOut = new FloatProp(1f, 0f, 0, 116, LINEAR);
+ // There should be a slight overlap b/w window fading out and fg fading in.
+ // (fg startDelay < window fade out duration)
+ FloatProp mFgFadeIn = new FloatProp(0, 255f, 100, mDuration - 100, LINEAR);
+ FloatProp mRadius = new FloatProp(mStartRadius, mEndRadius, 0, mDuration, LINEAR);
+ FloatProp mThreePointInterpolation = new FloatProp(0, 1, 0, mDuration, LINEAR);
+
+ @Override
+ public float getWorkspaceTransY() {
+ return mHomeTransY.value;
+ }
+
+ @Override
+ public float getWorkspaceScale() {
+ return mHomeScale.value;
+ }
+
+ @Override
+ public float getWindowAlpha() {
+ return mWindowFadeOut.value;
+ }
+
+ @Override
+ public int getFgAlpha() {
+ return (int) mFgFadeIn.value;
+ }
+
+ @Override
+ public float getCornerRadius() {
+ return mRadius.value;
+ }
+
+ @Override
+ public float getInterpolatedProgress() {
+ return mThreePointInterpolation.value;
+ }
+
+ @Override
+ public void onUpdate(float percent) {}
+ };
+ }
+
+ public void end() {
+ if (mAnimsStarted) {
+ if (mRectXAnim.canSkipToEnd()) {
+ mRectXAnim.skipToEnd();
+ }
+ if (mRectYAnim.canSkipToEnd()) {
+ mRectYAnim.skipToEnd();
+ }
+ mRectScaleAnim.end();
+ }
+ mRectXAnimEnded = true;
+ mRectYAnimEnded = true;
+ mRectScaleAnimEnded = true;
+ maybeOnEnd();
+ }
+
+ private boolean isEnded() {
+ return mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded;
+ }
+
+ private void onUpdate() {
+ if (isEnded()) {
+ // Prevent further updates from being called. This can happen between callbacks for
+ // ending the x/y/scale animations.
+ return;
+ }
+
+ if (!mOnUpdateListeners.isEmpty()) {
+ float rectProgress = mProgress;
+ float currentWidth = Utilities.mapRange(rectProgress, mStartRect.width(),
+ mTargetRect.width());
+ float currentHeight = Utilities.mapRange(rectProgress, mStartRect.height(),
+ mTargetRect.height());
+ if (mTrackingBottomY) {
+ mCurrentRect.set(mCurrentCenterX - currentWidth / 2, mCurrentY - currentHeight,
+ mCurrentCenterX + currentWidth / 2, mCurrentY);
+ } else {
+ mCurrentRect.set(mCurrentCenterX - currentWidth / 2, mCurrentY,
+ mCurrentCenterX + currentWidth / 2, mCurrentY + currentHeight);
+ }
+
+ float currentPlayTime = mRectScaleAnimEnded ? mRectScaleAnim.getDuration()
+ : mRectScaleAnim.getCurrentPlayTime();
+ float linearProgress = Math.min(1f, currentPlayTime / mRectScaleAnim.getDuration());
+ for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
+ onUpdateListener.onUpdate(mValues, mCurrentRect, linearProgress);
+ }
+ }
+ }
+
+ private void maybeOnEnd() {
+ if (mAnimsStarted && isEnded()) {
+ mAnimsStarted = false;
+ setCanRelease(true);
+ for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
+ animatorListener.onAnimationEnd(null);
+ }
+ }
+ }
+
+ public void cancel() {
+ if (mAnimsStarted) {
+ for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
+ onUpdateListener.onCancel();
+ }
+ }
+ end();
+ }
+
+ private Interpolator getAppCloseInterpolator(Context context) {
+ ResourceProvider rp = DynamicResource.provider(context);
+ String path = String.format("M 0,0 C %f, %f, %f, %f, %f, %f C %f, %f, %f, %f, 1, 1",
+ rp.getFloat(R.dimen.c1_a),
+ rp.getFloat(R.dimen.c1_b),
+ rp.getFloat(R.dimen.c1_c),
+ rp.getFloat(R.dimen.c1_d),
+ rp.getFloat(R.dimen.mp_x),
+ rp.getFloat(R.dimen.mp_y),
+ rp.getFloat(R.dimen.c2_a),
+ rp.getFloat(R.dimen.c2_b),
+ rp.getFloat(R.dimen.c2_c),
+ rp.getFloat(R.dimen.c2_d));
+ return PathInterpolatorCompat.create(PathParser.createPathFromPathData(path));
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java b/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
index 176478f..88cc650 100644
--- a/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
+++ b/quickstep/src/com/android/quickstep/util/SplitScreenBounds.java
@@ -77,7 +77,7 @@
WindowBounds bounds = new WindowBounds(wm.getBounds(),
new Rect(insets.left, insets.top, insets.right, insets.bottom));
- int rotation = DisplayController.getDefaultDisplay(context).getInfo().rotation;
+ int rotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
int halfDividerSize = context.getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 9576eac..01d51f8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -16,15 +16,20 @@
package com.android.quickstep.util;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
+import android.content.res.Resources;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.util.Pair;
+import android.view.Gravity;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -32,7 +37,10 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.LauncherAnimationRunner;
+import com.android.launcher3.R;
import com.android.launcher3.WrappedAnimationRunnerImpl;
import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
@@ -114,6 +122,26 @@
resetState();
}
+ /**
+ * @return {@link InsettableFrameLayout.LayoutParams} to correctly position the
+ * split placeholder view
+ */
+ public InsettableFrameLayout.LayoutParams getLayoutParamsForActivePosition(Resources resources,
+ DeviceProfile deviceProfile) {
+ InsettableFrameLayout.LayoutParams params =
+ new InsettableFrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ boolean topLeftPosition = mInitialPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT;
+ if (deviceProfile.isLandscape) {
+ params.width = (int) resources.getDimension(R.dimen.split_placeholder_size);
+ params.gravity = topLeftPosition ? Gravity.START : Gravity.END;
+ } else {
+ params.height = (int) resources.getDimension(R.dimen.split_placeholder_size);
+ params.gravity = Gravity.TOP;
+ }
+
+ return params;
+ }
+
@Nullable
public SplitPositionOption getActiveSplitPositionOption() {
return mInitialPosition;
@@ -133,8 +161,8 @@
}
@Override
- public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
- Runnable finishCallback) {
+ public void startAnimation(IBinder transition, TransitionInfo info,
+ SurfaceControl.Transaction t, Runnable finishCallback) {
TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTaskView, mTaskView,
info, t, finishCallback);
// After successful launch, call resetState
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 1df459e..ab95138 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.config.FeatureFlags.PROTOTYPE_APP_CLOSE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
@@ -139,7 +140,7 @@
addDepthAnimationForState(launcher, NORMAL, DURATION_MS);
- mAnimators.play(launcher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
+ mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
.setDuration(DURATION_MS));
mAnimators.addListener(new AnimatorListenerAdapter() {
@Override
@@ -220,6 +221,9 @@
* @param totalRows Total number of rows.
*/
private void addStaggeredAnimationForView(View v, int row, int totalRows) {
+ if (PROTOTYPE_APP_CLOSE.get()) {
+ return;
+ }
// Invert the rows, because we stagger starting from the bottom of the screen.
int invertedRow = totalRows - row;
// Add 1 to the inverted row so that the bottom most row has a start delay.
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
new file mode 100644
index 0000000..f74aa55
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2021 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.quickstep.views;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Outline;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.widget.RemoteViews.RemoteViewOutlineProvider;
+
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.RoundedCornerEnforcement;
+
+import java.util.stream.IntStream;
+
+/**
+ * Mimics the appearance of the background view of a {@link LauncherAppWidgetHostView} through a
+ * an App Widget activity launch animation.
+ */
+@TargetApi(Build.VERSION_CODES.S)
+final class FloatingWidgetBackgroundView extends View {
+ private final ColorDrawable mFallbackDrawable = new ColorDrawable();
+ private final DrawableProperties mForegroundProperties = new DrawableProperties();
+ private final DrawableProperties mBackgroundProperties = new DrawableProperties();
+
+ private Drawable mOriginalForeground;
+ private Drawable mOriginalBackground;
+ private float mFinalRadius;
+ private float mInitialOutlineRadius;
+ private float mOutlineRadius;
+ private boolean mIsUsingFallback;
+ private View mSourceView;
+
+ FloatingWidgetBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mOutlineRadius);
+ }
+ });
+ setClipToOutline(true);
+ }
+
+ void init(LauncherAppWidgetHostView hostView, View backgroundView, float finalRadius) {
+ mFinalRadius = finalRadius;
+ mSourceView = backgroundView;
+ mInitialOutlineRadius = getOutlineRadius(hostView, backgroundView);
+ mIsUsingFallback = false;
+ if (isSupportedDrawable(backgroundView.getForeground())) {
+ mOriginalForeground = backgroundView.getForeground();
+ mForegroundProperties.init(
+ mOriginalForeground.getConstantState().newDrawable().mutate());
+ setForeground(mForegroundProperties.mDrawable);
+ mSourceView.setForeground(null);
+ }
+ if (isSupportedDrawable(backgroundView.getBackground())) {
+ mOriginalBackground = backgroundView.getBackground();
+ mBackgroundProperties.init(
+ mOriginalBackground.getConstantState().newDrawable().mutate());
+ setBackground(mBackgroundProperties.mDrawable);
+ mSourceView.setBackground(null);
+ } else if (mOriginalForeground == null) {
+ mFallbackDrawable.setColor(Themes.getColorBackground(backgroundView.getContext()));
+ setBackground(mFallbackDrawable);
+ mIsUsingFallback = true;
+ }
+ }
+
+ /** Update the animated properties of the drawables. */
+ void update(float cornerRadiusProgress, float fallbackAlpha) {
+ if (isUninitialized()) return;
+ mOutlineRadius = mInitialOutlineRadius + (mFinalRadius - mInitialOutlineRadius)
+ * cornerRadiusProgress;
+ mForegroundProperties.updateDrawable(mFinalRadius, cornerRadiusProgress);
+ mBackgroundProperties.updateDrawable(mFinalRadius, cornerRadiusProgress);
+ setAlpha(mIsUsingFallback ? fallbackAlpha : 1f);
+ }
+
+ /** Restores the drawables to the source view. */
+ void finish() {
+ if (isUninitialized()) return;
+ mSourceView.setForeground(mOriginalForeground);
+ mSourceView.setBackground(mOriginalBackground);
+ }
+
+ void recycle() {
+ mSourceView = null;
+ mOriginalForeground = null;
+ mOriginalBackground = null;
+ mOutlineRadius = 0;
+ mFinalRadius = 0;
+ setForeground(null);
+ setBackground(null);
+ }
+
+ /** Get the largest of drawable corner radii or background view outline radius. */
+ float getMaximumRadius() {
+ if (isUninitialized()) return 0;
+ return Math.max(mInitialOutlineRadius, Math.max(getMaxRadius(mOriginalForeground),
+ getMaxRadius(mOriginalBackground)));
+ }
+
+ private boolean isUninitialized() {
+ return mSourceView == null;
+ }
+
+ /** Returns the maximum corner radius of {@param drawable}. */
+ private static float getMaxRadius(Drawable drawable) {
+ if (!(drawable instanceof GradientDrawable)) return 0;
+ float[] cornerRadii = ((GradientDrawable) drawable).getCornerRadii();
+ float cornerRadius = ((GradientDrawable) drawable).getCornerRadius();
+ double radiiMax = cornerRadii == null ? 0 : IntStream.range(0, cornerRadii.length)
+ .mapToDouble(i -> cornerRadii[i]).max().orElse(0);
+ return Math.max(cornerRadius, (float) radiiMax);
+ }
+
+ /** Returns whether the given drawable type is supported. */
+ private static boolean isSupportedDrawable(Drawable drawable) {
+ return drawable instanceof ColorDrawable || (drawable instanceof GradientDrawable
+ && ((GradientDrawable) drawable).getShape() == GradientDrawable.RECTANGLE);
+ }
+
+ /** Corner radius from source view's outline, or enforced view. */
+ private static float getOutlineRadius(LauncherAppWidgetHostView hostView, View v) {
+ if (RoundedCornerEnforcement.isRoundedCornerEnabled()
+ && hostView.hasEnforcedCornerRadius()) {
+ return hostView.getEnforcedCornerRadius();
+ } else if (v.getOutlineProvider() instanceof RemoteViewOutlineProvider
+ && v.getClipToOutline()) {
+ return ((RemoteViewOutlineProvider) v.getOutlineProvider()).getRadius();
+ }
+ return 0;
+ }
+
+ /** Stores and modifies a drawable's properties through an animation. */
+ private static class DrawableProperties {
+ private Drawable mDrawable;
+ private float mOriginalRadius;
+ private float[] mOriginalRadii;
+ private final float[] mTmpRadii = new float[8];
+
+ /** Store a drawable's animated properties. */
+ void init(Drawable drawable) {
+ mDrawable = drawable;
+ if (!(drawable instanceof GradientDrawable)) return;
+ mOriginalRadius = ((GradientDrawable) drawable).getCornerRadius();
+ mOriginalRadii = ((GradientDrawable) drawable).getCornerRadii();
+ }
+
+ /**
+ * Update the drawable for the given animation state.
+ *
+ * @param finalRadius the radius of each corner when {@param progress} is 1
+ * @param progress the linear progress of the corner radius from its original value to
+ * {@param finalRadius}
+ */
+ void updateDrawable(float finalRadius, float progress) {
+ if (!(mDrawable instanceof GradientDrawable)) return;
+ GradientDrawable d = (GradientDrawable) mDrawable;
+ if (mOriginalRadii != null) {
+ for (int i = 0; i < mOriginalRadii.length; i++) {
+ mTmpRadii[i] = mOriginalRadii[i] + (finalRadius - mOriginalRadii[i]) * progress;
+ }
+ d.setCornerRadii(mTmpRadii);
+ } else {
+ d.setCornerRadius(mOriginalRadius + (finalRadius - mOriginalRadius) * progress);
+ }
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
new file mode 100644
index 0000000..d23884c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2021 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.quickstep.views;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.GhostView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.views.ListenerView;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.RoundedCornerEnforcement;
+
+/** A view that mimics an App Widget through a launch animation. */
+@TargetApi(Build.VERSION_CODES.S)
+public class FloatingWidgetView extends FrameLayout implements AnimatorListener {
+ private static final Matrix sTmpMatrix = new Matrix();
+
+ private final Launcher mLauncher;
+ private final ListenerView mListenerView;
+ private final FloatingWidgetBackgroundView mBackgroundView;
+ private final RectF mBackgroundOffset = new RectF();
+
+ private LauncherAppWidgetHostView mAppWidgetView;
+ private View mAppWidgetBackgroundView;
+ private RectF mBackgroundPosition;
+ private GhostView mForegroundOverlayView;
+
+ private Runnable mEndRunnable;
+ private Runnable mFastFinishRunnable;
+
+ public FloatingWidgetView(Context context) {
+ this(context, null);
+ }
+
+ public FloatingWidgetView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FloatingWidgetView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mLauncher = Launcher.getLauncher(context);
+ mListenerView = new ListenerView(context, attrs);
+ mBackgroundView = new FloatingWidgetBackgroundView(context, attrs, defStyleAttr);
+ addView(mBackgroundView);
+ setWillNotDraw(false);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ Runnable endRunnable = mEndRunnable;
+ mEndRunnable = null;
+ if (endRunnable != null) {
+ endRunnable.run();
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Animator animator) {
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {
+ }
+
+ /** Sets a runnable that is called after a call to {@link #fastFinish()}. */
+ public void setFastFinishRunnable(Runnable runnable) {
+ mFastFinishRunnable = runnable;
+ }
+
+ /** Callback at the end or early exit of the animation. */
+ public void fastFinish() {
+ if (isUninitialized()) return;
+ Runnable fastFinishRunnable = mFastFinishRunnable;
+ if (fastFinishRunnable != null) {
+ fastFinishRunnable.run();
+ }
+ Runnable endRunnable = mEndRunnable;
+ mEndRunnable = null;
+ if (endRunnable != null) {
+ endRunnable.run();
+ }
+ }
+
+ private void init(DragLayer dragLayer, LauncherAppWidgetHostView originalView,
+ RectF widgetBackgroundPosition, Rect windowTargetBounds, float windowCornerRadius) {
+ mAppWidgetView = originalView;
+ mAppWidgetView.beginDeferringUpdates();
+ mBackgroundPosition = widgetBackgroundPosition;
+ mEndRunnable = () -> finish(dragLayer);
+
+ mAppWidgetBackgroundView = RoundedCornerEnforcement.findBackground(mAppWidgetView);
+ if (mAppWidgetBackgroundView == null) {
+ mAppWidgetBackgroundView = mAppWidgetView;
+ }
+
+ getRelativePosition(mAppWidgetBackgroundView, dragLayer, mBackgroundPosition);
+ getRelativePosition(mAppWidgetBackgroundView, mAppWidgetView, mBackgroundOffset);
+ mBackgroundView.init(mAppWidgetView, mAppWidgetBackgroundView, windowCornerRadius);
+ // Layout call before GhostView creation so that the overlaid view isn't clipped
+ layout(0, 0, windowTargetBounds.width(), windowTargetBounds.height());
+ mForegroundOverlayView = GhostView.addGhost(mAppWidgetView, this);
+ positionViews();
+
+ mListenerView.setListener(this::fastFinish);
+ dragLayer.addView(mListenerView);
+ }
+
+ /**
+ * Updates the position and opacity of the floating widget's components.
+ *
+ * @param backgroundPosition the new position of the widget's background relative to the
+ * {@link FloatingWidgetView}'s parent
+ * @param floatingWidgetAlpha the overall opacity of the {@link FloatingWidgetView}
+ * @param foregroundAlpha the opacity of the foreground layer
+ * @param fallbackBackgroundAlpha the opacity of the fallback background used when the App
+ * Widget doesn't have a background
+ * @param cornerRadiusProgress progress of the corner radius animation, where 0 is the
+ * original radius and 1 is the window radius
+ */
+ public void update(RectF backgroundPosition, float floatingWidgetAlpha, float foregroundAlpha,
+ float fallbackBackgroundAlpha, float cornerRadiusProgress) {
+ if (isUninitialized()) return;
+ setAlpha(floatingWidgetAlpha);
+ mBackgroundView.update(cornerRadiusProgress, fallbackBackgroundAlpha);
+ mAppWidgetView.setAlpha(foregroundAlpha);
+ mBackgroundPosition = backgroundPosition;
+ positionViews();
+ }
+
+ /** Sets the layout parameters of the floating view and its background view child. */
+ private void positionViews() {
+ LayoutParams layoutParams = (LayoutParams) getLayoutParams();
+ layoutParams.setMargins(0, 0, 0, 0);
+ setLayoutParams(layoutParams);
+
+ // FloatingWidgetView layout is forced LTR
+ mBackgroundView.setTranslationX(mBackgroundPosition.left);
+ mBackgroundView.setTranslationY(mBackgroundPosition.top);
+ LayoutParams backgroundParams = (LayoutParams) mBackgroundView.getLayoutParams();
+ backgroundParams.leftMargin = 0;
+ backgroundParams.topMargin = 0;
+ backgroundParams.width = (int) mBackgroundPosition.width();
+ backgroundParams.height = (int) mBackgroundPosition.height();
+ mBackgroundView.setLayoutParams(backgroundParams);
+
+ sTmpMatrix.reset();
+ float foregroundScale = mBackgroundPosition.width() / mAppWidgetBackgroundView.getWidth();
+ sTmpMatrix.setTranslate(-mBackgroundOffset.left - mAppWidgetView.getLeft(),
+ -mBackgroundOffset.top - mAppWidgetView.getTop());
+ sTmpMatrix.postScale(foregroundScale, foregroundScale);
+ sTmpMatrix.postTranslate(mBackgroundPosition.left, mBackgroundPosition.top);
+ mForegroundOverlayView.setMatrix(sTmpMatrix);
+ }
+
+ private void finish(DragLayer dragLayer) {
+ mAppWidgetView.setAlpha(1f);
+ GhostView.removeGhost(mAppWidgetView);
+ ((ViewGroup) dragLayer.getParent()).removeView(this);
+ dragLayer.removeView(mListenerView);
+ mBackgroundView.finish();
+ mAppWidgetView.endDeferringUpdates();
+ recycle();
+ mLauncher.getViewCache().recycleView(R.layout.floating_widget_view, this);
+ }
+
+ public float getInitialCornerRadius() {
+ return mBackgroundView.getMaximumRadius();
+ }
+
+ private boolean isUninitialized() {
+ return mForegroundOverlayView == null;
+ }
+
+ private void recycle() {
+ mEndRunnable = null;
+ mFastFinishRunnable = null;
+ mBackgroundPosition = null;
+ mListenerView.setListener(null);
+ mAppWidgetView = null;
+ mForegroundOverlayView = null;
+ mAppWidgetBackgroundView = null;
+ mBackgroundView.recycle();
+ }
+
+ /**
+ * Configures and returns a an instance of {@link FloatingWidgetView} matching the appearance of
+ * {@param originalView}.
+ *
+ * @param widgetBackgroundPosition a {@link RectF} that will be updated with the widget's
+ * background bounds
+ * @param windowTargetBounds the bounds of the window when launched
+ * @param windowCornerRadius the corner radius of the window
+ */
+ public static FloatingWidgetView getFloatingWidgetView(Launcher launcher,
+ LauncherAppWidgetHostView originalView, RectF widgetBackgroundPosition,
+ Rect windowTargetBounds, float windowCornerRadius) {
+ final DragLayer dragLayer = launcher.getDragLayer();
+ ViewGroup parent = (ViewGroup) dragLayer.getParent();
+ FloatingWidgetView floatingView =
+ launcher.getViewCache().getView(R.layout.floating_widget_view, launcher, parent);
+ floatingView.recycle();
+
+ floatingView.init(dragLayer, originalView, widgetBackgroundPosition, windowTargetBounds,
+ windowCornerRadius);
+ parent.addView(floatingView);
+ return floatingView;
+ }
+
+ private static void getRelativePosition(View descendant, View ancestor, RectF position) {
+ float[] points = new float[]{0, 0, descendant.getWidth(), descendant.getHeight()};
+ Utilities.getDescendantCoordRelativeToAncestor(descendant, ancestor, points,
+ false /* includeRootScroll */);
+ position.set(
+ Math.min(points[0], points[2]),
+ Math.min(points[1], points[3]),
+ Math.max(points[0], points[2]),
+ Math.max(points[1], points[3]));
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 0eb2392..e5ce950 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -42,9 +42,10 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
+import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
@@ -88,11 +89,13 @@
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ListView;
+import android.widget.OverScroller;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -116,14 +119,15 @@
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MultiValueAlpha;
-import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.TranslateEdgeEffect;
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseActivityInterface;
@@ -137,11 +141,10 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.ViewUtils;
-import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitScreenBounds;
+import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -158,6 +161,7 @@
import com.android.wm.shell.pip.IPipAnimationListener;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -297,6 +301,9 @@
}
};
+ // OverScroll constants
+ private static final int OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION = 270;
+
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
@@ -315,9 +322,13 @@
protected final Rect mTempRect = new Rect();
protected final RectF mTempRectF = new RectF();
private final PointF mTempPointF = new PointF();
+ private final float[] mTempFloat = new float[1];
+ private final List<OnScrollChangedListener> mScrollListeners = new ArrayList<>();
private float mFullscreenScale;
private static final int DISMISS_TASK_DURATION = 300;
+ private static final int DISMISS_TASK_TRANSLATION_DURATION = 200;
+ private static final int ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION = 75;
private static final int ADDITION_TASK_DURATION = 200;
// The threshold at which we update the SystemUI flags when animating from the task into the app
public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
@@ -355,11 +366,12 @@
protected float mTaskViewsPrimaryTranslation = 0;
// Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
private float mGridProgress = 0;
+ private final IntSet mTopRowIdSet = new IntSet();
// The GestureEndTarget that is still in progress.
protected GestureState.GestureEndTarget mCurrentGestureEndTarget;
- IntSet mTopIdSet = new IntSet();
+ private int mOverScrollShift = 0;
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
@@ -438,7 +450,6 @@
private boolean mRunningTaskIconScaledDown = false;
- private final boolean mHasLightBackground;
private boolean mOverviewStateEnabled;
private boolean mHandleTaskStackChanges;
private boolean mSwipeDownShouldLaunchApp;
@@ -572,8 +583,6 @@
mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
mLiveTileTaskViewSimulator.setOrientationState(mOrientationState);
mLiveTileTaskViewSimulator.setDrawsBelowRecents(true);
-
- mHasLightBackground = Themes.getAttrBoolean(mActivity, android.R.attr.isLightTheme);
}
public OverScroller getScroller() {
@@ -585,6 +594,72 @@
}
@Override
+ protected void initEdgeEffect() {
+ mEdgeGlowLeft = new TranslateEdgeEffect(getContext());
+ mEdgeGlowRight = new TranslateEdgeEffect(getContext());
+ }
+
+ @Override
+ protected void drawEdgeEffect(Canvas canvas) {
+ // Do not draw edge effect
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ // Draw overscroll
+ if (mAllowOverScroll && (!mEdgeGlowRight.isFinished() || !mEdgeGlowLeft.isFinished())) {
+ final int restoreCount = canvas.save();
+ final int width = getWidth();
+ final int height = getHeight();
+ int primarySize = mOrientationHandler.getPrimaryValue(width, height);
+ int secondarySize = mOrientationHandler.getSecondaryValue(width, height);
+
+ float effectiveShift = 0;
+ if (!mEdgeGlowLeft.isFinished()) {
+ mEdgeGlowLeft.setSize(secondarySize, primarySize);
+ if (((TranslateEdgeEffect) mEdgeGlowLeft).getTranslationShift(mTempFloat)) {
+ effectiveShift = mTempFloat[0];
+ postInvalidateOnAnimation();
+ }
+ }
+ if (!mEdgeGlowRight.isFinished()) {
+ mEdgeGlowRight.setSize(secondarySize, primarySize);
+ if (((TranslateEdgeEffect) mEdgeGlowRight).getTranslationShift(mTempFloat)) {
+ effectiveShift -= mTempFloat[0];
+ postInvalidateOnAnimation();
+ }
+ }
+
+ int scroll = OverScroll.dampedScroll(effectiveShift * primarySize, primarySize);
+ mOrientationHandler.set(canvas, CANVAS_TRANSLATE, scroll);
+
+ if (mOverScrollShift != scroll) {
+ mOverScrollShift = scroll;
+ dispatchScrollChanged();
+ }
+
+ super.dispatchDraw(canvas);
+ canvas.restoreToCount(restoreCount);
+ } else {
+ if (mOverScrollShift != 0) {
+ mOverScrollShift = 0;
+ dispatchScrollChanged();
+ }
+ super.dispatchDraw(canvas);
+ }
+ if (LIVE_TILE.get() && mEnableDrawingLiveTile && mLiveTileParams.getTargetSet() != null) {
+ redrawLiveTile();
+ }
+ }
+
+ /**
+ * Returns the view shift due to overscroll
+ */
+ public int getOverScrollShift() {
+ return mOverScrollShift;
+ }
+
+ @Override
public Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) {
if (mHandleTaskStackChanges) {
TaskView taskView = getTaskView(taskId);
@@ -746,20 +821,24 @@
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
appAnimator.setInterpolator(ACCEL_DEACCEL);
- appAnimator.addUpdateListener(new MultiValueUpdateListener() {
- @Override
- public void onUpdate(float percent) {
- SurfaceParams.Builder builder = new SurfaceParams.Builder(
- apps[apps.length - 1].leash);
- Matrix matrix = new Matrix();
- matrix.postScale(percent, percent);
- matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
- mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
- builder.withAlpha(percent).withMatrix(matrix);
- surfaceApplier.scheduleApply(builder.build());
- }
+ appAnimator.addUpdateListener(valueAnimator -> {
+ float percent = valueAnimator.getAnimatedFraction();
+ SurfaceParams.Builder builder = new SurfaceParams.Builder(
+ apps[apps.length - 1].leash);
+ Matrix matrix = new Matrix();
+ matrix.postScale(percent, percent);
+ matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
+ mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
+ builder.withAlpha(percent).withMatrix(matrix);
+ surfaceApplier.scheduleApply(builder.build());
});
anim.play(appAnimator);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishRecentsAnimation(true /* toRecents */, null);
+ }
+ });
} else {
TaskViewUtils.composeRecentsLaunchAnimator(
anim, taskView, apps,
@@ -768,30 +847,6 @@
mActivity.getStateManager(), this,
getDepthController());
}
- anim.addListener(new AnimatorListenerAdapter(){
-
- @Override
- public void onAnimationEnd(Animator animator) {
- cleanUp(false);
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {
- cleanUp(true);
- }
-
- private void cleanUp(boolean canceled) {
- if (mRecentsAnimationController != null) {
- finishRecentsAnimation(false /* toRecents */, null /* onFinishComplete */);
- if (canceled) {
- mRecentsAnimationController = null;
- } else {
- mSizeStrategy.onLaunchTaskSuccess();
- }
- ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
- }
- }
- });
anim.start();
}
@@ -850,13 +905,6 @@
cancelSplitSelect(false);
}
}
-
- if (enabled) {
- mActivity.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, hasLightBackground());
- } else {
- mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
- }
}
/**
@@ -955,8 +1003,30 @@
}
@Override
- protected boolean snapToPageInFreeScroll() {
- return !showAsGrid();
+ protected void onNotSnappingToPageInFreeScroll() {
+ int finalPos = mScroller.getFinalX();
+ if (!showAsGrid() && finalPos > mMinScroll && finalPos < mMaxScroll) {
+ int firstPageScroll = getScrollForPage(!mIsRtl ? 0 : getPageCount() - 1);
+ int lastPageScroll = getScrollForPage(!mIsRtl ? getPageCount() - 1 : 0);
+
+ // If scrolling ends in the half of the added space that is closer to
+ // the end, settle to the end. Otherwise snap to the nearest page.
+ // If flinging past one of the ends, don't change the velocity as it
+ // will get stopped at the end anyway.
+ int pageSnapped = finalPos < (firstPageScroll + mMinScroll) / 2
+ ? mMinScroll
+ : finalPos > (lastPageScroll + mMaxScroll) / 2
+ ? mMaxScroll
+ : getScrollForPage(mNextPage);
+
+ mScroller.setFinalX(pageSnapped);
+ // Ensure the scroll/snap doesn't happen too fast;
+ int extraScrollDuration = OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION
+ - mScroller.getDuration();
+ if (extraScrollDuration > 0) {
+ mScroller.extendDuration(extraScrollDuration);
+ }
+ }
}
@Override
@@ -1165,24 +1235,26 @@
updateTaskSize();
// Update ActionsView position
- FrameLayout.LayoutParams layoutParams =
- (FrameLayout.LayoutParams) mActionsView.getLayoutParams();
- if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
- layoutParams.gravity = Gravity.BOTTOM;
- layoutParams.bottomMargin =
- dp.heightPx - mInsets.bottom - mLastComputedGridSize.bottom;
- layoutParams.leftMargin = mLastComputedTaskSize.left;
- layoutParams.rightMargin = dp.widthPx - mLastComputedTaskSize.right;
- // When in modal state, remove bottom margin to avoid covering content.
- mActionsView.setModalTransformY(layoutParams.bottomMargin);
- } else {
- layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- layoutParams.bottomMargin = 0;
- layoutParams.leftMargin = 0;
- layoutParams.rightMargin = 0;
- mActionsView.setModalTransformY(0);
+ if (mActionsView != null) {
+ FrameLayout.LayoutParams layoutParams =
+ (FrameLayout.LayoutParams) mActionsView.getLayoutParams();
+ if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
+ layoutParams.gravity = Gravity.BOTTOM;
+ layoutParams.bottomMargin =
+ dp.heightPx - mInsets.bottom - mLastComputedGridSize.bottom;
+ layoutParams.leftMargin = mLastComputedTaskSize.left;
+ layoutParams.rightMargin = dp.widthPx - mLastComputedTaskSize.right;
+ // When in modal state, remove bottom margin to avoid covering content.
+ mActionsView.setModalTransformY(layoutParams.bottomMargin);
+ } else {
+ layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ layoutParams.bottomMargin = 0;
+ layoutParams.leftMargin = 0;
+ layoutParams.rightMargin = 0;
+ mActionsView.setModalTransformY(0);
+ }
+ mActionsView.setLayoutParams(layoutParams);
}
- mActionsView.setLayoutParams(layoutParams);
}
/**
@@ -1195,26 +1267,23 @@
}
float accumulatedTranslationX = 0;
- float[] fullscreenTranslations = new float[taskCount];
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
taskView.updateTaskSize();
- fullscreenTranslations[i] += accumulatedTranslationX;
+ taskView.getPrimaryFullscreenTranslationProperty().set(taskView,
+ accumulatedTranslationX);
+ taskView.getSecondaryFullscreenTranslationProperty().set(taskView, 0f);
// Compensate space caused by TaskView scaling.
float widthDiff =
taskView.getLayoutParams().width * (1 - taskView.getFullscreenScale());
// Compensate page spacing widening caused by RecentsView scaling.
widthDiff += mPageSpacing * (1 - 1 / mFullscreenScale);
- float fullscreenTranslationX = mIsRtl ? widthDiff : -widthDiff;
- accumulatedTranslationX += fullscreenTranslationX;
+ accumulatedTranslationX += mIsRtl ? widthDiff : -widthDiff;
}
- for (int i = 0; i < taskCount; i++) {
- getTaskViewAt(i).setFullscreenTranslationX(fullscreenTranslations[i]);
- }
mClearAllButton.setFullscreenTranslationPrimary(accumulatedTranslationX);
- updateGridProperties(/*isTaskDismissal=*/false);
+ updateGridProperties();
}
public void getTaskSize(Rect outRect) {
@@ -1284,12 +1353,6 @@
// Update the high res thumbnail loader state
mModel.getThumbnailCache().getHighResLoadingState().setFlingingFast(isFlingingFast);
-
- mLiveTileTaskViewSimulator.setScroll(getScrollOffset());
- if (LIVE_TILE.get() && mEnableDrawingLiveTile
- && mLiveTileParams.getTargetSet() != null) {
- redrawLiveTile();
- }
return scrolling;
}
@@ -1437,12 +1500,19 @@
mTaskListChangeId = -1;
mFocusedTaskId = -1;
- mRecentsAnimationController = null;
+ if (mRecentsAnimationController != null) {
+ if (LIVE_TILE.get() && mEnableDrawingLiveTile) {
+ // We are still drawing the live tile, finish it now to clean up.
+ finishRecentsAnimation(true /* toRecents */, null);
+ } else {
+ mRecentsAnimationController = null;
+ }
+ }
mLiveTileParams.setTargetSet(null);
+ mLiveTileTaskViewSimulator.setDrawsBelowRecents(true);
unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
setCurrentPage(0);
- mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
LayoutUtils.setViewEnabled(mActionsView, true);
if (mOrientationState.setGestureActive(false)) {
updateOrientationHandler();
@@ -1516,8 +1586,9 @@
* {@link #onGestureAnimationStart} and {@link #onGestureAnimationEnd()}.
*/
public void onSwipeUpAnimationSuccess() {
+ Log.d("b/186444448", "onSwipeUpAnimationSuccess");
if (getRunningTaskView() != null) {
- animateUpRunningTaskIconScale(0f);
+ animateUpRunningTaskIconScale();
}
setSwipeDownShouldLaunchApp(true);
}
@@ -1572,7 +1643,7 @@
// When switching to tasks in quick switch, ensures the snapped page's scroll maintain
// invariant between quick switch and overview grid, to ensure a smooth animation
// transition.
- updateGridProperties(/*isTaskDismissal=*/false);
+ updateGridProperties();
}
}
@@ -1580,21 +1651,22 @@
* Called when a gesture from an app has finished, and the animation to the target has ended.
*/
public void onGestureAnimationEnd() {
+ Log.d("b/186444448", "onGestureEnd");
mGestureActive = false;
if (mOrientationState.setGestureActive(false)) {
updateOrientationHandler();
}
- setOnScrollChangeListener(null);
setEnableFreeScroll(true);
- setEnableDrawingLiveTile(true);
+ setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS);
if (!LIVE_TILE.get()) {
setRunningTaskViewShowScreenshot(true);
}
setRunningTaskHidden(false);
animateUpRunningTaskIconScale();
- if (!showAsGrid() || getFocusedTaskView() != null) {
+ if (mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS
+ && (!showAsGrid() || getFocusedTaskView() != null)) {
animateActionsViewIn();
}
@@ -1734,25 +1806,36 @@
}
public void animateUpRunningTaskIconScale() {
- animateUpRunningTaskIconScale(0);
- }
-
- public void animateUpRunningTaskIconScale(float startProgress) {
mRunningTaskIconScaledDown = false;
TaskView firstTask = getRunningTaskView();
+ Log.d("b/186444448", "animateUpRunningTaskIconScale: firstTask="
+ + (firstTask != null ? "t:" + firstTask.getTask() : null));
if (firstTask != null) {
+ firstTask.setIconScaleAnimStartProgress(0f);
firstTask.animateIconScaleAndDimIntoView();
- firstTask.setIconScaleAnimStartProgress(startProgress);
}
}
+ /** Updates TaskView and ClearAllButtion scaling and translation required to turn into grid
+ * layout.
+ * This method is used when no task dismissal has occurred.
+ */
+ private void updateGridProperties() {
+ updateGridProperties(null, -1);
+ }
+
/**
* Updates TaskView and ClearAllButton scaling and translation required to turn into grid
* layout.
* This method only calculates the potential position and depends on {@link #setGridProgress} to
- * apply the actual scaling and translation.
+ * apply the actual scaling and translation. This adds task translation animations in the case
+ * of task dismissals: e.g. when dismissedTask is not null.
+ *
+ * @param dismissedTask the TaskView dismissed, possibly null
+ * @param dismissedIndex the index at which the dismissedTask was prior to dismissal, if no
+ * dismissal occurred, this is unused
*/
- private void updateGridProperties(boolean isTaskDismissal) {
+ private void updateGridProperties(TaskView dismissedTask, int dismissedIndex) {
int taskCount = getTaskViewCount();
if (taskCount == 0) {
return;
@@ -1779,8 +1862,12 @@
int snappedPage = getNextPage();
TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(snappedPage);
+ boolean isTaskDismissal = dismissedTask != null;
+ float dismissedTaskWidth =
+ isTaskDismissal ? dismissedTask.getLayoutParams().width + mPageSpacing : 0;
+
if (!isTaskDismissal) {
- mTopIdSet.clear();
+ mTopRowIdSet.clear();
}
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
@@ -1815,13 +1902,14 @@
// calculate the distance focused task need to shift.
focusedTaskShift += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
}
- boolean isTopRow = isTaskDismissal ? mTopIdSet.contains(taskView.getTask().key.id)
+ int taskId = taskView.getTask().key.id;
+ boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId)
: topRowWidth <= bottomRowWidth;
if (isTopRow) {
gridTranslations[i] += topAccumulatedTranslationX;
topRowWidth += taskWidthAndSpacing;
topSet.add(i);
- mTopIdSet.add(taskView.getTask().key.id);
+ mTopRowIdSet.add(taskId);
taskView.setGridTranslationY(taskGridVerticalDiff);
@@ -1875,17 +1963,38 @@
snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
}
-
+ // Animate task dismissTranslationX for tasks with index >= dismissed index and in the
+ // same row as the dismissed index, or if the dismissed task was the focused task. Offset
+ // successive task dismissal durations for a staggered effect.
+ ArrayList<Animator> gridTranslationAnimators = new ArrayList<>();
+ boolean isFocusedTaskDismissed =
+ isTaskDismissal && dismissedTask.getTask().key.id == mFocusedTaskId;
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
+ if (isFocusedTaskDismissed || (i >= dismissedIndex && isSameGridRow(dismissedTask,
+ taskView))) {
+ Animator taskDismissAnimator = ObjectAnimator.ofFloat(taskView,
+ taskView.getPrimaryDismissTranslationProperty(),
+ mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, 0f);
+ int additionalTranslationDuration =
+ i >= dismissedIndex ? (ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION * (
+ (i - dismissedIndex) / 2)) : 0;
+ taskDismissAnimator.setDuration(
+ DISMISS_TASK_TRANSLATION_DURATION + additionalTranslationDuration);
+ gridTranslationAnimators.add(taskDismissAnimator);
+ }
taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX);
- taskView.setNonFullscreenTranslationX(snappedTaskFullscreenScrollAdjustment);
+ taskView.getPrimaryNonFullscreenTranslationProperty().set(taskView,
+ snappedTaskFullscreenScrollAdjustment);
+ taskView.getSecondaryNonFullscreenTranslationProperty().set(taskView, 0f);
}
+ AnimatorSet gridTranslationAnimatorSet = new AnimatorSet();
+ gridTranslationAnimatorSet.playTogether(gridTranslationAnimators);
+ gridTranslationAnimatorSet.start();
- // Use the accumulated translation of the longer row.
- float clearAllAccumulatedTranslation = mIsRtl ? Math.max(topAccumulatedTranslationX,
- bottomAccumulatedTranslationX) : Math.min(topAccumulatedTranslationX,
- bottomAccumulatedTranslationX);
+ // Use the accumulated translation of the row containing the last task.
+ float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1)
+ ? topAccumulatedTranslationX : bottomAccumulatedTranslationX;
// If the last task is on the shorter row, ClearAllButton will embed into the shorter row
// which is not what we want. Compensate the width difference of the 2 rows in that case.
@@ -1903,13 +2012,14 @@
mIsRtl ? -shorterRowCompensation : shorterRowCompensation;
// If the total width is shorter than one grid's width, move ClearAllButton further away
- // accordingly.
+ // accordingly. Update longRowWidth if ClearAllButton has been moved.
float clearAllShortTotalCompensation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
if (longRowWidth < mLastComputedGridSize.width()) {
float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
clearAllShortTotalCompensation =
mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
+ longRowWidth = mLastComputedGridSize.width();
}
float clearAllTotalTranslationX =
@@ -1942,6 +2052,19 @@
setGridProgress(mGridProgress);
}
+ private boolean isSameGridRow(TaskView taskView1, TaskView taskView2) {
+ if (taskView1 == null || taskView2 == null) {
+ return false;
+ }
+ int taskId1 = taskView1.getTask().key.id;
+ int taskId2 = taskView2.getTask().key.id;
+ if (taskId1 == mFocusedTaskId || taskId2 == mFocusedTaskId) {
+ return false;
+ }
+ return (mTopRowIdSet.contains(taskId1) && mTopRowIdSet.contains(taskId2)) || (
+ !mTopRowIdSet.contains(taskId1) && !mTopRowIdSet.contains(taskId2));
+ }
+
/**
* Moves TaskView and ClearAllButton between carousel and 2 row grid.
*
@@ -2152,8 +2275,12 @@
}
int pageToSnapTo = mCurrentPage;
- if (draggedIndex < pageToSnapTo ||
- pageToSnapTo == (getTaskViewCount() - 1)) {
+ // Snap to start if focused task was dismissed, as after quick switch it could
+ // be at any page but the focused task always displays at the start.
+ if (taskView.getTask().key.id == mFocusedTaskId) {
+ pageToSnapTo = mTaskViewStartIndex;
+ } else if (draggedIndex < pageToSnapTo || pageToSnapTo == (getTaskViewCount()
+ - 1)) {
pageToSnapTo -= 1;
}
removeViewInLayout(taskView);
@@ -2164,8 +2291,9 @@
} else {
snapToPageImmediately(pageToSnapTo);
// Grid got messed up, reapply.
- updateGridProperties(/*isTaskDismissal=*/true);
- if (showAsGrid() && getFocusedTaskView() == null) {
+ updateGridProperties(taskView, draggedIndex - mTaskViewStartIndex);
+ if (showAsGrid() && getFocusedTaskView() == null
+ && mActionsView.getVisibilityAlpha().getValue() == 1) {
animateActionsViewOut();
}
}
@@ -2173,7 +2301,9 @@
// immediately available.
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
}
- resetTaskVisuals();
+ if (!showAsGrid()) {
+ resetTaskVisuals();
+ }
onDismissAnimationEnds();
mPendingAnimation = null;
}
@@ -2533,6 +2663,10 @@
? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
: mOrientationHandler.getPrimaryViewTranslate();
translationProperty.set(child, totalTranslation);
+ if (LIVE_TILE.get() && mEnableDrawingLiveTile && i == getRunningTaskIndex()) {
+ mLiveTileTaskViewSimulator.taskPrimaryTranslation.value = totalTranslation;
+ redrawLiveTile();
+ }
}
updateCurveProperties();
}
@@ -2656,19 +2790,16 @@
}
}
- /**
- * True if the background scrim of the recents view is light colored and the foreground elements
- * should use dark colors.
- */
- public boolean hasLightBackground() {
- return mHasLightBackground;
- }
-
public void initiateSplitSelect(TaskView taskView, SplitPositionOption splitPositionOption) {
mSplitHiddenTaskView = taskView;
- mSplitPlaceholderView.getSplitController().setInitialTaskSelect(taskView,
+ SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
+ splitController.setInitialTaskSelect(taskView,
splitPositionOption);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
+ mSplitPlaceholderView.setLayoutParams(
+ splitController.getLayoutParamsForActivePosition(getResources(),
+ mActivity.getDeviceProfile()));
+ mSplitPlaceholderView.setIcon(taskView.getIconView());
}
public PendingAnimation createSplitSelectInitAnimation() {
@@ -2909,10 +3040,9 @@
// tasks' flags
if (animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD) {
mActivity.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, targetSysUiFlags);
+ UI_STATE_FULLSCREEN_TASK, targetSysUiFlags);
} else {
- mActivity.getSystemUiController().updateUiState(
- UI_STATE_OVERVIEW, hasLightBackground());
+ mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
// Passing the threshold from taskview to fullscreen app will vibrate
@@ -3085,6 +3215,7 @@
// typical example of this is (1) user swipes up from app to Overview (2) user
// taps on QSB (3) user goes back to Overview and launch the most recent task.
setCurrentTask(-1);
+ mRecentsAnimationController = null;
});
}
@@ -3147,18 +3278,20 @@
@Override
protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren,
ComputePageScrollsLogic scrollLogic) {
- boolean pageScrollChanged = super.getPageScrolls(outPageScrolls, layoutChildren,
- scrollLogic);
+ int[] newPageScrolls = new int[outPageScrolls.length];
+ super.getPageScrolls(newPageScrolls, layoutChildren, scrollLogic);
boolean showAsFullscreen = showAsFullscreen();
boolean showAsGrid = showAsGrid();
// Align ClearAllButton to the left (RTL) or right (non-RTL), which is different from other
// TaskViews. This must be called after laying out ClearAllButton.
if (layoutChildren) {
- int clearAllWidthDiff = mTaskWidth - mClearAllButton.getWidth();
+ int clearAllWidthDiff = mOrientationHandler.getPrimaryValue(mTaskWidth, mTaskHeight)
+ - mOrientationHandler.getPrimarySize(mClearAllButton);
mClearAllButton.setScrollOffsetPrimary(mIsRtl ? clearAllWidthDiff : -clearAllWidthDiff);
}
+ boolean pageScrollChanged = false;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -3170,9 +3303,10 @@
showAsGrid);
}
- if (scrollDiff != 0) {
- outPageScrolls[i] += scrollDiff;
+ final int pageScroll = newPageScrolls[i] + (int) scrollDiff;
+ if (outPageScrolls[i] != pageScroll) {
pageScrollChanged = true;
+ outPageScrolls[i] = pageScroll;
}
}
return pageScrollChanged;
@@ -3206,13 +3340,6 @@
return mClearAllButton;
}
- @Override
- protected boolean onOverscroll(int amount) {
- // overscroll should only be accepted on -1 direction (for clear all button)
- if ((amount > 0 && !mIsRtl) || (amount < 0 && mIsRtl)) return false;
- return super.onOverscroll(amount);
- }
-
/**
* @return How many pixels the running task is offset on the currently laid out dominant axis.
*/
@@ -3227,14 +3354,8 @@
if (pageIndex == -1) {
return 0;
}
- // Unbound the scroll (due to overscroll) if the adjacent tasks are offset away from it.
- // This allows the page to move freely, given there's no visual indication why it shouldn't.
- int boundedScroll = mOrientationHandler.getPrimaryScroll(this);
- int unboundedScroll = getUnboundedScroll();
- float unboundedProgress = mAdjacentPageOffset;
- int scroll = Math.round(unboundedScroll * unboundedProgress
- + boundedScroll * (1 - unboundedProgress));
- return getScrollForPage(pageIndex) - scroll;
+ return getScrollForPage(pageIndex) - mOrientationHandler.getPrimaryScroll(this)
+ + getOverScrollShift();
}
/**
@@ -3420,6 +3541,33 @@
void onEmptyMessageUpdated(boolean isEmpty);
}
+ /**
+ * Adds a listener for scroll changes
+ */
+ public void addOnScrollChangedListener(OnScrollChangedListener listener) {
+ mScrollListeners.add(listener);
+ }
+
+ /**
+ * Removes a previously added scroll change listener
+ */
+ public void removeOnScrollChangedListener(OnScrollChangedListener listener) {
+ mScrollListeners.remove(listener);
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ dispatchScrollChanged();
+ }
+
+ private void dispatchScrollChanged() {
+ mLiveTileTaskViewSimulator.setScroll(getScrollOffset());
+ for (int i = mScrollListeners.size() - 1; i >= 0; i--) {
+ mScrollListeners.get(i).onScrollChanged();
+ }
+ }
+
private static class PinnedStackAnimationListener<T extends BaseActivity> extends
IPipAnimationListener.Stub {
private T mActivity;
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index fb9be81..bb8bc11 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -19,11 +19,12 @@
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatProperty;
-import android.view.View;
+import android.view.Gravity;
+import android.widget.FrameLayout;
import com.android.quickstep.util.SplitSelectStateController;
-public class SplitPlaceholderView extends View {
+public class SplitPlaceholderView extends FrameLayout {
public static final FloatProperty<SplitPlaceholderView> ALPHA_FLOAT =
new FloatProperty<SplitPlaceholderView>("SplitViewAlpha") {
@@ -40,6 +41,7 @@
};
private SplitSelectStateController mSplitController;
+ private IconView mIcon;
public SplitPlaceholderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -52,4 +54,15 @@
public SplitSelectStateController getSplitController() {
return mSplitController;
}
+
+ public void setIcon(IconView icon) {
+ if (mIcon == null) {
+ mIcon = new IconView(getContext());
+ addView(mIcon);
+ }
+ mIcon.setDrawable(icon.getDrawable());
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(icon.getLayoutParams());
+ params.gravity = Gravity.CENTER;
+ mIcon.setLayoutParams(params);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 658d71d..32cd367 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -121,7 +121,7 @@
};
}
- private void setPosition(float x, float y) {
+ private void setPosition(float x, float y, int overscrollShift) {
PagedOrientationHandler pagedOrientationHandler = mTaskView.getPagedOrientationHandler();
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
float adjustedY = y + taskTopMargin;
@@ -136,8 +136,9 @@
setPivotY(0);
}
setRotation(pagedOrientationHandler.getDegreesRotated());
- setX(pagedOrientationHandler.getTaskMenuX(x, mTaskView.getThumbnail()));
- setY(pagedOrientationHandler.getTaskMenuY(adjustedY, mTaskView.getThumbnail()));
+ setX(pagedOrientationHandler.getTaskMenuX(x, mTaskView.getThumbnail(), overscrollShift));
+ setY(pagedOrientationHandler.getTaskMenuY(
+ adjustedY, mTaskView.getThumbnail(), overscrollShift));
}
public void onRotationChanged() {
@@ -169,14 +170,15 @@
return false;
}
post(this::animateOpen);
- mActivity.getRootView().getViewTreeObserver().addOnScrollChangedListener(this);
+ ((RecentsView) mActivity.getOverviewPanel()).addOnScrollChangedListener(this);
return true;
}
@Override
public void onScrollChanged() {
RecentsView rv = mTaskView.getRecentsView();
- setPosition(mTaskView.getX() - rv.getScrollX(), mTaskView.getY() - rv.getScrollY());
+ setPosition(mTaskView.getX() - rv.getScrollX(), mTaskView.getY() - rv.getScrollY(),
+ rv.getOverScrollShift());
}
/** @return true if successfully able to populate task view menu, false otherwise */
@@ -199,12 +201,13 @@
}
private void addMenuOption(SystemShortcut menuOption) {
- ViewGroup menuOptionView = (ViewGroup) mActivity.getLayoutInflater().inflate(
+ LinearLayout menuOptionView = (LinearLayout) mActivity.getLayoutInflater().inflate(
R.layout.task_view_menu_option, this, false);
menuOption.setIconAndLabelFor(
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams();
- mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp);
+ mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp,
+ menuOptionView, mActivity.getDeviceProfile());
menuOptionView.setEnabled(menuOption.isEnabled());
menuOptionView.setAlpha(menuOption.isEnabled() ? 1 : 0.5f);
menuOptionView.setOnClickListener(view -> {
@@ -226,17 +229,16 @@
mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
Rect insets = mActivity.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
+ // TODO(b/186583656) Move the entire menu to the center/make smaller than thumbnail width
params.width = orientationHandler.getTaskMenuWidth(taskView.getThumbnail());
// Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
params.gravity = Gravity.LEFT;
setLayoutParams(params);
setScaleX(taskView.getScaleX());
setScaleY(taskView.getScaleY());
- boolean canActivityRotate = taskView.getRecentsView()
- .mOrientationState.isRecentsActivityRotationAllowed();
- mOptionLayout.setOrientation(orientationHandler
- .getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout));
- setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top);
+ orientationHandler.setTaskMenuLayoutOrientation(
+ mActivity.getDeviceProfile(), mOptionLayout);
+ setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top, 0);
}
private void animateOpen() {
@@ -282,7 +284,7 @@
private void closeComplete() {
mIsOpen = false;
mActivity.getDragLayer().removeView(this);
- mActivity.getRootView().getViewTreeObserver().removeOnScrollChangedListener(this);
+ ((RecentsView) mActivity.getOverviewPanel()).removeOnScrollChangedListener(this);
}
private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 8f22622..3349b74 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -250,6 +250,58 @@
}
};
+ private static final FloatProperty<TaskView> FULLSCREEN_TRANSLATION_X =
+ new FloatProperty<TaskView>("fullscreenTranslationX") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setFullscreenTranslationX(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFullscreenTranslationX;
+ }
+ };
+
+ private static final FloatProperty<TaskView> FULLSCREEN_TRANSLATION_Y =
+ new FloatProperty<TaskView>("fullscreenTranslationY") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setFullscreenTranslationY(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFullscreenTranslationY;
+ }
+ };
+
+ private static final FloatProperty<TaskView> NON_FULLSCREEN_TRANSLATION_X =
+ new FloatProperty<TaskView>("nonFullscreenTranslationX") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setNonFullscreenTranslationX(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mNonFullscreenTranslationX;
+ }
+ };
+
+ private static final FloatProperty<TaskView> NON_FULLSCREEN_TRANSLATION_Y =
+ new FloatProperty<TaskView>("nonFullscreenTranslationY") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setNonFullscreenTranslationY(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mNonFullscreenTranslationY;
+ }
+ };
+
private static final FloatProperty<TaskView> COLOR_TINT =
new FloatProperty<TaskView>("colorTint") {
@Override
@@ -284,9 +336,11 @@
private float mTaskResistanceTranslationY;
// The following translation variables should only be used in the same orientation as Launcher.
private float mFullscreenTranslationX;
+ private float mFullscreenTranslationY;
// Applied as a complement to fullscreenTranslation, for adjusting the carousel overview, or the
// in transition carousel before forming the grid on tablets.
private float mNonFullscreenTranslationX;
+ private float mNonFullscreenTranslationY;
private float mBoxTranslationY;
// The following grid translations scales with mGridProgress.
private float mGridTranslationX;
@@ -484,7 +538,6 @@
mIsClickableAsLiveTile = false;
RecentsView recentsView = getRecentsView();
RemoteAnimationTargets targets = recentsView.getLiveTileParams().getTargetSet();
- recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(false);
AnimatorSet anim = new AnimatorSet();
TaskViewUtils.composeRecentsLaunchAnimator(
@@ -494,9 +547,12 @@
recentsView.getDepthController());
anim.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animator) {
+ recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(false);
+ }
+
+ @Override
public void onAnimationEnd(Animator animator) {
- recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(true);
- recentsView.finishRecentsAnimation(false, null);
mIsClickableAsLiveTile = true;
}
});
@@ -521,7 +577,7 @@
if (mTask != null) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
- ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this);
+ ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this, null);
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
return opts.onEndCallback;
@@ -738,6 +794,8 @@
}
public void animateIconScaleAndDimIntoView() {
+ Log.d("b/186444448", "animateIconScaleAndDimIntoView: startProgress="
+ + mIconScaleAnimStartProgress);
if (mIconAndDimAnimator != null) {
mIconAndDimAnimator.cancel();
}
@@ -747,6 +805,7 @@
mIconAndDimAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ Log.d("b/186444448", "animateIconScaleAndDimIntoView: end");
mIconAndDimAnimator = null;
}
});
@@ -784,8 +843,9 @@
@Override
public void onRecycle() {
- mFullscreenTranslationX = mNonFullscreenTranslationX =
- mGridTranslationX = mGridTranslationY = mBoxTranslationY = 0f;
+ mFullscreenTranslationX = mFullscreenTranslationY = mNonFullscreenTranslationX =
+ mNonFullscreenTranslationY = mGridTranslationX = mGridTranslationY =
+ mBoxTranslationY = 0f;
resetViewTransforms();
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
@@ -927,16 +987,26 @@
applyTranslationY();
}
- public void setFullscreenTranslationX(float fullscreenTranslationX) {
+ private void setFullscreenTranslationX(float fullscreenTranslationX) {
mFullscreenTranslationX = fullscreenTranslationX;
applyTranslationX();
}
- public void setNonFullscreenTranslationX(float nonFullscreenTranslationX) {
+ private void setFullscreenTranslationY(float fullscreenTranslationY) {
+ mFullscreenTranslationY = fullscreenTranslationY;
+ applyTranslationY();
+ }
+
+ private void setNonFullscreenTranslationX(float nonFullscreenTranslationX) {
mNonFullscreenTranslationX = nonFullscreenTranslationX;
applyTranslationX();
}
+ private void setNonFullscreenTranslationY(float nonFullscreenTranslationY) {
+ mNonFullscreenTranslationY = nonFullscreenTranslationY;
+ applyTranslationY();
+ }
+
public void setGridTranslationX(float gridTranslationX) {
mGridTranslationX = gridTranslationX;
applyTranslationX();
@@ -958,9 +1028,9 @@
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
float scrollAdjustment = 0;
if (fullscreenEnabled) {
- scrollAdjustment += mFullscreenTranslationX;
+ scrollAdjustment += getPrimaryFullscreenTranslationProperty().get(this);
} else {
- scrollAdjustment += mNonFullscreenTranslationX;
+ scrollAdjustment += getPrimaryNonFullscreenTranslationProperty().get(this);
}
if (gridEnabled) {
scrollAdjustment += mGridTranslationX;
@@ -1010,7 +1080,10 @@
* change according to a temporary state (e.g. task offset).
*/
public float getPersistentTranslationY() {
- return getGridTrans(mGridTranslationY) + mBoxTranslationY;
+ return mBoxTranslationY
+ + getFullscreenTrans(mFullscreenTranslationY)
+ + getNonFullscreenTrans(mNonFullscreenTranslationY)
+ + getGridTrans(mGridTranslationY);
}
public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
@@ -1033,6 +1106,26 @@
TASK_RESISTANCE_TRANSLATION_X, TASK_RESISTANCE_TRANSLATION_Y);
}
+ public FloatProperty<TaskView> getPrimaryFullscreenTranslationProperty() {
+ return getPagedOrientationHandler().getPrimaryValue(
+ FULLSCREEN_TRANSLATION_X, FULLSCREEN_TRANSLATION_Y);
+ }
+
+ public FloatProperty<TaskView> getSecondaryFullscreenTranslationProperty() {
+ return getPagedOrientationHandler().getSecondaryValue(
+ FULLSCREEN_TRANSLATION_X, FULLSCREEN_TRANSLATION_Y);
+ }
+
+ public FloatProperty<TaskView> getPrimaryNonFullscreenTranslationProperty() {
+ return getPagedOrientationHandler().getPrimaryValue(
+ NON_FULLSCREEN_TRANSLATION_X, NON_FULLSCREEN_TRANSLATION_Y);
+ }
+
+ public FloatProperty<TaskView> getSecondaryNonFullscreenTranslationProperty() {
+ return getPagedOrientationHandler().getSecondaryValue(
+ NON_FULLSCREEN_TRANSLATION_X, NON_FULLSCREEN_TRANSLATION_Y);
+ }
+
@Override
public boolean hasOverlappingRendering() {
// TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 713fd07..88f1850 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -139,10 +139,6 @@
TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE, startTime.toString()).
getString("result"));
}
- // b/143488140
- mDevice.pressHome();
- mDevice.waitForIdle();
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
}
// b/143488140
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 0fe5432..a700e16 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Intent;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -36,6 +37,7 @@
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.views.RecentsView;
@@ -187,10 +189,12 @@
@NavigationModeSwitch
@PortraitLandscape
public void testSwitchToOverview() throws Exception {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "testSwitchToOverview");
assertNotNull("Workspace.switchToOverview() returned null",
mLauncher.pressHome().switchToOverview());
assertTrue("Launcher internal state didn't switch to Overview",
isInState(() -> LauncherState.OVERVIEW));
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "testSwitchToOverview finished");
}
@Test
diff --git a/res/color-night-v31/widgets_picker_surface.xml b/res/color-night-v31/widgets_picker_surface.xml
new file mode 100644
index 0000000..fbc9e43
--- /dev/null
+++ b/res/color-night-v31/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, 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.
+*/
+-->
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_800" />
+</selector>
diff --git a/res/color-v31/overview_scrim.xml b/res/color-v31/overview_scrim.xml
new file mode 100644
index 0000000..8079995
--- /dev/null
+++ b/res/color-v31/overview_scrim.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral2_500" android:lStar="87" />
+</selector>
diff --git a/res/color-v31/overview_scrim_dark.xml b/res/color-v31/overview_scrim_dark.xml
new file mode 100644
index 0000000..b8ed774
--- /dev/null
+++ b/res/color-v31/overview_scrim_dark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_800" />
+</selector>
diff --git a/res/color-v31/widgets_picker_surface.xml b/res/color-v31/widgets_picker_surface.xml
new file mode 100644
index 0000000..30f3032
--- /dev/null
+++ b/res/color-v31/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, 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.
+*/
+-->
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_500" android:lStar="98"/>
+</selector>
diff --git a/res/color/overview_scrim.xml b/res/color/overview_scrim.xml
new file mode 100644
index 0000000..48cf576
--- /dev/null
+++ b/res/color/overview_scrim.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#30000000" />
+</selector>
diff --git a/res/color/overview_scrim_dark.xml b/res/color/overview_scrim_dark.xml
new file mode 100644
index 0000000..48cf576
--- /dev/null
+++ b/res/color/overview_scrim_dark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#30000000" />
+</selector>
diff --git a/res/color/widgets_picker_surface.xml b/res/color/widgets_picker_surface.xml
new file mode 100644
index 0000000..6150110
--- /dev/null
+++ b/res/color/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, 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.
+*/
+-->
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorBackgroundFloating" />
+</selector>
diff --git a/res/drawable/widgets_list_bottom_ripple.xml b/res/drawable/widgets_list_bottom_ripple.xml
index 3a26091..72262d4 100644
--- a/res/drawable/widgets_list_bottom_ripple.xml
+++ b/res/drawable/widgets_list_bottom_ripple.xml
@@ -30,7 +30,7 @@
</item>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/widgets_picker_surface" />
<corners
android:topLeftRadius="@dimen/widget_list_content_corner_radius"
android:topRightRadius="@dimen/widget_list_content_corner_radius"
diff --git a/res/drawable/widgets_list_middle_ripple.xml b/res/drawable/widgets_list_middle_ripple.xml
index da025d7..1136bea 100644
--- a/res/drawable/widgets_list_middle_ripple.xml
+++ b/res/drawable/widgets_list_middle_ripple.xml
@@ -31,7 +31,7 @@
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/widgets_picker_surface" />
<corners
android:topLeftRadius="@dimen/widget_list_content_corner_radius"
android:topRightRadius="@dimen/widget_list_content_corner_radius"
diff --git a/res/drawable/widgets_list_single_item_ripple.xml b/res/drawable/widgets_list_single_item_ripple.xml
index b8b6f42..a82918e 100644
--- a/res/drawable/widgets_list_single_item_ripple.xml
+++ b/res/drawable/widgets_list_single_item_ripple.xml
@@ -30,7 +30,7 @@
</item>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/widgets_picker_surface" />
<corners
android:topLeftRadius="@dimen/widget_list_top_bottom_corner_radius"
android:topRightRadius="@dimen/widget_list_top_bottom_corner_radius"
diff --git a/res/drawable/widgets_list_top_ripple.xml b/res/drawable/widgets_list_top_ripple.xml
index 6efc3e1..4ad185c 100644
--- a/res/drawable/widgets_list_top_ripple.xml
+++ b/res/drawable/widgets_list_top_ripple.xml
@@ -31,7 +31,7 @@
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?android:attr/colorBackground" />
+ <solid android:color="@color/widgets_picker_surface" />
<corners
android:topLeftRadius="@dimen/widget_list_top_bottom_corner_radius"
android:topRightRadius="@dimen/widget_list_top_bottom_corner_radius"
diff --git a/res/drawable/widgets_recommendation_background.xml b/res/drawable/widgets_recommendation_background.xml
new file mode 100644
index 0000000..b59de27
--- /dev/null
+++ b/res/drawable/widgets_recommendation_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<shape android:shape="rectangle"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/widgets_picker_surface" />
+ <corners android:radius="@dimen/widget_list_top_bottom_corner_radius"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/floating_widget_view.xml b/res/layout/floating_widget_view.xml
new file mode 100644
index 0000000..eea7a92
--- /dev/null
+++ b/res/layout/floating_widget_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.quickstep.views.FloatingWidgetView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layoutDirection="ltr" />
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index f34e685..039d8d3 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -66,8 +66,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/scrim_view"
- android:background="?attr/allAppsScrimColor"
- android:alpha="0" />
+ android:background="@android:color/transparent" />
<include
android:id="@+id/apps_view"
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index 172284b..a01aa2c 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -25,7 +25,7 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?android:attr/colorBackgroundFloating"
+ android:background="?android:attr/colorBackground"
android:elevation="4dp">
<TextView
diff --git a/res/layout/widgets_full_sheet_search_and_recommendations.xml b/res/layout/widgets_full_sheet_search_and_recommendations.xml
index e5df175..bfce01d 100644
--- a/res/layout/widgets_full_sheet_search_and_recommendations.xml
+++ b/res/layout/widgets_full_sheet_search_and_recommendations.xml
@@ -20,7 +20,8 @@
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:layout_marginBottom="16dp"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:clipToPadding="false">
<View
android:id="@+id/collapse_handle"
android:layout_width="48dp"
@@ -44,6 +45,8 @@
android:id="@+id/recommended_widget_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@drawable/widgets_recommendation_background"
+ android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding"
android:layout_marginTop="16dp"
- android:visibility="gone" />
+ android:visibility="gone"/>
</LinearLayout>
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 8259c16..f20af87 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -19,7 +19,7 @@
android:id="@+id/widgets_list_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="8dp"
+ android:layout_marginHorizontal="16dp"
android:background="@drawable/widgets_list_middle_ripple"
android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
@@ -35,6 +35,7 @@
tools:src="@drawable/ic_corp"/>
<LinearLayout
+ android:id="@+id/app_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index 0b5f0b9..e63483d 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -18,6 +18,6 @@
android:id="@+id/widgets_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="8dp"
+ android:layout_marginHorizontal="16dp"
android:background="@drawable/widgets_list_middle_ripple"
android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"/>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 08605ef..31ac27f 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -97,8 +97,8 @@
<string name="folder_name_format_exact" msgid="8626242716117004803">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা বস্তু"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা অথবা তাতকৈ অধিক বস্তু"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ৱালপেপাৰসমূহ"</string>
- <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ষ্টাইল & ৱালপেপাৰ"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিংসমূহ"</string>
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"শৈলী আৰু ৱালপেপাৰ"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিং"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ফ\'নটো যেতিয়া ঘূৰোৱা হয়"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 20821d3..c2d9946 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -115,7 +115,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Змяніць налады"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Паказваць значкі апавяшчэнняў"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Дадаць значкі праграм на Галоўны экран"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Дадаваць значкі праграм на Галоўны экран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для новых праграм"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невядома"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Выдаліць"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index ac7c84b..c49dce5 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -109,7 +109,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra els punts de notificació"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Afegeix icones a la pantalla d\'inici"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Afegeix icones d\'aplicacions a la pantalla d\'inici"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per a les aplicacions noves"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index a742f2f..a7f9908 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -116,7 +116,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"Změnit nastavení"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Zobrazovat puntíky s oznámením"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Přidat na plochu ikony aplikací"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pro nové aplikace"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"U nových aplikací"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
<string name="abandoned_search" msgid="891119232568284442">"Hledat"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 63e5192..77ddc86 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -26,47 +26,39 @@
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Heruntergeladene App im abgesicherten Modus deaktiviert"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets im abgesicherten Modus deaktiviert"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"Verknüpfung nicht verfügbar"</string>
- <!-- no translation found for home_screen (5629429142036709174) -->
- <skip />
- <!-- no translation found for recent_task_option_split_screen (6690461455618725183) -->
- <skip />
- <!-- no translation found for long_press_widget_to_add (3587712543577675817) -->
- <skip />
- <!-- no translation found for long_accessible_way_to_add (2733588281439571974) -->
- <skip />
+ <string name="home_screen" msgid="5629429142036709174">"Startbildschirm"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Splitscreen"</string>
+ <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tippen und halten, um ein Widget zu bewegen."</string>
+ <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Doppeltippen und halten, um ein Widget zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breit und %2$d hoch"</string>
<string name="add_item_request_drag_hint" msgid="5899764264480397019">"Zum manuellen Hinzufügen gedrückt halten"</string>
<string name="place_automatically" msgid="8064208734425456485">"Automatisch hinzufügen"</string>
- <!-- no translation found for widgets_count (656794749266073027) -->
- <!-- no translation found for shortcuts_count (8080294865447938455) -->
- <!-- no translation found for widgets_and_shortcuts_count (7209136747878365116) -->
- <skip />
+ <plurals name="widgets_count" formatted="false" msgid="656794749266073027">
+ <item quantity="other"><xliff:g id="WIDGETS_COUNT_1">%1$d</xliff:g> Widgets</item>
+ <item quantity="one"><xliff:g id="WIDGETS_COUNT_0">%1$d</xliff:g> Widget</item>
+ </plurals>
+ <plurals name="shortcuts_count" formatted="false" msgid="8080294865447938455">
+ <item quantity="other"><xliff:g id="SHORTCUTS_COUNT_1">%1$d</xliff:g> Verknüpfungen</item>
+ <item quantity="one"><xliff:g id="SHORTCUTS_COUNT_0">%1$d</xliff:g> Verknüpfung</item>
+ </plurals>
+ <string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
- <!-- no translation found for widgets_full_sheet_search_bar_hint (8484659090860596457) -->
- <skip />
- <!-- no translation found for widgets_full_sheet_cancel_button_description (5766167035728653605) -->
- <skip />
- <!-- no translation found for no_widgets_available (9140948620298620513) -->
- <skip />
- <!-- no translation found for no_search_results (6518732304311458580) -->
- <skip />
- <!-- no translation found for widgets_full_sheet_personal_tab (2743540105607120182) -->
- <skip />
- <!-- no translation found for widgets_full_sheet_work_tab (3767150027110633765) -->
- <skip />
- <!-- no translation found for widget_category_conversations (8894438636213590446) -->
- <skip />
+ <string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"Suche"</string>
+ <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Text aus dem Suchfeld löschen"</string>
+ <string name="no_widgets_available" msgid="9140948620298620513">"Keine Widgets verfügbar"</string>
+ <string name="no_search_results" msgid="6518732304311458580">"Keine Suchergebnisse"</string>
+ <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Privat"</string>
+ <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Geschäftlich"</string>
+ <string name="widget_category_conversations" msgid="8894438636213590446">"Unterhaltungen"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Apps finden"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Apps werden geladen…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Keine Apps für \"<xliff:g id="QUERY">%1$s</xliff:g>\" gefunden"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Weitere Apps suchen"</string>
<string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="notifications_header" msgid="1404149926117359025">"Benachrichtigungen"</string>
- <!-- no translation found for long_press_shortcut_to_add (5405328730817637737) -->
- <skip />
- <!-- no translation found for long_accessible_way_to_add_shortcut (2199537273817090740) -->
- <skip />
+ <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Tippen und halten, um eine Verknüpfung zu bewegen."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Doppeltippen und halten, um eine Verknüpfung zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
<string name="out_of_space" msgid="4691004494942118364">"Auf diesem Startbildschirm ist kein Platz mehr vorhanden."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ablage \"Favoriten\" ist voll."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste der Apps"</string>
@@ -108,7 +100,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Designs und Hintergründe"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Startbildschirm-Einstellungen"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Von deinem Administrator deaktiviert"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Drehung des Startbildschirms zulassen"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Drehen des Startbildschirms zulassen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Beim Drehen des Smartphones"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"App-Benachrichtigungspunkte"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"An"</string>
@@ -124,8 +116,7 @@
<string name="abandoned_search" msgid="891119232568284442">"Suchen"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Diese App ist nicht installiert"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"Die App für dieses Symbol ist nicht installiert. Du kannst das Symbol entfernen oder die App lokalisieren und dann manuell installieren."</string>
- <!-- no translation found for app_installing_title (5864044122733792085) -->
- <skip />
+ <string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> wird installiert, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wird heruntergeladen, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Warten auf Installation von <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgetliste"</string>
@@ -165,20 +156,13 @@
<string name="work_profile_edu_next" msgid="8783418929296503629">"Weiter"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="2389865654362803723">"Arbeitsprofil pausiert"</string>
- <!-- no translation found for work_apps_paused_body (4209084728264328628) -->
- <skip />
- <!-- no translation found for work_apps_paused_content_description (4473292417145736203) -->
- <skip />
- <!-- no translation found for work_apps_paused_edu_banner (8872412121608402058) -->
- <skip />
- <!-- no translation found for work_apps_paused_edu_accept (6377476824357318532) -->
- <skip />
- <!-- no translation found for work_apps_pause_btn_text (4669288269140620646) -->
- <skip />
- <!-- no translation found for work_apps_enable_btn_text (82111102541971856) -->
- <skip />
- <!-- no translation found for developer_options_filter_hint (5896817443635989056) -->
- <skip />
+ <string name="work_apps_paused_body" msgid="4209084728264328628">"Geschäftliche Apps können dir keine Benachrichtigungen senden, deinen Akku nicht nutzen und nicht auf deinen Standort zugreifen"</string>
+ <string name="work_apps_paused_content_description" msgid="4473292417145736203">"Das Arbeitsprofil ist pausiert. Geschäftliche Apps können dir keine Benachrichtigungen senden, deinen Akku nicht nutzen und nicht auf deinen Standort zugreifen."</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Geschäftliche Apps sind gekennzeichnet und für deinen IT-Administrator sichtbar"</string>
+ <string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Geschäftliche Apps pausieren"</string>
+ <string name="work_apps_enable_btn_text" msgid="82111102541971856">"Aktivieren"</string>
+ <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="work_switch_tip" msgid="808075064383839144">"Geschäftliche Apps und Benachrichtigungen pausieren"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 3cd084b..8b9ab0c 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -110,7 +110,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar ajustes"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificación"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Añadir aplicaciones a la pantalla de inicio"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para aplicaciones nuevas"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Añade el icono de una aplicación nueva instalada a la pantalla de inicio"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</string>
<string name="abandoned_search" msgid="891119232568284442">"Buscar"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index a38c3d2..a485a14 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -66,7 +66,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Laneko aplikazioen zerrenda"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Kendu"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalatu"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren datuak"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren informazioa"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instalatu"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ez iradoki aplikazioa"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ainguratu iragarpena"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d7e3a5b..34ed9e0 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -103,7 +103,7 @@
<string name="allow_rotation_title" msgid="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kun puhelinta kierretään"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pistemerkit"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"Käytössä"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Päällä"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Ei päällä"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Ilmoituksien käyttöoikeus tarvitaan"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"<xliff:g id="NAME">%1$s</xliff:g> tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää."</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index fe12e37..f336031 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="work_folder_name" msgid="3753320833950115786">"Travail"</string>
+ <string name="work_folder_name" msgid="3753320833950115786">"Pro"</string>
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
@@ -98,7 +98,7 @@
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> éléments ou plus"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Styles et fonds d\'écran"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Paramètres d\'accueil"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Paramètres de l\'accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Lorsque vous faites pivoter le téléphone"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 7d65a14..382f6ff 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -27,7 +27,7 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"Os widgets están desactivados no modo seguro"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"O atallo non está dispoñible"</string>
<string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Dividir pantalla"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén premido un widget para movelo."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -108,7 +108,7 @@
<string name="title_missing_notification_access" msgid="7503287056163941064">"Necesítase acceso ás notificacións"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para que se mostren os puntos de notificacións, activa as notificacións da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar configuración"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificacións"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra puntos de notificacións"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Engadir iconas de aplicacións á pantalla de inicio"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicacións"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 1bdbbcb..478d87e 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -124,7 +124,7 @@
<string name="action_add_to_workspace" msgid="8902165848117513641">"होम स्क्रीन में जोड़ें"</string>
<string name="action_move_here" msgid="2170188780612570250">"आइटम यहां ले जाएं"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"होम स्क्रीन में आइटम जोड़ा गया"</string>
- <string name="item_removed" msgid="851119963877842327">"आइटम निकाला गया"</string>
+ <string name="item_removed" msgid="851119963877842327">"आइटम हटाया गया"</string>
<string name="undo" msgid="4151576204245173321">"पहले जैसा करें"</string>
<string name="action_move" msgid="4339390619886385032">"आइटम ले जाएं"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"पंक्ति <xliff:g id="NUMBER_0">%1$s</xliff:g> स्तंभ <xliff:g id="NUMBER_1">%2$s</xliff:g> पर ले जाएं"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 7589ea8..8ebc33f 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -68,7 +68,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Popis radnih aplikacija"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Ukloni"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deinstaliraj"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"Info o aplikaciji"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"Podaci o aplikaciji"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Instaliraj"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ne predlaži aplikaciju"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Prikvači predviđenu apl."</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 2397e92..104b4ac 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -100,7 +100,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stílar og veggfóður"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Heimastillingar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning fyrir heimaskjá"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning á heimaskjá"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Þegar símanum er snúið"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Tilkynningapunktar"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Kveikt"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 7857fef..9e13576 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -98,7 +98,7 @@
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> o più elementi"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stili e sfondi"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Impostazioni Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Impostazioni schermata Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Consenti rotazione della schermata Home"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Con il telefono ruotato"</string>
@@ -109,7 +109,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per mostrare gli indicatori di notifica, attiva le notifiche per l\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifica impostazioni"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra indicatori di notifica"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Aggiungi icone app a schermata Home"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Aggiungi icone delle app alla schermata Home"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per le nuove app"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 9636353..639aa86 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -56,9 +56,9 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"עבודה"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"שיחות"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"חיפוש אפליקציות"</string>
- <string name="all_apps_loading_message" msgid="5813968043155271636">"טוען אפליקציות…"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"טעינת אפליקציות מתבצעת…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"לא נמצאו אפליקציות התואמות ל-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
- <string name="all_apps_search_market_message" msgid="1366263386197059176">"חפש אפליקציות נוספות"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"חיפוש אפליקציות נוספות"</string>
<string name="label_application" msgid="8531721983832654978">"אפליקציה"</string>
<string name="notifications_header" msgid="1404149926117359025">"התראות"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"כדי להעביר קיצור דרך למקום אחר יש לגעת ולא להרפות."</string>
@@ -68,17 +68,17 @@
<string name="all_apps_button_label" msgid="8130441508702294465">"רשימת אפליקציות"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"רשימת אפליקציות אישיות"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"רשימת אפליקציות עבודה"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"הסר"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"הסרה"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"להסרת התקנה"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"פרטי אפליקציה"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"התקנה"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"בלי להציע את האפליקציה"</string>
<string name="pin_prediction" msgid="4196423321649756498">"הצמדת החיזוי"</string>
- <string name="permlab_install_shortcut" msgid="5632423390354674437">"התקן קיצורי דרך"</string>
+ <string name="permlab_install_shortcut" msgid="5632423390354674437">"התקנת קיצורי דרך"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"מאפשר לאפליקציה להוסיף קיצורי דרך ללא התערבות המשתמש."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"קרא הגדרות וקיצורי דרך של דף הבית"</string>
+ <string name="permlab_read_settings" msgid="1941457408239617576">"קריאת הגדרות וקיצורי דרך של דף הבית"</string>
<string name="permdesc_read_settings" msgid="5833423719057558387">"מאפשר לאפליקציה לקרוא את ההגדרות וקיצורי הדרך בדף הבית."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"כתוב הגדרות וקיצורי דרך של דף הבית"</string>
+ <string name="permlab_write_settings" msgid="3574213698004620587">"כתיבת הגדרות וקיצורי דרך של דף הבית"</string>
<string name="permdesc_write_settings" msgid="5440712911516509985">"מאפשר לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> אינו רשאי להתקשר"</string>
<string name="gadget_error_text" msgid="6081085226050792095">"בעיה בטעינת ווידג\'ט"</string>
@@ -95,59 +95,59 @@
<string name="default_scroll_format" msgid="7475544710230993317">"דף %1$d מתוך %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"מסך דף הבית %1$d מתוך %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"מסך דף הבית חדש"</string>
- <string name="folder_opened" msgid="94695026776264709">"תיקיה פתוחה, <xliff:g id="WIDTH">%1$d</xliff:g> על <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
- <string name="folder_tap_to_close" msgid="4625795376335528256">"הקש כדי לסגור את התיקייה"</string>
- <string name="folder_tap_to_rename" msgid="4017685068016979677">"הקש כדי לשמור שינוי שם"</string>
- <string name="folder_closed" msgid="4100806530910930934">"התיקיה נסגרה"</string>
- <string name="folder_renamed" msgid="1794088362165669656">"שם התיקיה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="folder_opened" msgid="94695026776264709">"תיקייה פתוחה, <xliff:g id="WIDTH">%1$d</xliff:g> על <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"יש להקיש כדי לסגור את התיקייה"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"יש להקיש כדי לשמור שינוי שם"</string>
+ <string name="folder_closed" msgid="4100806530910930934">"התיקייה נסגרה"</string>
+ <string name="folder_renamed" msgid="1794088362165669656">"שם התיקייה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"תיקייה: <xliff:g id="NAME">%1$s</xliff:g>, מספר הפריטים: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"תיקייה: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> פריטים או יותר"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"טפטים"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"סגנונות וטפטים"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"הגדרות דף הבית"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"הגדרות של מסך הבית"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"אפשרות סיבוב של מסך דף הבית"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"סיבוב של מסך הבית"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"כאשר הטלפון מסובב"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"סימני ההתראות"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"מופעל"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"כבוי"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"נדרשת גישה להתראות"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"כדי להציג את סימני ההתראות,יש להפעיל התראות מהאפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="title_change_settings" msgid="1376365968844349552">"שנה את ההגדרות"</string>
+ <string name="title_change_settings" msgid="1376365968844349552">"שינוי ההגדרות"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"הצגת סימני ההתראות"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"הוספת סמלי אפליקציות למסך הבית"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"לאפליקציות חדשות"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"הסר"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"הסרה"</string>
<string name="abandoned_search" msgid="891119232568284442">"חיפוש"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"אפליקציה זו אינה מותקנת"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"האפליקציה של סמל זה אינה מותקנת. ניתן להסיר אותו, או לחפש את האפליקציה ולהתקין אותה ידנית."</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> בתהליך התקנה, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
- <string name="app_downloading_title" msgid="8336702962104482644">"מוריד את <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
+ <string name="app_downloading_title" msgid="8336702962104482644">"הורדת <xliff:g id="NAME">%1$s</xliff:g> מתבצעת, <xliff:g id="PROGRESS">%2$s</xliff:g> הושלמו"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"מחכה להתקנה של <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="widgets_list" msgid="796804551140113767">"רשימת ווידג\'טים"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"רשימת הווידג\'טים נסגרה"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"הוספה למסך דף הבית"</string>
- <string name="action_move_here" msgid="2170188780612570250">"העבר את הפריט לכאן"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"העברת הפריט לכאן"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"הפריט הועבר אל מסך דף הבית"</string>
<string name="item_removed" msgid="851119963877842327">"הפריט הוסר"</string>
<string name="undo" msgid="4151576204245173321">"ביטול"</string>
- <string name="action_move" msgid="4339390619886385032">"העבר את הפריט"</string>
- <string name="move_to_empty_cell" msgid="2833711483015685619">"העבר אל שורה <xliff:g id="NUMBER_0">%1$s</xliff:g> עמודה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
- <string name="move_to_position" msgid="6750008980455459790">"העבר אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
- <string name="move_to_hotseat_position" msgid="6295412897075147808">"העבר אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g> במועדפים"</string>
+ <string name="action_move" msgid="4339390619886385032">"העברת הפריט"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"העברה אל שורה <xliff:g id="NUMBER_0">%1$s</xliff:g> עמודה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"העברה אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"העברה אל מיקום <xliff:g id="NUMBER">%1$s</xliff:g> במועדפים"</string>
<string name="item_moved" msgid="4606538322571412879">"הפריט הועבר"</string>
- <string name="add_to_folder" msgid="9040534766770853243">"הוסף לתיקייה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="add_to_folder_with_app" msgid="4534929978967147231">"העבר אל התיקייה עם <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"הוספה לתיקייה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"הוספה לתיקייה עם <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="added_to_folder" msgid="4793259502305558003">"הפריט נוסף לתיקייה"</string>
- <string name="create_folder_with" msgid="4050141361160214248">"צור תיקייה עם: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"יצירת תיקייה עם: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"התיקייה נוצרה"</string>
<string name="action_move_to_workspace" msgid="1603837886334246317">"העבר אל מסך דף הבית"</string>
- <string name="action_resize" msgid="1802976324781771067">"שנה גודל"</string>
- <string name="action_increase_width" msgid="8773715375078513326">"הגדל רוחב"</string>
- <string name="action_increase_height" msgid="459390020612501122">"הגדל גובה"</string>
- <string name="action_decrease_width" msgid="1374549771083094654">"הקטן רוחב"</string>
- <string name="action_decrease_height" msgid="282377193880900022">"הקטן גובה"</string>
+ <string name="action_resize" msgid="1802976324781771067">"שינוי גודל"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"הגדלת רוחב"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"הגדלת גובה"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"הקטנת רוחב"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"הקטנת גובה"</string>
<string name="widget_resized" msgid="9130327887929620">"גודל הווידג\'ט שונה - רוחב <xliff:g id="NUMBER_0">%1$s</xliff:g> גובה <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"קיצורי דרך"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"קיצורי דרך והתראות"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index bc70a3d..f460512 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -124,7 +124,7 @@
<string name="action_add_to_workspace" msgid="8902165848117513641">"បញ្ចូលទៅអេក្រង់ដើម"</string>
<string name="action_move_here" msgid="2170188780612570250">"ផ្លាស់ធាតុមកទីនេះ"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ធាតុដែលត្រូវបានបន្ថែមទៅអេក្រង់ដើម"</string>
- <string name="item_removed" msgid="851119963877842327">"ធាតុដែលបានដកចេញ"</string>
+ <string name="item_removed" msgid="851119963877842327">"បានដកធាតុចេញ"</string>
<string name="undo" msgid="4151576204245173321">"ត្រឡប់វិញ"</string>
<string name="action_move" msgid="4339390619886385032">"ផ្លាស់ទីធាតុ"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"ផ្លាស់ទីទៅជួរដេកទី <xliff:g id="NUMBER_0">%1$s</xliff:g> ជួរឈរទី <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 7606ca1..50c36d5 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -50,7 +50,7 @@
<string name="no_search_results" msgid="6518732304311458580">"Издөө жыйынтыктары жок"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Жеке"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жумуш"</string>
- <string name="widget_category_conversations" msgid="8894438636213590446">"Жазышуулар"</string>
+ <string name="widget_category_conversations" msgid="8894438636213590446">"Сүйлөшүүлөр"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Колдонмолорду издөө"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Колдонмолор жүктөлүүдө…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сурамына дал келген колдонмолор табылган жок"</string>
@@ -100,8 +100,8 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Стилдер жана тушкагаздар"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Башкы бет жөндөөлөрү"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды айлантууга уруксат берүү"</string>
- <string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон айланганда"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды бурууга уруксат берүү"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон бурулганда"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Билдирмелер белгилери"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Күйүк"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Өчүк"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 967a22e..3ce2c20 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -98,7 +98,7 @@
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ຫຼື ລາຍການເພີ່ມເຕີມ"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ຮູບແບບ ແລະ ຮູບພື້ນຫຼັງ"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າ Home"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າໜ້າຫຼັກ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍຢູ່ໜ້າຫຼັກໄດ້"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ເມື່ອໝຸນໂທລະສັບ"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 247144d..ce79bde 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -109,7 +109,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промени ги поставките"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Прикажувај точки за известување"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавај икони за апликации на почетен екран"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавај икони за апликации на почетниот екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови апликации"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 8ae7bdf..7fc330e 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -110,7 +110,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग्ज बदला"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"सूचना बिंदू दाखवा"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"होम स्क्रीनवर ॲप आयकन जोडा"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन ॲप्ससाठी"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन अॅप्ससाठी"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
<string name="abandoned_search" msgid="891119232568284442">"Search"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index c7960a6..b429602 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -103,13 +103,13 @@
<string name="allow_rotation_title" msgid="7728578836261442095">"ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ဖုန်းကိုလှည့်ထားစဉ်"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"သတိပေးချက် အစက်များ"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"ဖွင့်ထားသည်"</string>
- <string name="notification_dots_desc_off" msgid="1760796511504341095">"ပိတ်ထားသည်"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"ဖွင့်"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"ပိတ်"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"အကြောင်းကြားချက် အစက်များကို ပြသရန် <xliff:g id="NAME">%1$s</xliff:g> အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ဆက်တင်များ ပြောင်းရန်"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"သတိပေးချက် အစက်များ ပြရန်"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"\'ပင်မစာမျက်နှာ\' တွင် အက်ပ်သင်္ကေတထည့်ရန်"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"အကြောင်းကြားချက် အစက်များ ပြရန်"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ပင်မစာမျက်နှာတွင် အက်ပ်သင်္ကေတထည့်ရန်"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"အက်ပ်အသစ်များအတွက်"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"မသိ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ဖယ်ရှားရန်"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 6f2afc2..9c348e3 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -108,7 +108,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"शैली तथा वालपेपरहरू"</string>
<string name="settings_button_text" msgid="8873672322605444408">"गृहपृष्ठका सेटिङहरू"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"गृह स्क्रिनलाई रोटेट हुन दिइयोस्"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फोनलाई घुमाइँदा"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"सूचनाको प्रतीक जनाउने थोप्लाहरू"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"सक्रिय"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 03519ba..8505c8e 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -27,7 +27,7 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍ ଅକ୍ଷମ କରାଗଲା"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"ଶର୍ଟକଟ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="home_screen" msgid="5629429142036709174">"ମୂଳପୃଷ୍ଠା"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍ପ୍ଲିଟ୍ ସ୍କ୍ରିନ୍"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 243f665..fa2a50e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -97,7 +97,7 @@
<string name="folder_name_format_exact" msgid="8626242716117004803">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> itens"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ou mais itens"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Imagens de fundo"</string>
- <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e imagens de fundo"</string>
+ <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e fundo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Definições de início"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo gestor"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação do ecrã principal"</string>
@@ -110,7 +110,7 @@
<string name="title_change_settings" msgid="1376365968844349552">"Alterar definições"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar pontos de notificação"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Adic. ícones de apps ao ecrã principal"</string>
- <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicações"</string>
+ <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
<string name="abandoned_search" msgid="891119232568284442">"Pesquisar"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 22a041d..165a013 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -98,7 +98,7 @@
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ou mais itens"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Planos de fundo"</string>
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Estilos e planos de fundo"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Config. tela inicial"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Configurações da tela inicial"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação da tela inicial"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Quando o smartphone for girado"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 2e17d44..24aabc5 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -130,7 +130,7 @@
<string name="action_add_to_workspace" msgid="8902165848117513641">"Добавить на главный экран"</string>
<string name="action_move_here" msgid="2170188780612570250">"Переместить элемент сюда"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Элемент добавлен на главный экран"</string>
- <string name="item_removed" msgid="851119963877842327">"Элемент удален"</string>
+ <string name="item_removed" msgid="851119963877842327">"Элемент удален."</string>
<string name="undo" msgid="4151576204245173321">"Отменить"</string>
<string name="action_move" msgid="4339390619886385032">"Переместить элемент"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"Переместить в ячейку <xliff:g id="NUMBER_0">%1$s</xliff:g> <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 5879f91..9e60efb 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -106,7 +106,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Slogi in ozadja"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Domače nastavitve"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Omogočanje sukanja začetnega zaslona"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Omogoči sukanje začetnega zaslona"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ko se telefon zasuka"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Obvestilne pike"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Vklopljeno"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index f2c16b4..1ed8070 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -100,7 +100,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilet dhe imazhet e sfondit"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cilësimet e ekranit bazë"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit kryesor"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit bazë"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kur telefoni rrotullohet"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pikat e njoftimeve"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index a3c7256..344f455 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -100,7 +100,7 @@
<string name="styles_wallpaper_button_text" msgid="4342122323125579619">"స్టయిల్స్ & వాల్పేపర్లు"</string>
<string name="settings_button_text" msgid="8873672322605444408">"హోమ్ సెట్టింగ్లు"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ రొటేషన్ను అనుమతించండి"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ఫోన్ను తిప్పినప్పుడు"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"నోటిఫికేషన్ డాట్లు"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"ఆన్"</string>
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index 24aac10..7f27bf8 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -17,9 +17,11 @@
*/
-->
<resources>
+ <color name="popup_color_neutral_light">@android:color/system_neutral1_0</color>
<color name="popup_color_primary_light">@android:color/system_neutral1_50</color>
<color name="popup_color_secondary_light">@android:color/system_neutral2_100</color>
<color name="popup_color_tertiary_light">@android:color/system_neutral2_300</color>
+ <color name="popup_color_neutral_dark">@android:color/system_neutral1_1000</color>
<color name="popup_color_primary_dark">@android:color/system_neutral1_800</color>
<color name="popup_color_secondary_dark">@android:color/system_neutral1_900</color>
<color name="popup_color_tertiary_dark">@android:color/system_neutral2_700</color>
@@ -30,4 +32,7 @@
<color name="text_color_primary_dark">@android:color/system_neutral1_50</color>
<color name="text_color_secondary_dark">@android:color/system_neutral2_200</color>
<color name="text_color_tertiary_dark">@android:color/system_neutral2_400</color>
+
+ <color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
+
</resources>
\ No newline at end of file
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index f7bef37..318d453 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -108,7 +108,7 @@
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cần quyền truy cập thông báo"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Để hiển thị Dấu chấm thông báo, hãy bật thông báo ứng dụng cho <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Thay đổi cài đặt"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"Hiển thị dấu chấm thông báo"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Hiện dấu chấm thông báo"</string>
<string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Thêm biểu tượng ứng dụng vào Màn hình chính"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Cho ứng dụng mới"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
@@ -125,7 +125,7 @@
<string name="action_move_here" msgid="2170188780612570250">"Di chuyển mục vào đây"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Đã thêm mục vào màn hình chính"</string>
<string name="item_removed" msgid="851119963877842327">"Đã xóa mục"</string>
- <string name="undo" msgid="4151576204245173321">"Hoàn tác"</string>
+ <string name="undo" msgid="4151576204245173321">"Hủy"</string>
<string name="action_move" msgid="4339390619886385032">"Di chuyển mục"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"Di chuyển đến hàng <xliff:g id="NUMBER_0">%1$s</xliff:g> cột <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="move_to_position" msgid="6750008980455459790">"Di chuyển tới vị trí <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index fd0ff0e..c6f933c 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -109,7 +109,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"如要顯示通知圓點,請開啟「<xliff:g id="NAME">%1$s</xliff:g>」的應用程式通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"變更設定"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"顯示通知圓點"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"將應用程式圖示新增到主畫面"</string>
+ <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"將應用程式圖示加到主畫面"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"適用於新安裝的應用程式"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 1beb8dd..93d88c2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -19,9 +19,9 @@
<!-- Attributes used for launcher theme -->
<attr name="allAppsScrimColor" format="color" />
- <attr name="allAppsInterimScrimAlpha" format="integer" />
<attr name="allAppsNavBarScrimColor" format="color" />
<attr name="allAppsTheme" format="reference" />
+ <attr name="popupColorNeutral" format="color" />
<attr name="popupColorPrimary" format="color" />
<attr name="popupColorSecondary" format="color" />
<attr name="popupColorTertiary" format="color" />
@@ -35,6 +35,7 @@
<attr name="widgetsTheme" format="reference" />
<attr name="iconOnlyShortcutColor" format="color" />
<attr name="eduHalfSheetBGColor" format="color" />
+ <attr name="overviewScrimColor" format="color" />
<attr name="folderDotColor" format="color" />
<attr name="folderFillColor" format="color" />
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 2c096b4..83d2deb 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -38,12 +38,14 @@
<color name="gesture_tutorial_ripple_color">#A0C2F9</color> <!-- Light Blue -->
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
<color name="gesture_tutorial_fake_previous_task_view_color">#3C4043</color> <!-- Gray -->
- <color name="gesture_tutorial_action_button_label_color">#FFFFFFFF</color>
- <color name="gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
+ <color name="gesture_tutorial_action_button_label_color">#FF000000</color>
+ <color name="gesture_tutorial_primary_color">#B7F29F</color> <!-- Light Green -->
+ <color name="popup_color_neutral_light">#FFF</color>
<color name="popup_color_primary_light">#FFF</color>
<color name="popup_color_secondary_light">#F1F3F4</color>
<color name="popup_color_tertiary_light">#E0E0E0</color> <!-- Gray 300 -->
+ <color name="popup_color_neutral_dark">#3C4043</color> <!-- Gray 800 -->
<color name="popup_color_primary_dark">#3C4043</color> <!-- Gray 800 -->
<color name="popup_color_secondary_dark">#202124</color>
<color name="popup_color_tertiary_dark">#757575</color> <!-- Gray 600 -->
@@ -55,4 +57,6 @@
<color name="text_color_secondary_dark">#FFFFFFFF</color>
<color name="text_color_tertiary_dark">#CCFFFFFF</color>
+ <color name="wallpaper_popup_scrim">?android:attr/colorAccent</color>
+
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index db98811..f8a517d 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -134,8 +134,45 @@
<item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item>
<item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
+
+ <item name="swipe_up_scale_start" type="dimen" format="float">0.98</item>
+ <item name="swipe_up_duration" type="dimen" format="float">500</item>
+
+ <item name="swipe_up_trans_y_dp" type="dimen" format="float">3</item>
+ <item name="swipe_up_trans_y_dp_per_s" type="dimen" format="float">3</item>
+
+ <item name="swipe_up_trans_y_damping" type="dimen" format="float">0.4</item>
+ <item name="swipe_up_trans_y_stiffness" type="dimen" format="float">200</item>
+
<item name="swipe_up_rect_xy_damping_ratio" type="dimen" format="float">0.8</item>
- <item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item>
+ <item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">100</item>
+
+
+ <item name="swipe_up_rect_2_x_damping_ratio" type="dimen" format="float">1</item>
+ <item name="swipe_up_rect_2_x_stiffness" type="dimen" format="float">350</item>
+
+ <item name="swipe_up_rect_2_y_damping_ratio" type="dimen" format="float">1</item>
+ <item name="swipe_up_rect_2_y_stiffness" type="dimen" format="float">700</item>
+
+ <item name="swipe_up_rect_2_y_stiffness_low_swipe_multiplier" type="dimen" format="float">1</item>
+ <item name="swipe_up_low_swipe_duration_multiplier" type="dimen" format="float">1</item>
+
+ <item name="swipe_up_launcher_alpha_max_progress" type="dimen" format="float">0.85</item>
+
+
+ <item name="c1_a" type="dimen" format="float">0.05</item>
+ <item name="c1_b" type="dimen" format="float">0</item>
+ <item name="c1_c" type="dimen" format="float">0.133333</item>
+ <item name="c1_d" type="dimen" format="float">0.06</item>
+
+ <item name="mp_x" type="dimen" format="float">0.166666</item>
+ <item name="mp_y" type="dimen" format="float">.4</item>
+
+ <item name="c2_a" type="dimen" format="float">0.208333</item>
+ <item name="c2_b" type="dimen" format="float">.82</item>
+ <item name="c2_c" type="dimen" format="float">.25</item>
+ <item name="c2_d" type="dimen" format="float">1</item>
+
<item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
<item name="staggered_stiffness" type="dimen" format="float">150</item>
@@ -151,40 +188,34 @@
<dimen name="swipe_up_max_workspace_trans_y">-60dp</dimen>
<array name="dynamic_resources">
- <item>@dimen/all_apps_spring_damping_ratio</item>
- <item>@dimen/all_apps_spring_stiffness</item>
+ <item>@dimen/swipe_up_duration</item>
+ <item>@dimen/swipe_up_scale_start</item>
+ <item>@dimen/swipe_up_trans_y_dp</item>
+ <item>@dimen/swipe_up_trans_y_dp_per_s</item>
+ <item>@dimen/swipe_up_trans_y_damping</item>
+ <item>@dimen/swipe_up_trans_y_stiffness</item>
+ <item>@dimen/swipe_up_rect_2_x_damping_ratio</item>
+ <item>@dimen/swipe_up_rect_2_x_stiffness</item>
+ <item>@dimen/swipe_up_rect_2_y_damping_ratio</item>
+ <item>@dimen/swipe_up_rect_2_y_stiffness</item>
+ <item>@dimen/swipe_up_launcher_alpha_max_progress</item>
+ <item>@dimen/swipe_up_rect_2_y_stiffness_low_swipe_multiplier</item>
+ <item>@dimen/swipe_up_low_swipe_duration_multiplier</item>
- <item>@dimen/dismiss_task_trans_y_damping_ratio</item>
- <item>@dimen/dismiss_task_trans_y_stiffness</item>
+ <item>@dimen/c1_a</item>
+ <item>@dimen/c1_b</item>
+ <item>@dimen/c1_c</item>
+ <item>@dimen/c1_d</item>
- <item>@dimen/dismiss_task_trans_x_damping_ratio</item>
- <item>@dimen/dismiss_task_trans_x_stiffness</item>
+ <item>@dimen/mp_x</item>
+ <item>@dimen/mp_y</item>
- <item>@dimen/horizontal_spring_damping_ratio</item>
- <item>@dimen/horizontal_spring_stiffness</item>
-
- <item>@dimen/swipe_up_rect_scale_damping_ratio</item>
- <item>@dimen/swipe_up_rect_scale_stiffness</item>
-
- <item>@dimen/swipe_up_rect_xy_fling_friction</item>
- <item>@dimen/swipe_up_rect_xy_damping_ratio</item>
- <item>@dimen/swipe_up_rect_xy_stiffness</item>
-
- <item>@dimen/staggered_damping_ratio</item>
- <item>@dimen/staggered_stiffness</item>
- <item>@dimen/unlock_staggered_velocity_dp_per_s</item>
-
- <item>@dimen/swipe_up_fling_min_visible_change</item>
- <item>@dimen/swipe_up_y_overshoot</item>
-
- <item>@dimen/hint_scale_damping_ratio</item>
- <item>@dimen/hint_scale_stiffness</item>
- <item>@dimen/hint_scale_velocity_dp_per_s</item>
+ <item>@dimen/c2_a</item>
+ <item>@dimen/c2_b</item>
+ <item>@dimen/c2_c</item>
+ <item>@dimen/c2_d</item>
</array>
- <string-array name="live_wallpapers_remove_sysui_scrims">
- </string-array>
-
<string-array name="filtered_components" ></string-array>
<!-- Name of the class used to generate colors from the wallpaper colors. Must be implementing the LauncherAppWidgetHostView.ColorGenerator interface. -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a06b42c..600a550 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -84,7 +84,7 @@
<dimen name="fastscroll_end_margin">-26dp</dimen>
<!-- All Apps -->
- <dimen name="all_apps_open_vertical_translate">96dp</dimen>
+ <dimen name="all_apps_open_vertical_translate">300dp</dimen>
<dimen name="all_apps_search_bar_field_height">48dp</dimen>
<dimen name="all_apps_search_bar_bottom_padding">30dp</dimen>
<dimen name="all_apps_empty_search_message_top_offset">40dp</dimen>
@@ -118,6 +118,7 @@
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
<dimen name="widget_cell_font_size">14sp</dimen>
+ <dimen name="recommended_widgets_table_vertical_padding">8dp</dimen>
<dimen name="widget_list_top_bottom_corner_radius">28dp</dimen>
<dimen name="widget_list_content_corner_radius">4dp</dimen>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4266445..5ae4e3f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,9 +32,9 @@
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
<item name="android:textColorSecondary">#DE000000</item>
<item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
- <item name="allAppsInterimScrimAlpha">46</item>
<item name="allAppsNavBarScrimColor">#66FFFFFF</item>
<item name="allAppsTheme">@style/AllAppsTheme</item>
+ <item name="popupColorNeutral">@color/popup_color_neutral_light</item>
<item name="popupColorPrimary">@color/popup_color_primary_light</item>
<item name="popupColorSecondary">@color/popup_color_secondary_light</item>
<item name="popupColorTertiary">@color/popup_color_tertiary_light</item>
@@ -57,6 +57,7 @@
<item name="eduHalfSheetBGColor">?android:attr/colorAccent</item>
<item name="disabledIconAlpha">.54</item>
<item name="gridColor">?android:attr/colorAccent</item>
+ <item name="overviewScrimColor">@color/overview_scrim</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
@@ -76,7 +77,6 @@
<style name="LauncherTheme.DarkText" parent="@style/LauncherTheme">
<item name="workspaceTextColor">@color/workspace_text_color_dark</item>
- <item name="allAppsInterimScrimAlpha">128</item>
<item name="workspaceShadowColor">@android:color/transparent</item>
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
@@ -96,9 +96,9 @@
<item name="android:colorControlHighlight">#A0FFFFFF</item>
<item name="android:colorPrimary">#FF212121</item>
<item name="allAppsScrimColor">?android:attr/colorBackgroundFloating</item>
- <item name="allAppsInterimScrimAlpha">102</item>
<item name="allAppsNavBarScrimColor">#80000000</item>
<item name="allAppsTheme">@style/AllAppsTheme.Dark</item>
+ <item name="popupColorNeutral">@color/popup_color_neutral_dark</item>
<item name="popupColorPrimary">@color/popup_color_primary_dark</item>
<item name="popupColorSecondary">@color/popup_color_secondary_dark</item>
<item name="popupColorTertiary">@color/popup_color_tertiary_dark</item>
@@ -113,6 +113,7 @@
<item name="iconOnlyShortcutColor">#B3FFFFFF</item>
<item name="workProfileOverlayTextColor">@android:color/white</item>
<item name="eduHalfSheetBGColor">#DD000000</item>
+ <item name="overviewScrimColor">@color/overview_scrim_dark</item>
</style>
<style name="LauncherTheme.Dark.DarkMainColor" parent="@style/LauncherTheme.Dark">
@@ -123,7 +124,6 @@
<style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
<item name="android:colorControlHighlight">#75212121</item>
- <item name="allAppsInterimScrimAlpha">25</item>
<item name="folderFillColor">#CDFFFFFF</item>
<item name="folderTextColor">?attr/workspaceTextColor</item>
<item name="workspaceTextColor">@color/workspace_text_color_dark</item>
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index f77f7e8..f64ce5c 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -17,7 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
-import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -39,6 +39,7 @@
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.ScrimView;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -157,6 +158,10 @@
return mSystemUiController;
}
+ public ScrimView getScrimView() {
+ return null;
+ }
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@@ -197,7 +202,7 @@
// Reset the overridden sysui flags used for the task-swipe launch animation, this is a
// catch all for if we do not get resumed (and therefore not paused below)
- getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
+ getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
@Override
@@ -209,7 +214,7 @@
// here instead of at the end of the animation because the start of the new activity does
// not happen immediately, which would cause us to reset to launcher's sysui flags and then
// back to the new app (causing a flash)
- getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
+ getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
}
@Override
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 5ba03ed..2c76e52 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -17,10 +17,15 @@
package com.android.launcher3;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
-import static com.android.launcher3.util.DisplayController.DisplayHolder.CHANGE_ROTATION;
+import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.ActivityOptions;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
import android.content.ActivityNotFoundException;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.res.Configuration;
@@ -28,7 +33,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Process;
import android.os.StrictMode;
@@ -54,7 +58,6 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
@@ -68,8 +71,9 @@
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
+@SuppressWarnings("NewApi")
public abstract class BaseDraggingActivity extends BaseActivity
- implements WallpaperColorInfo.OnChangeListener, DisplayInfoChangeListener {
+ implements OnColorsChangedListener, DisplayInfoChangeListener {
private static final String TAG = "BaseDraggingActivity";
@@ -89,13 +93,15 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
() -> getPackageManager().isSafeMode());
- DisplayController.getDefaultDisplay(this).addChangeListener(this);
+ DisplayController.INSTANCE.get(this).addChangeListener(this);
// Update theme
- WallpaperColorInfo.INSTANCE.get(this).addOnChangeListener(this);
+ if (Utilities.ATLEAST_P) {
+ getSystemService(WallpaperManager.class)
+ .addOnColorsChangedListener(this, MAIN_EXECUTOR.getHandler());
+ }
int themeRes = Themes.getActivityThemeRes(this);
if (themeRes != mThemeRes) {
mThemeRes = themeRes;
@@ -114,7 +120,7 @@
}
@Override
- public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
+ public void onColorsChanged(WallpaperColors wallpaperColors, int which) {
updateTheme();
}
@@ -166,7 +172,7 @@
}
@NonNull
- public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
+ public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
int left = 0, top = 0;
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
if (v instanceof BubbleTextView) {
@@ -193,7 +199,7 @@
return false;
}
- Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v).toBundle() : null;
+ Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
UserHandle user = item == null ? null : item.user;
// Prepare intent
@@ -278,8 +284,10 @@
@Override
protected void onDestroy() {
super.onDestroy();
- WallpaperColorInfo.INSTANCE.get(this).removeOnChangeListener(this);
- DisplayController.getDefaultDisplay(this).removeChangeListener(this);
+ if (Utilities.ATLEAST_P) {
+ getSystemService(WallpaperManager.class).removeOnColorsChangedListener(this);
+ }
+ DisplayController.INSTANCE.get(this).removeChangeListener(this);
}
public void runOnceOnStart(Runnable action) {
@@ -297,7 +305,7 @@
}
@Override
- public void onDisplayInfoChanged(Info info, int flags) {
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.updateIsSeascape(this)) {
reapplyUi();
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d333b49..2ace796 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@@ -26,16 +25,13 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
-import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Process;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Property;
@@ -50,7 +46,6 @@
import androidx.annotation.UiThread;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.FolderIcon;
@@ -60,7 +55,6 @@
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
-import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.PlaceHolderIconDrawable;
import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.model.data.AppInfo;
@@ -97,11 +91,6 @@
private float mScaleForReorderBounce = 1f;
- protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private final Path mHighlightPath = new Path();
- protected int mHighlightColor = Color.TRANSPARENT;
- private final BlurMaskFilter mHighlightShadowFilter;
-
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
= new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
@Override
@@ -220,10 +209,6 @@
setEllipsize(TruncateAt.END);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
setTextAlpha(1f);
-
- int shadowSize = context.getResources().getDimensionPixelSize(
- R.dimen.blur_size_click_shadow);
- mHighlightShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.INNER);
}
@Override
@@ -451,41 +436,10 @@
@Override
public void onDraw(Canvas canvas) {
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mHighlightColor != Color.TRANSPARENT) {
- int count = canvas.save();
- drawFocusHighlight(canvas);
- canvas.restoreToCount(count);
- }
super.onDraw(canvas);
drawDotIfNecessary(canvas);
}
- protected void drawFocusHighlight(Canvas canvas) {
- boolean isBadged = getTag() instanceof ItemInfo && !Process.myUserHandle().equals(
- ((ItemInfo) getTag()).user);
- float insetScale = (HIGHLIGHT_SCALE - 1) / 2;
- canvas.translate(-getIconSize() * insetScale, -insetScale * getIconSize());
- float outlineSize = getIconSize() * HIGHLIGHT_SCALE;
- mHighlightPath.reset();
- mHighlightPaint.reset();
- getIconBounds(mDotParams.iconBounds);
- getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left, mDotParams.iconBounds.top,
- outlineSize / 2);
- if (isBadged) {
- float borderSize = outlineSize - getIconSize();
- float badgeSize = LauncherIcons.getBadgeSizeForIconSize(getIconSize()) + borderSize;
- float badgeInset = outlineSize - badgeSize;
- getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left + badgeInset,
- mDotParams.iconBounds.top + badgeInset, badgeSize / 2);
- }
- mHighlightPaint.setMaskFilter(mHighlightShadowFilter);
- mHighlightPaint.setColor(mDotParams.color);
- canvas.drawPath(mHighlightPath, mHighlightPaint);
- mHighlightPaint.setMaskFilter(null);
- mHighlightPaint.setColor(mHighlightColor);
- canvas.drawPath(mHighlightPath, mHighlightPaint);
- }
-
/**
* Draws the notification dot in the top right corner of the icon bounds.
*
@@ -921,11 +875,9 @@
@Override
public SafeCloseable prepareDrawDragView() {
- int highlightColor = mHighlightColor;
- mHighlightColor = Color.TRANSPARENT;
resetIconScale();
setForceHideDot(true);
- return () -> mHighlightColor = highlightColor;
+ return () -> { };
}
private void resetIconScale() {
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 4740079..a26217c 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -183,7 +183,6 @@
hideTooltip();
if (!d.dragComplete) {
- d.dragView.setColor(0);
d.dragView.setAlpha(1f);
} else {
d.dragView.setAlpha(DRAG_VIEW_HOVER_OVER_OPACITY);
@@ -241,6 +240,7 @@
final Rect to = getIconRect(d);
final float scale = (float) to.width() / from.width();
+ d.dragView.detachContentView(/* reattachToPreviousParent= */ true);
mDropTargetBar.deferOnDragEnd();
Runnable onAnimationEndRunnable = () -> {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index fc09295..c3816cc 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -61,7 +61,6 @@
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.CellAndSpan;
@@ -70,6 +69,7 @@
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1038,6 +1038,9 @@
mDragCellSpan[0] = spanX;
mDragCellSpan[1] = spanY;
+ // Apply color extraction on a widget when dragging.
+ applyColorExtractionOnWidget(dragObject, mDragCell, spanX, spanY);
+
final int oldIndex = mDragOutlineCurrent;
mDragOutlineAnims[oldIndex].animateOut();
mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
@@ -1059,18 +1062,17 @@
}
/** Applies the local color extraction to a dragging widget object. */
- private void applyColorExtraction(DropTarget.DragObject dragObject, int[] targetCell, int spanX,
- int spanY) {
+ private void applyColorExtractionOnWidget(DropTarget.DragObject dragObject, int[] targetCell,
+ int spanX, int spanY) {
// Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
- Drawable drawable = dragObject.dragView.getDrawable();
- if (drawable instanceof AppWidgetHostViewDrawable) {
+ View view = dragObject.dragView.getContentView();
+ if (view instanceof LauncherAppWidgetHostView) {
Workspace workspace =
Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
int screenId = workspace.getIdForScreen(this);
int pageId = workspace.getPageIndexForScreenId(screenId);
- AppWidgetHostViewDrawable hostViewDrawable = ((AppWidgetHostViewDrawable) drawable);
cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
- hostViewDrawable.getAppWidgetHostView().handleDrag(mTempRect, pageId);
+ ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 985a445..fd97936 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,15 +16,22 @@
package com.android.launcher3;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
import static com.android.launcher3.ResourceUtils.pxFromDp;
import static com.android.launcher3.Utilities.dpiFromPx;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Surface;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -32,23 +39,27 @@
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.DevicePaddings.DevicePadding;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.icons.DotRenderer;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.WindowBounds;
import java.io.PrintWriter;
+@SuppressLint("NewApi")
public class DeviceProfile {
private static final float TABLET_MIN_DPS = 600;
private static final float LARGE_TABLET_MIN_DPS = 720;
+ private static final int DEFAULT_DOT_SIZE = 100;
public final InvariantDeviceProfile inv;
private final Info mInfo;
+ private final DisplayMetrics mMetrics;
// Device properties
public final boolean isTablet;
@@ -212,7 +223,8 @@
mInfo = info;
// Constants from resources
- float swDPs = dpiFromPx(Math.min(info.smallestSize.x, info.smallestSize.y), info.metrics);
+ float swDPs = dpiFromPx(Math.min(info.smallestSize.x, info.smallestSize.y),
+ info.densityDpi);
boolean allowRotation = context.getResources().getBoolean(R.bool.allow_rotation);
// Tablet UI is built with assumption that simulated landscape is disabled.
isTablet = allowRotation && swDPs >= TABLET_MIN_DPS;
@@ -225,6 +237,7 @@
context = getContext(context, info, isVerticalBarLayout()
? Configuration.ORIENTATION_LANDSCAPE
: Configuration.ORIENTATION_PORTRAIT);
+ mMetrics = context.getResources().getDisplayMetrics();
final Resources res = context.getResources();
isTaskbarPresent = isTablet && FeatureFlags.ENABLE_TASKBAR.get();
@@ -232,11 +245,13 @@
// Taskbar will be added later, but provides bottom insets that we should subtract
// from availableHeightPx.
taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
- WindowInsets windowInsets = DisplayController.INSTANCE.get(context).getHolder(mInfo.id)
- .getDisplayContext().getSystemService(WindowManager.class)
+ WindowInsets windowInsets =
+ context.createWindowContext(
+ context.getSystemService(DisplayManager.class).getDisplay(mInfo.id),
+ TYPE_APPLICATION, null)
+ .getSystemService(WindowManager.class)
.getCurrentWindowMetrics().getWindowInsets();
- nonOverlappingTaskbarInset =
- taskbarSize - windowInsets.getSystemWindowInsetBottom();
+ nonOverlappingTaskbarInset = taskbarSize - windowInsets.getSystemWindowInsetBottom();
if (nonOverlappingTaskbarInset > 0) {
nonFinalAvailableHeightPx -= nonOverlappingTaskbarInset;
}
@@ -259,7 +274,7 @@
res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right);
folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
- setCellLayoutBorderSpacing(pxFromDp(inv.borderSpacing, mInfo.metrics, 1f));
+ setCellLayoutBorderSpacing(pxFromDp(inv.borderSpacing, mMetrics, 1f));
cellLayoutBorderSpacingOriginalPx = cellLayoutBorderSpacingPx;
folderCellLayoutBorderSpacingPx = cellLayoutBorderSpacingPx;
@@ -306,7 +321,7 @@
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
int hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
- hotseatBarSizePx = pxFromDp(inv.iconSize, mInfo.metrics, 1f)
+ hotseatBarSizePx = pxFromDp(inv.iconSize, mMetrics, 1f)
+ (isVerticalBarLayout()
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
: (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx
@@ -353,11 +368,10 @@
updateWorkspacePadding();
// This is done last, after iconSizePx is calculated above.
- mDotRendererWorkSpace = new DotRenderer(iconSizePx, IconShape.getShapePath(),
- IconShape.DEFAULT_PATH_SIZE);
+ Path dotPath = GraphicsUtils.getShapePath(DEFAULT_DOT_SIZE);
+ mDotRendererWorkSpace = new DotRenderer(iconSizePx, dotPath, DEFAULT_DOT_SIZE);
mDotRendererAllApps = iconSizePx == allAppsIconSizePx ? mDotRendererWorkSpace :
- new DotRenderer(allAppsIconSizePx, IconShape.getShapePath(),
- IconShape.DEFAULT_PATH_SIZE);
+ new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
private void setCellLayoutBorderSpacing(int borderSpacing) {
@@ -509,16 +523,16 @@
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
float invIconSizeDp = isLandscape ? inv.landscapeIconSize : inv.iconSize;
- iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale));
+ iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
float invIconTextSizeSp = isLandscape ? inv.landscapeIconTextSize : inv.iconTextSize;
- iconTextSizePx = (int) (Utilities.pxFromSp(invIconTextSizeSp, mInfo.metrics) * scale);
+ iconTextSizePx = (int) (Utilities.pxFromSp(invIconTextSizeSp, mMetrics) * scale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
setCellLayoutBorderSpacing((int) (cellLayoutBorderSpacingOriginalPx * scale));
if (isScalableGrid) {
- cellWidthPx = pxFromDp(inv.minCellWidth, mInfo.metrics, scale);
- cellHeightPx = pxFromDp(inv.minCellHeight, mInfo.metrics, scale);
+ cellWidthPx = pxFromDp(inv.minCellWidth, mMetrics, scale);
+ cellHeightPx = pxFromDp(inv.minCellHeight, mMetrics, scale);
int cellContentHeight = iconSizePx + iconDrawablePaddingPx
+ Utilities.calculateTextHeight(iconTextSizePx);
cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
@@ -540,8 +554,8 @@
// All apps
if (allAppsHasDifferentNumColumns()) {
- allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mInfo.metrics);
- allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mInfo.metrics);
+ allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mMetrics);
+ allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mMetrics);
allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
autoResizeAllAppsCells();
} else {
@@ -611,8 +625,8 @@
private void updateFolderCellSize(float scale, Resources res) {
float invIconSizeDp = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize;
- folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale));
- folderChildTextSizePx = pxFromDp(inv.iconTextSize, mInfo.metrics, scale);
+ folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
+ folderChildTextSizePx = pxFromDp(inv.iconTextSize, mMetrics, scale);
folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
@@ -799,14 +813,8 @@
*/
public boolean updateIsSeascape(Context context) {
if (isVerticalBarLayout()) {
- // Check an up-to-date info.
- DisplayController.Info displayInfo = DisplayController.getDefaultDisplay(context)
- .createInfoForContext(context);
- if (displayInfo == null) {
- return false;
- }
-
- boolean isSeascape = displayInfo.rotation == Surface.ROTATION_270;
+ boolean isSeascape = DisplayController.INSTANCE.get(context)
+ .getInfo().rotation == Surface.ROTATION_270;
if (mIsSeascape != isSeascape) {
mIsSeascape = isSeascape;
return true;
@@ -838,12 +846,12 @@
}
private String pxToDpStr(String name, float value) {
- return "\t" + name + ": " + value + "px (" + dpiFromPx(value, mInfo.metrics) + "dp)";
+ return "\t" + name + ": " + value + "px (" + dpiFromPx(value, mMetrics.densityDpi) + "dp)";
}
public void dump(String prefix, PrintWriter writer) {
writer.println(prefix + "DeviceProfile:");
- writer.println(prefix + "\t1 dp = " + mInfo.metrics.density + " px");
+ writer.println(prefix + "\t1 dp = " + mMetrics.density + " px");
writer.println(prefix + "\tisTablet:" + isTablet);
writer.println(prefix + "\tisLargeTablet:" + isLargeTablet);
@@ -936,7 +944,7 @@
private static Context getContext(Context c, Info info, int orientation) {
Configuration config = new Configuration(c.getResources().getConfiguration());
config.orientation = orientation;
- config.densityDpi = info.metrics.densityDpi;
+ config.densityDpi = info.densityDpi;
return c.createConfigurationContext(config);
}
@@ -973,6 +981,10 @@
mInfo = info;
mTransposeLayoutWithOrientation = context.getResources()
.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
+ "transposeLayout=" + mTransposeLayoutWithOrientation);
+ }
}
public Builder setSizeRange(Point minSize, Point maxSize) {
@@ -985,6 +997,10 @@
mWidth = width;
mHeight = height;
mIsLandscape = mWidth > mHeight;
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
+ "isLandscape=" + mIsLandscape + " w=" + mWidth + " h=" + mHeight);
+ }
return this;
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index f198777..1332e14 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -18,8 +18,9 @@
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.Utilities.getPointString;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME;
+import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import static com.android.launcher3.util.DisplayController.CHANGE_SIZE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
@@ -48,7 +49,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.graphics.IconShape;
-import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.IntArray;
@@ -155,7 +156,6 @@
public Rect defaultWidgetPadding;
private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
- private ConfigMonitor mConfigMonitor;
private OverlayMonitor mOverlayMonitor;
@VisibleForTesting
@@ -202,7 +202,12 @@
.putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, getPointString(numColumns, numRows))
.apply();
- mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
+ DisplayController.INSTANCE.get(context).addChangeListener(
+ (displayContext, info, flags) -> {
+ if ((flags & (CHANGE_SIZE | CHANGE_DENSITY)) != 0) {
+ onConfigChanged(displayContext);
+ }
+ });
mOverlayMonitor = new OverlayMonitor(context);
}
@@ -221,12 +226,12 @@
*/
public InvariantDeviceProfile(Context context, Display display) {
// Ensure that the main device profile is initialized
- InvariantDeviceProfile originalProfile = INSTANCE.get(context);
+ INSTANCE.get(context);
String gridName = getCurrentGridName(context);
// Get the display info based on default display and interpolate it to existing display
DisplayOption defaultDisplayOption = invDistWeightedInterpolate(
- DisplayController.getDefaultDisplay(context).getInfo(),
+ DisplayController.INSTANCE.get(context).getInfo(),
getPredefinedDeviceProfiles(context, gridName));
Info myInfo = new Info(context, display);
@@ -256,9 +261,6 @@
if (ENABLE_TWO_PANEL_HOME.get()) {
return ENABLE_TWO_PANEL_HOME.key;
}
- if (ENABLE_FOUR_COLUMNS.get()) {
- return ENABLE_FOUR_COLUMNS.key;
- }
return Utilities.isGridOptionsEnabled(context)
? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null;
}
@@ -275,7 +277,7 @@
}
private String initGrid(Context context, String gridName) {
- Info displayInfo = DisplayController.getDefaultDisplay(context).getInfo();
+ Info displayInfo = DisplayController.INSTANCE.get(context).getInfo();
ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
@@ -285,6 +287,7 @@
private void initGrid(
Context context, Info displayInfo, DisplayOption displayOption) {
+ DisplayMetrics metrics = context.getResources().getDisplayMetrics();
GridOption closestProfile = displayOption.grid;
numRows = closestProfile.numRows;
numColumns = closestProfile.numColumns;
@@ -302,7 +305,7 @@
iconSize = displayOption.iconSize;
iconShapePath = getIconShapePath(context);
landscapeIconSize = displayOption.landscapeIconSize;
- iconBitmapSize = ResourceUtils.pxFromDp(iconSize, displayInfo.metrics);
+ iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
iconTextSize = displayOption.iconTextSize;
landscapeIconTextSize = displayOption.landscapeIconTextSize;
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
@@ -327,7 +330,7 @@
// If the partner customization apk contains any grid overrides, apply them
// Supported overrides: numRows, numColumns, iconSize
- applyPartnerDeviceProfileOverrides(context, displayInfo.metrics);
+ applyPartnerDeviceProfileOverrides(context, metrics);
Point realSize = new Point(displayInfo.realSize);
// The real size never changes. smallSide and largeSide will remain the
@@ -338,6 +341,10 @@
DeviceProfile.Builder builder = new DeviceProfile.Builder(context, this, displayInfo)
.setSizeRange(new Point(displayInfo.smallestSize),
new Point(displayInfo.largestSize));
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED,
+ "largeSide=" + largeSide + " smallSide=" + smallSide);
+ }
landscapeProfile = builder.setSize(largeSide, smallSide).build();
portraitProfile = builder.setSize(smallSide, largeSide).build();
@@ -389,6 +396,9 @@
}
private void onConfigChanged(Context context) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "IDP.onConfigChanged");
+ }
// Config changes, what shall we do?
InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
@@ -417,10 +427,6 @@
}
private void apply(Context context, int changeFlags) {
- // Create a new config monitor
- mConfigMonitor.unregister();
- mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
-
for (OnIDPChangeListener listener : mChangeListeners) {
listener.onIdpChanged(changeFlags, this);
}
@@ -522,10 +528,10 @@
Point largestSize = new Point(displayInfo.largestSize);
// This guarantees that width < height
- float width = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y),
- displayInfo.metrics);
- float height = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y),
- displayInfo.metrics);
+ float width = Utilities.dpiFromPx((float) Math.min(smallestSize.x, smallestSize.y),
+ displayInfo.densityDpi);
+ float height = Utilities.dpiFromPx((float) Math.min(largestSize.x, largestSize.y),
+ displayInfo.densityDpi);
// Sort the profiles based on the closeness to the device size
Collections.sort(points, (a, b) ->
@@ -571,6 +577,10 @@
}
public DeviceProfile getDeviceProfile(Context context) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "getDeviceProfile: orientation="
+ + context.getResources().getConfiguration().orientation);
+ }
return context.getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE ? landscapeProfile : portraitProfile;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3236f5d..f640118 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -551,11 +551,16 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
-
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
onIdpChanged(mDeviceProfile.inv);
}
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "onConfigurationChanged: diff=" + diff);
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "newConfig=" + newConfig);
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "oldConfig=" + mOldConfig);
+ }
+
mOldConfig.setTo(newConfig);
super.onConfigurationChanged(newConfig);
}
@@ -566,7 +571,9 @@
}
private void onIdpChanged(InvariantDeviceProfile idp) {
-
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "onIdpChanged");
+ }
initDeviceProfile(idp);
dispatchDeviceProfileChanged();
reapplyUi();
@@ -1419,6 +1426,7 @@
return mDropTargetBar;
}
+ @Override
public ScrimView getScrimView() {
return mScrimView;
}
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 803f8d2..b56c012 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -19,6 +19,8 @@
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.util.IntProperty;
@@ -135,6 +137,22 @@
}
};
+ public static final IntProperty<View> VIEW_BACKGROUND_COLOR =
+ new IntProperty<View>("backgroundColor") {
+ @Override
+ public void setValue(View view, int color) {
+ view.setBackgroundColor(color);
+ }
+
+ @Override
+ public Integer get(View view) {
+ if (!(view.getBackground() instanceof ColorDrawable)) {
+ return Color.TRANSPARENT;
+ }
+ return ((ColorDrawable) view.getBackground()).getColor();
+ }
+ };
+
/**
* Utility method to create an {@link AnimatorListener} which executes a callback on animation
* cancel.
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4754558..11585f9 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -17,9 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
-import static com.android.launcher3.InvariantDeviceProfile.KEY_MIGRATION_SRC_HOTSEAT_COUNT;
-import static com.android.launcher3.InvariantDeviceProfile.KEY_MIGRATION_SRC_WORKSPACE_SIZE;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
@@ -126,33 +123,6 @@
mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context);
- // b/175329686 Temporary logic to gracefully migrate group of users to the new 4x5 grid.
- String gridName = InvariantDeviceProfile.getCurrentGridName(context);
- if (ENABLE_FOUR_COLUMNS.get()
- || "reasonable".equals(gridName)
- || ENABLE_FOUR_COLUMNS.key.equals(gridName)) {
- // Reset flag and remove it from developer options to prevent it from being enabled
- // again.
- ENABLE_FOUR_COLUMNS.reset(context);
- FeatureFlags.removeFlag(ENABLE_FOUR_COLUMNS);
-
- // Force migration code to run
- Utilities.getPrefs(context).edit()
- .remove(KEY_MIGRATION_SRC_HOTSEAT_COUNT)
- .remove(KEY_MIGRATION_SRC_WORKSPACE_SIZE)
- .apply();
-
- // We make an empty call here to ensure the database is created with the old IDP grid,
- // so that when we set the new grid the migration can proceeds as expected.
- LauncherSettings.Settings.call(context.getContentResolver(), "");
-
- String newGridName = "practical";
- Utilities.getPrefs(mContext).edit().putString("idp_grid_name", newGridName).commit();
- mInvariantDeviceProfile.setCurrentGrid(context, "practical");
- } else {
- FeatureFlags.removeFlag(ENABLE_FOUR_COLUMNS);
- }
-
mIconCache = new IconCache(mContext, mInvariantDeviceProfile, iconCacheFileName);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext));
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 83ddf64..f26cfe8 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -33,11 +33,12 @@
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mForceHideBackArrow;
- private SysUiScrim mSysUiScrim;
+ private final SysUiScrim mSysUiScrim;
public LauncherRootView(Context context, AttributeSet attrs) {
super(context, attrs);
mActivity = StatefulActivity.fromContext(context);
+ mSysUiScrim = new SysUiScrim(this);
}
private void handleSystemWindowInsets(Rect insets) {
@@ -72,6 +73,7 @@
// modifying child layout params.
if (!insets.equals(mInsets)) {
super.setInsets(insets);
+ mSysUiScrim.onInsetsChanged(insets);
}
}
@@ -100,15 +102,9 @@
}
}
- public void setSysUiScrim(SysUiScrim scrim) {
- mSysUiScrim = scrim;
- }
-
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mSysUiScrim != null) {
- mSysUiScrim.draw(canvas);
- }
+ mSysUiScrim.draw(canvas);
super.dispatchDraw(canvas);
}
@@ -117,6 +113,7 @@
super.onLayout(changed, l, t, r, b);
SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
setDisallowBackGesture(mDisallowBackGesture);
+ mSysUiScrim.setSize(r - l, b - t);
}
@TargetApi(Build.VERSION_CODES.Q)
@@ -136,6 +133,10 @@
: Collections.emptyList());
}
+ public SysUiScrim getSysUiScrim() {
+ return mSysUiScrim;
+ }
+
public interface WindowStateListener {
void onWindowFocusChanged(boolean hasFocus);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 58df9c8..4c11725 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -30,6 +30,7 @@
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import android.content.Context;
+import android.graphics.Color;
import android.view.animation.Interpolator;
import com.android.launcher3.statemanager.BaseState;
@@ -217,8 +218,12 @@
return 0;
}
- public float getWorkspaceScrimAlpha(Launcher launcher) {
- return 0;
+ /**
+ * What color should the workspace scrim be in when at rest in this state.
+ * Return {@link Color#TRANSPARENT} for no scrim.
+ */
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Color.TRANSPARENT;
}
/**
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 7496703..c9cc372 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -16,16 +16,14 @@
package com.android.launcher3;
+import static com.android.launcher3.anim.Interpolators.SCROLL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
-import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.touch.OverScroll.OVERSCROLL_DAMP_FACTOR;
-import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_BY;
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_TO;
import android.animation.LayoutTransition;
-import android.animation.TimeInterpolator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
@@ -46,19 +44,17 @@
import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.Interpolator;
+import android.widget.OverScroller;
import android.widget.ScrollView;
import androidx.annotation.Nullable;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.pageindicators.PageIndicator;
-import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds;
-import com.android.launcher3.util.OverScroller;
+import com.android.launcher3.util.EdgeEffectCompat;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
@@ -80,9 +76,6 @@
public static final int PAGE_SNAP_ANIMATION_DURATION = 750;
- // OverScroll constants
- private final static int OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION = 270;
-
private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
// The page is moved more than halfway, automatically move to the next page on touch up.
private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
@@ -113,7 +106,6 @@
protected int mMaxScroll;
protected int mMinScroll;
protected OverScroller mScroller;
- private Interpolator mDefaultInterpolator;
private VelocityTracker mVelocityTracker;
protected int mPageSpacing = 0;
@@ -144,12 +136,6 @@
protected boolean mIsPageInTransition = false;
private Runnable mOnPageTransitionEndCallback;
- protected float mSpringOverScroll;
-
- protected boolean mWasInOverscroll = false;
-
- protected int mUnboundedScroll;
-
// Page Indicator
@Thunk int mPageIndicatorViewId;
protected T mPageIndicator;
@@ -162,6 +148,9 @@
private int[] mTmpIntPair = new int[2];
+ protected EdgeEffectCompat mEdgeGlowLeft;
+ protected EdgeEffectCompat mEdgeGlowRight;
+
public PagedView(Context context) {
this(context, null);
}
@@ -181,8 +170,7 @@
setHapticFeedbackEnabled(false);
mIsRtl = Utilities.isRtl(getResources());
- mScroller = new OverScroller(context);
- setDefaultInterpolator(Interpolators.SCROLL);
+ mScroller = new OverScroller(context, SCROLL);
mCurrentPage = 0;
final ViewConfiguration configuration = ViewConfiguration.get(context);
@@ -196,12 +184,14 @@
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density);
+ initEdgeEffect();
setDefaultFocusHighlightEnabled(false);
+ setWillNotDraw(false);
}
- protected void setDefaultInterpolator(Interpolator interpolator) {
- mDefaultInterpolator = interpolator;
- mScroller.setInterpolator(mDefaultInterpolator);
+ protected void initEdgeEffect() {
+ mEdgeGlowLeft = new EdgeEffectCompat(getContext());
+ mEdgeGlowRight = new EdgeEffectCompat(getContext());
}
public void initParentViews(View parent) {
@@ -256,7 +246,7 @@
newPosition = getScrollForPage(mCurrentPage);
}
mOrientationHandler.set(this, VIEW_SCROLL_TO, newPosition);
- mOrientationHandler.scrollerStartScroll(mScroller, newPosition);
+ mScroller.startScroll(mScroller.getCurrX(), 0, newPosition - mScroller.getCurrX(), 0);
forceFinishScroller(true);
}
@@ -420,7 +410,6 @@
* to provide custom behavior during animation.
*/
protected void onPageEndTransition() {
- mWasInOverscroll = false;
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
@@ -442,56 +431,12 @@
}
}
- protected int getUnboundedScroll() {
- return mUnboundedScroll;
- }
-
- @Override
- public void scrollBy(int x, int y) {
- mOrientationHandler.delegateScrollBy(this, getUnboundedScroll(), x, y);
- }
-
@Override
public void scrollTo(int x, int y) {
- int primaryScroll = mOrientationHandler.getPrimaryValue(x, y);
- int secondaryScroll = mOrientationHandler.getSecondaryValue(x, y);
- mUnboundedScroll = primaryScroll;
-
- boolean isBeforeFirstPage = mIsRtl ?
- (primaryScroll > mMaxScroll) : (primaryScroll < mMinScroll);
- boolean isAfterLastPage = mIsRtl ?
- (primaryScroll < mMinScroll) : (primaryScroll > mMaxScroll);
- if (!isBeforeFirstPage && !isAfterLastPage) {
- mSpringOverScroll = 0;
- }
-
- if (isBeforeFirstPage) {
- mOrientationHandler.delegateScrollTo(this,
- secondaryScroll, mIsRtl ? mMaxScroll : mMinScroll);
- if (mAllowOverScroll) {
- mWasInOverscroll = true;
- overScroll(primaryScroll - (mIsRtl ? mMaxScroll : mMinScroll));
- }
- } else if (isAfterLastPage) {
- mOrientationHandler.delegateScrollTo(this,
- secondaryScroll, mIsRtl ? mMinScroll : mMaxScroll);
- if (mAllowOverScroll) {
- mWasInOverscroll = true;
- overScroll(primaryScroll - (mIsRtl ? mMinScroll : mMaxScroll));
- }
- } else {
- if (mWasInOverscroll) {
- overScroll(0);
- mWasInOverscroll = false;
- }
- super.scrollTo(x, y);
- }
- }
-
- /**
- * Helper for {@link PagedOrientationHandler} to be able to call parent's scrollTo method
- */
- public void superScrollTo(int x, int y) {
+ x = Utilities.boundToRange(x,
+ mOrientationHandler.getPrimaryValue(mMinScroll, 0), mMaxScroll);
+ y = Utilities.boundToRange(y,
+ mOrientationHandler.getPrimaryValue(0, mMinScroll), mMaxScroll);
super.scrollTo(x, y);
}
@@ -524,12 +469,22 @@
protected boolean computeScrollHelper(boolean shouldInvalidate) {
if (mScroller.computeScrollOffset()) {
// Don't bother scrolling if the page does not need to be moved
- int currentScroll = mOrientationHandler.getPrimaryScroll(this);
- if (mUnboundedScroll != mScroller.getCurrPos()
- || currentScroll != mScroller.getCurrPos()) {
- mOrientationHandler.set(this, VIEW_SCROLL_TO, mScroller.getCurrPos());
+ int oldPos = mOrientationHandler.getPrimaryScroll(this);
+ int newPos = mScroller.getCurrX();
+ if (oldPos != newPos) {
+ mOrientationHandler.set(this, VIEW_SCROLL_TO, mScroller.getCurrX());
}
if (shouldInvalidate) {
+ if (mAllowOverScroll) {
+ if (newPos < mMinScroll && oldPos >= mMinScroll) {
+ mEdgeGlowLeft.onAbsorb((int) mScroller.getCurrVelocity());
+ mScroller.abortAnimation();
+ } else if (newPos > mMaxScroll && oldPos <= mMaxScroll) {
+ mEdgeGlowRight.onAbsorb((int) mScroller.getCurrVelocity());
+ mScroller.abortAnimation();
+ }
+ }
+
invalidate();
}
return true;
@@ -982,9 +937,7 @@
mTotalMotion = 0;
mAllowEasyFling = false;
mActivePointerId = ev.getPointerId(0);
-
- updateIsBeingDraggedOnTouchDown();
-
+ updateIsBeingDraggedOnTouchDown(ev);
break;
}
@@ -1009,9 +962,9 @@
/**
* If being flinged and user touches the screen, initiate drag; otherwise don't.
*/
- private void updateIsBeingDraggedOnTouchDown() {
+ private void updateIsBeingDraggedOnTouchDown(MotionEvent ev) {
// mScroller.isFinished should be false when being flinged.
- final int xDist = Math.abs(mScroller.getFinalPos() - mScroller.getCurrPos());
+ final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
final boolean finishedScrolling = (mScroller.isFinished() || xDist < mPageSlop / 3);
if (finishedScrolling) {
@@ -1020,9 +973,20 @@
setCurrentPage(getNextPage());
pageEndTransition();
}
+ mIsBeingDragged = !mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished();
} else {
mIsBeingDragged = true;
}
+
+ // Catch the edge effect if it is active.
+ float displacement = mOrientationHandler.getSecondaryValue(ev.getX(), ev.getY())
+ / mOrientationHandler.getSecondaryValue(getWidth(), getHeight());
+ if (!mEdgeGlowLeft.isFinished()) {
+ mEdgeGlowLeft.onPullDistance(0f, 1f - displacement);
+ }
+ if (!mEdgeGlowRight.isFinished()) {
+ mEdgeGlowRight.onPullDistance(0f, displacement);
+ }
}
public boolean isHandlingTouch() {
@@ -1053,7 +1017,6 @@
mTotalMotion += Math.abs(mLastMotion - primaryDirection);
mLastMotion = primaryDirection;
mLastMotionRemainder = 0;
- onScrollInteractionBegin();
pageBeginTransition();
// Stop listening for things like pinches.
requestDisallowInterceptTouchEvent(true);
@@ -1114,69 +1077,6 @@
}
}
- @Override
- protected void dispatchDraw(Canvas canvas) {
- if (mScroller.isSpringing() && mSpringOverScroll != 0) {
- int saveCount = canvas.save();
- mOrientationHandler.set(canvas, CANVAS_TRANSLATE, -mSpringOverScroll);
- super.dispatchDraw(canvas);
-
- canvas.restoreToCount(saveCount);
- } else {
- super.dispatchDraw(canvas);
- }
- }
-
- /**
- * Returns the amount of overscroll caused by the spring in {@link OverScroller}.
- */
- private int getSpringOverScroll(int amount) {
- if (mScroller.isSpringing()) {
- return amount < 0
- ? mScroller.getCurrPos() - mMinScroll
- : Math.max(0, mScroller.getCurrPos() - mMaxScroll);
- } else {
- return 0;
- }
- }
-
- protected void dampedOverScroll(int amount) {
- if (amount == 0) {
- return;
- }
-
- int size = mOrientationHandler.getMeasuredSize(this);
- int overScrollAmount = OverScroll.dampedScroll(amount, size);
- if (mScroller.isSpringing()) {
- mSpringOverScroll = getSpringOverScroll(amount);
- invalidate();
- return;
- }
-
- int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
- int boundedScroll = Utilities.boundToRange(primaryScroll, mMinScroll, mMaxScroll);
- mOrientationHandler.delegateScrollTo(this, boundedScroll + overScrollAmount);
- invalidate();
- }
-
- protected void overScroll(int amount) {
- if (mScroller.isSpringing()) {
- mSpringOverScroll = getSpringOverScroll(amount);
- invalidate();
- return;
- }
-
- if (amount == 0) return;
-
- if (mFreeScroll && !mScroller.isFinished()) {
- int scrollAmount = amount < 0 ? mMinScroll + amount : mMaxScroll + amount;
- mOrientationHandler.delegateScrollTo(this, scrollAmount);
- } else {
- dampedOverScroll(amount);
- }
- }
-
-
public void setEnableFreeScroll(boolean freeScroll) {
if (mFreeScroll == freeScroll) {
return;
@@ -1209,7 +1109,7 @@
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
- updateIsBeingDraggedOnTouchDown();
+ updateIsBeingDraggedOnTouchDown(ev);
/*
* If being flinged and user touches, stop the fling. isFinished
@@ -1228,7 +1128,6 @@
mAllowEasyFling = false;
mActivePointerId = ev.getPointerId(0);
if (mIsBeingDragged) {
- onScrollInteractionBegin();
pageBeginTransition();
}
break;
@@ -1245,19 +1144,62 @@
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == -1) return true;
+ float oldScroll = mOrientationHandler.getPrimaryScroll(this);
+ float dx = ev.getX(pointerIndex);
+ float dy = ev.getY(pointerIndex);
- float direction = mOrientationHandler.getPrimaryDirection(ev, pointerIndex);
+ float direction = mOrientationHandler.getPrimaryValue(dx, dy);
float delta = mLastMotion + mLastMotionRemainder - direction;
+
+ int width = getWidth();
+ int height = getHeight();
+ int size = mOrientationHandler.getPrimaryValue(width, height);
+
+ final float displacement = mOrientationHandler.getSecondaryValue(dx, dy)
+ / mOrientationHandler.getSecondaryValue(width, height);
mTotalMotion += Math.abs(delta);
+ if (mAllowOverScroll) {
+ float consumed = 0;
+ if (delta < 0 && mEdgeGlowRight.getDistance() != 0f) {
+ consumed = size * mEdgeGlowRight.onPullDistance(delta / size, displacement);
+ } else if (delta > 0 && mEdgeGlowLeft.getDistance() != 0f) {
+ consumed = -size * mEdgeGlowLeft.onPullDistance(
+ -delta / size, 1 - displacement);
+ }
+ delta -= consumed;
+ }
+
// Only scroll and update mLastMotionX if we have moved some discrete amount. We
// keep the remainder because we are actually testing if we've moved from the last
// scrolled position (which is discrete).
- if (Math.abs(delta) >= 1.0f) {
- mLastMotion = direction;
- mLastMotionRemainder = delta - (int) delta;
+ mLastMotion = direction;
+ int movedDelta = (int) delta;
+ mLastMotionRemainder = delta - movedDelta;
- mOrientationHandler.set(this, VIEW_SCROLL_BY, (int) delta);
+ if (delta != 0) {
+ mOrientationHandler.set(this, VIEW_SCROLL_BY, movedDelta);
+
+ if (mAllowOverScroll) {
+ final float pulledToX = oldScroll + delta;
+
+ if (pulledToX < mMinScroll) {
+ mEdgeGlowLeft.onPullDistance(-delta / size, 1.f - displacement);
+ if (!mEdgeGlowRight.isFinished()) {
+ mEdgeGlowRight.onRelease();
+ }
+ } else if (pulledToX > mMaxScroll) {
+ mEdgeGlowRight.onPullDistance(delta / size, displacement);
+ if (!mEdgeGlowLeft.isFinished()) {
+ mEdgeGlowLeft.onRelease();
+ }
+ }
+
+ if (!mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished()) {
+ postInvalidateOnAnimation();
+ }
+ }
+
} else {
awakenScrollBars();
}
@@ -1335,45 +1277,24 @@
if (((initialScroll >= maxScroll) && (isVelocityLeft || !isFling)) ||
((initialScroll <= minScroll) && (!isVelocityLeft || !isFling))) {
- mScroller.springBack(initialScroll, minScroll, maxScroll);
+ mScroller.springBack(initialScroll, 0, minScroll, maxScroll, 0, 0);
mNextPage = getDestinationPage();
} else {
- mScroller.setInterpolator(mDefaultInterpolator);
- mScroller.fling(initialScroll, -velocity,
- minScroll, maxScroll,
- Math.round(getWidth() * 0.5f * OVERSCROLL_DAMP_FACTOR));
+ int velocity1 = -velocity;
+ // Continue a scroll or fling in progress
+ mScroller.fling(initialScroll, 0, velocity1, 0, minScroll, maxScroll, 0, 0,
+ Math.round(getWidth() * 0.5f * OVERSCROLL_DAMP_FACTOR), 0);
- int finalPos = mScroller.getFinalPos();
+ int finalPos = mScroller.getFinalX();
mNextPage = getDestinationPage(finalPos);
-
- int firstPageScroll = getScrollForPage(!mIsRtl ? 0 : getPageCount() - 1);
- int lastPageScroll = getScrollForPage(!mIsRtl ? getPageCount() - 1 : 0);
- if (snapToPageInFreeScroll() && finalPos > minScroll
- && finalPos < maxScroll) {
- // If scrolling ends in the half of the added space that is closer to
- // the end, settle to the end. Otherwise snap to the nearest page.
- // If flinging past one of the ends, don't change the velocity as it
- // will get stopped at the end anyway.
- int pageSnapped = finalPos < (firstPageScroll + minScroll) / 2
- ? minScroll
- : finalPos > (lastPageScroll + maxScroll) / 2
- ? maxScroll
- : getScrollForPage(mNextPage);
-
- mScroller.setFinalPos(pageSnapped);
- // Ensure the scroll/snap doesn't happen too fast;
- int extraScrollDuration = OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION
- - mScroller.getDuration();
- if (extraScrollDuration > 0) {
- mScroller.extendDuration(extraScrollDuration);
- }
- }
+ onNotSnappingToPageInFreeScroll();
}
invalidate();
}
- onScrollInteractionEnd();
}
+ mEdgeGlowLeft.onRelease();
+ mEdgeGlowRight.onRelease();
// End any intermediate reordering states
resetTouchState();
break;
@@ -1381,8 +1302,9 @@
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged) {
snapToDestination();
- onScrollInteractionEnd();
}
+ mEdgeGlowLeft.onRelease();
+ mEdgeGlowRight.onRelease();
resetTouchState();
break;
@@ -1395,9 +1317,7 @@
return true;
}
- protected boolean snapToPageInFreeScroll() {
- return true;
- }
+ protected void onNotSnappingToPageInFreeScroll() { }
protected boolean shouldFlingForVelocity(int velocity) {
float threshold = mAllowEasyFling ? mEasyFlingThresholdVelocity : mFlingThresholdVelocity;
@@ -1410,15 +1330,6 @@
mActivePointerId = INVALID_POINTER;
}
- /**
- * Triggered by scrolling via touch
- */
- protected void onScrollInteractionBegin() {
- }
-
- protected void onScrollInteractionEnd() {
- }
-
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
@@ -1554,19 +1465,7 @@
}
protected void snapToDestination() {
- snapToPage(getDestinationPage(), getPageSnapDuration());
- }
-
- protected boolean isInOverScroll() {
- int scroll = mOrientationHandler.getPrimaryScroll(this);
- return scroll > mMaxScroll || scroll < mMinScroll;
- }
-
- protected int getPageSnapDuration() {
- if (isInOverScroll()) {
- return OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION;
- }
- return PAGE_SNAP_ANIMATION_DURATION;
+ snapToPage(getDestinationPage(), PAGE_SNAP_ANIMATION_DURATION);
}
// We want the duration of the page snap animation to be influenced by the distance that
@@ -1584,7 +1483,7 @@
int halfScreenSize = mOrientationHandler.getMeasuredSize(this) / 2;
final int newLoc = getScrollForPage(whichPage);
- int delta = newLoc - getUnboundedScroll();
+ int delta = newLoc - mOrientationHandler.getPrimaryScroll(this);
int duration = 0;
if (Math.abs(velocity) < mMinFlingVelocity) {
@@ -1609,12 +1508,7 @@
// interpolator at zero, ie. 5. We use 4 to make it a little slower.
duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
- if (QUICKSTEP_SPRINGS.get() && mCurrentPage != whichPage) {
- return snapToPage(whichPage, delta, duration, false, null,
- velocity * Math.signum(delta), true);
- } else {
- return snapToPage(whichPage, delta, duration);
- }
+ return snapToPage(whichPage, delta, duration);
}
public boolean snapToPage(int whichPage) {
@@ -1622,32 +1516,26 @@
}
public boolean snapToPageImmediately(int whichPage) {
- return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null);
+ return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
}
public boolean snapToPage(int whichPage, int duration) {
- return snapToPage(whichPage, duration, false, null);
+ return snapToPage(whichPage, duration, false);
}
- public boolean snapToPage(int whichPage, int duration, TimeInterpolator interpolator) {
- return snapToPage(whichPage, duration, false, interpolator);
- }
-
- protected boolean snapToPage(int whichPage, int duration, boolean immediate,
- TimeInterpolator interpolator) {
+ protected boolean snapToPage(int whichPage, int duration, boolean immediate) {
whichPage = validateNewPage(whichPage);
int newLoc = getScrollForPage(whichPage);
- final int delta = newLoc - getUnboundedScroll();
- return snapToPage(whichPage, delta, duration, immediate, interpolator, 0, false);
+ final int delta = newLoc - mOrientationHandler.getPrimaryScroll(this);
+ return snapToPage(whichPage, delta, duration, immediate);
}
protected boolean snapToPage(int whichPage, int delta, int duration) {
- return snapToPage(whichPage, delta, duration, false, null, 0, false);
+ return snapToPage(whichPage, delta, duration, false);
}
- protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate,
- TimeInterpolator interpolator, float velocity, boolean spring) {
+ protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate) {
if (mFirstLayout) {
setCurrentPage(whichPage);
return false;
@@ -1677,18 +1565,7 @@
abortScrollerAnimation(false);
}
- if (interpolator != null) {
- mScroller.setInterpolator(interpolator);
- } else {
- mScroller.setInterpolator(mDefaultInterpolator);
- }
-
- if (spring && QUICKSTEP_SPRINGS.get()) {
- mScroller.startScrollSpring(getUnboundedScroll(), delta, duration, velocity);
- } else {
- mScroller.startScroll(getUnboundedScroll(), delta, duration);
- }
-
+ mScroller.startScroll(mOrientationHandler.getPrimaryScroll(this), 0, delta, 0, duration);
updatePageIndicator();
// Trigger a compute() to finish switching pages if necessary
@@ -1706,7 +1583,7 @@
snapToPage(getNextPage() - 1);
return true;
}
- return onOverscroll(-getMeasuredWidth());
+ return mAllowOverScroll;
}
public boolean scrollRight() {
@@ -1714,15 +1591,7 @@
snapToPage(getNextPage() + 1);
return true;
}
- return onOverscroll(getMeasuredWidth());
- }
-
- protected boolean onOverscroll(int amount) {
- if (!mAllowOverScroll) return false;
- onScrollInteractionBegin();
- overScroll(amount);
- onScrollInteractionEnd();
- return true;
+ return mAllowOverScroll;
}
@Override
@@ -1866,4 +1735,38 @@
mTmpIntPair[1] = rightChild;
return mTmpIntPair;
}
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ drawEdgeEffect(canvas);
+ }
+
+ protected void drawEdgeEffect(Canvas canvas) {
+ if (mAllowOverScroll && (!mEdgeGlowRight.isFinished() || !mEdgeGlowLeft.isFinished())) {
+ final int width = getWidth();
+ final int height = getHeight();
+ if (!mEdgeGlowLeft.isFinished()) {
+ final int restoreCount = canvas.save();
+ canvas.rotate(-90);
+ canvas.translate(-height, Math.min(mMinScroll, getScrollX()));
+ mEdgeGlowLeft.setSize(height, width);
+ if (mEdgeGlowLeft.draw(canvas)) {
+ postInvalidateOnAnimation();
+ }
+ canvas.restoreToCount(restoreCount);
+ }
+ if (!mEdgeGlowRight.isFinished()) {
+ final int restoreCount = canvas.save();
+ canvas.rotate(90, width, 0);
+ canvas.translate(width, -(Math.max(mMaxScroll, getScrollX())));
+
+ mEdgeGlowRight.setSize(height, width);
+ if (mEdgeGlowRight.draw(canvas)) {
+ postInvalidateOnAnimation();
+ }
+ canvas.restoreToCount(restoreCount);
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
index d79f62d..0bdb37c 100644
--- a/src/com/android/launcher3/Partner.java
+++ b/src/com/android/launcher3/Partner.java
@@ -129,7 +129,7 @@
"dimen", getPackageName());
if (resId > 0) {
int px = getResources().getDimensionPixelSize(resId);
- iconSize = Utilities.dpiFromPx(px, dm);
+ iconSize = Utilities.dpiFromPx((float) px, dm.densityDpi);
}
} catch (Resources.NotFoundException ex) {
Log.e(TAG, "Invalid Partner grid resource!", ex);
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 5036104..fe58da9 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -71,7 +71,7 @@
return;
}
- Log.i(LOG,
+ Log.d(LOG,
"Adding package name to install queue. Package name: " + info.getAppPackageName()
+ ", has app icon: " + (info.getAppIcon() != null)
+ ", has app label: " + !TextUtils.isEmpty(info.getAppLabel()));
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 1776777..a799b4a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -65,6 +65,7 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
import androidx.core.graphics.ColorUtils;
import androidx.core.os.BuildCompat;
@@ -404,8 +405,8 @@
return res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}
- public static float dpiFromPx(float size, DisplayMetrics metrics) {
- float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+ public static float dpiFromPx(float size, int densityDpi) {
+ float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
return (size / densityRatio);
}
@@ -600,7 +601,7 @@
LauncherActivityInfo activityInfo = launcher.getSystemService(LauncherApps.class)
.resolveActivity(info.getIntent(), info.user);
outObj[0] = activityInfo;
- return activityInfo == null ? null : new IconProvider(launcher).getIconForUI(
+ return activityInfo == null ? null : new IconProvider(launcher).getIcon(
activityInfo, launcher.getDeviceProfile().inv.fillResIconDpi);
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
if (info instanceof PendingAddShortcutInfo) {
@@ -752,6 +753,16 @@
ColorUtils.blendARGB(0, color, tintAmount));
}
+ /**
+ * Sets start margin on the provided {@param view} to be {@param margin}.
+ * Assumes {@param view} is a child of {@link LinearLayout}
+ */
+ public static void setStartMarginForView(View view, int margin) {
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
+ lp.setMarginStart(margin);
+ view.setLayoutParams(lp);
+ }
+
private static class FixedSizeEmptyDrawable extends ColorDrawable {
private final int mSize;
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index f43452c..75d25d7 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -457,10 +457,24 @@
drawable.setBounds(x, 0, x + previewWidth, previewHeight);
drawable.draw(c);
} else {
- RectF boxRect = drawBoxWithShadow(c, previewWidth, previewHeight);
+ RectF boxRect;
// Draw horizontal and vertical lines to represent individual columns.
final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ if (Utilities.ATLEAST_S) {
+ boxRect = new RectF(/* left= */ 0, /* top= */ 0, /* right= */
+ previewWidth, /* bottom= */ previewHeight);
+
+ p.setStyle(Paint.Style.FILL);
+ p.setColor(Color.WHITE);
+ float roundedCorner = mContext.getResources().getDimension(
+ android.R.dimen.system_app_widget_background_radius);
+ c.drawRoundRect(boxRect, roundedCorner, roundedCorner, p);
+ } else {
+ boxRect = drawBoxWithShadow(c, previewWidth, previewHeight);
+ }
+
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(mContext.getResources()
.getDimension(R.dimen.widget_preview_cell_divider_width));
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index c9e575d..05d6e04 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -24,7 +24,6 @@
import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_INACCESSIBLE;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
@@ -69,7 +68,6 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.FolderDotInfo;
-import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
@@ -97,10 +95,12 @@
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.WorkspaceTouchListener;
+import com.android.launcher3.util.EdgeEffectCompat;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.OverlayEdgeEffect;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.WallpaperOffsetInterpolator;
@@ -246,10 +246,7 @@
private float mTransitionProgress;
// State related to Launcher Overlay
- LauncherOverlay mLauncherOverlay;
- boolean mScrollInteractionBegan;
- boolean mStartedSendingScrollEvents;
- float mLastOverlayScroll = 0;
+ private OverlayEdgeEffect mOverlayEdgeEffect;
boolean mOverlayShown = false;
private Runnable mOnOverlayHiddenCallback;
@@ -414,7 +411,9 @@
}
if (mDragInfo != null && mDragInfo.cell != null) {
- CellLayout layout = (CellLayout) mDragInfo.cell.getParent().getParent();
+ CellLayout layout = (CellLayout) (mDragInfo.cell instanceof LauncherAppWidgetHostView
+ ? dragObject.dragView.getContentViewParent().getParent()
+ : mDragInfo.cell.getParent().getParent());
layout.markCellsAsUnoccupiedForView(mDragInfo.cell);
}
@@ -944,47 +943,25 @@
}
}
- protected void onScrollInteractionBegin() {
- super.onScrollInteractionBegin();
- mScrollInteractionBegan = true;
- }
-
- protected void onScrollInteractionEnd() {
- super.onScrollInteractionEnd();
- mScrollInteractionBegan = false;
- if (mStartedSendingScrollEvents) {
- mStartedSendingScrollEvents = false;
- mLauncherOverlay.onScrollInteractionEnd();
- }
- }
-
public void setLauncherOverlay(LauncherOverlay overlay) {
- mLauncherOverlay = overlay;
- // A new overlay has been set. Reset event tracking
- mStartedSendingScrollEvents = false;
+ mOverlayEdgeEffect = overlay == null ? null : new OverlayEdgeEffect(getContext(), overlay);
+ EdgeEffectCompat newEffect = overlay == null
+ ? new EdgeEffectCompat(getContext()) : mOverlayEdgeEffect;
+ if (mIsRtl) {
+ mEdgeGlowRight = newEffect;
+ } else {
+ mEdgeGlowLeft = newEffect;
+ }
onOverlayScrollChanged(0);
}
public boolean hasOverlay() {
- return mLauncherOverlay != null;
- }
-
- private boolean isScrollingOverlay() {
- return mLauncherOverlay != null &&
- ((mIsRtl && getUnboundedScroll() > mMaxScroll)
- || (!mIsRtl && getUnboundedScroll() < mMinScroll));
+ return mOverlayEdgeEffect != null;
}
@Override
protected void snapToDestination() {
- // If we're overscrolling the overlay, we make sure to immediately reset the PagedView
- // to it's baseline position instead of letting the overscroll settle. The overlay handles
- // it's own settling, and every gesture to the overlay should be self-contained and start
- // from 0, so we zero it out here.
- if (isScrollingOverlay()) {
- // We reset mWasInOverscroll so that PagedView doesn't zero out the overscroll
- // interaction when we call snapToPageImmediately.
- mWasInOverscroll = false;
+ if (mOverlayEdgeEffect != null && !mOverlayEdgeEffect.isFinished()) {
snapToPageImmediately(0);
} else {
super.snapToDestination();
@@ -1017,38 +994,6 @@
}
@Override
- protected void overScroll(int amount) {
- boolean shouldScrollOverlay = mLauncherOverlay != null && !mScroller.isSpringing() &&
- ((amount <= 0 && !mIsRtl) || (amount >= 0 && mIsRtl));
-
- boolean shouldZeroOverlay = mLauncherOverlay != null && mLastOverlayScroll != 0 &&
- ((amount >= 0 && !mIsRtl) || (amount <= 0 && mIsRtl));
-
- if (shouldScrollOverlay) {
- if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
- mStartedSendingScrollEvents = true;
- mLauncherOverlay.onScrollInteractionBegin();
- }
-
- mLastOverlayScroll = Math.abs(((float) amount) / getMeasuredWidth());
- mLauncherOverlay.onScrollChange(mLastOverlayScroll, mIsRtl);
- } else {
- dampedOverScroll(amount);
- }
-
- if (shouldZeroOverlay) {
- mLauncherOverlay.onScrollChange(0, mIsRtl);
- }
- }
-
- @Override
- protected boolean onOverscroll(int amount) {
- // Enforce overscroll on -1 direction
- if ((amount > 0 && !mIsRtl) || (amount < 0 && mIsRtl)) return false;
- return super.onOverscroll(amount);
- }
-
- @Override
protected boolean shouldFlingForVelocity(int velocityX) {
// When the overlay is moving, the fling or settle transition is controlled by the overlay.
return Float.compare(Math.abs(mOverlayTranslation), 0) == 0 &&
@@ -1376,10 +1321,6 @@
mOutlineProvider = outlineProvider;
}
- public void snapToPageFromOverView(int whichPage) {
- snapToPage(whichPage, OVERVIEW.getTransitionDuration(mLauncher), Interpolators.ZOOM_IN);
- }
-
private void onStartStateTransition(LauncherState state) {
mIsSwitchingState = true;
mTransitionProgress = 0;
@@ -1527,10 +1468,19 @@
draggableView = (DraggableView) child;
}
+ final View contentView = previewProvider.getContentView();
+ final float scale;
// The draggable drawable follows the touch point around on the screen
- final Drawable drawable = previewProvider.createDrawable();
+ final Drawable drawable;
+ if (contentView == null) {
+ drawable = previewProvider.createDrawable();
+ scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
+ } else {
+ drawable = null;
+ scale = previewProvider.getScaleAndPosition(contentView, mTempXY);
+ }
+
int halfPadding = previewProvider.previewPadding / 2;
- float scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
int dragLayerX = mTempXY[0];
int dragLayerY = mTempXY[1];
@@ -1556,22 +1506,37 @@
}
}
- if (drawable instanceof AppWidgetHostViewDrawable) {
- mDragController.addDragListener(new AppWidgetHostViewDragListener(mLauncher));
+ final DragView dv;
+ if (contentView instanceof View) {
+ if (contentView instanceof LauncherAppWidgetHostView) {
+ mDragController.addDragListener(new AppWidgetHostViewDragListener(mLauncher));
+ }
+ dv = mDragController.startDrag(
+ contentView,
+ draggableView,
+ dragLayerX,
+ dragLayerY,
+ source,
+ dragObject,
+ dragVisualizeOffset,
+ dragRect,
+ scale * iconScale,
+ scale,
+ dragOptions);
+ } else {
+ dv = mDragController.startDrag(
+ drawable,
+ draggableView,
+ dragLayerX,
+ dragLayerY,
+ source,
+ dragObject,
+ dragVisualizeOffset,
+ dragRect,
+ scale * iconScale,
+ scale,
+ dragOptions);
}
- DragView dv = mDragController.startDrag(
- drawable,
- draggableView,
- dragLayerX,
- dragLayerY,
- source,
- dragObject,
- dragVisualizeOffset,
- dragRect,
- scale * iconScale,
- scale,
- dragOptions);
- dv.setIntrinsicIconScaleFactor(dragOptions.intrinsicIconScaleFactor);
return dv;
}
@@ -1901,6 +1866,8 @@
CellLayout parentCell = getParentCellLayoutForView(cell);
if (parentCell != null) {
parentCell.removeView(cell);
+ } else if (mDragInfo.cell instanceof LauncherAppWidgetHostView) {
+ d.dragView.detachContentView(/* reattachToPreviousParent= */ false);
} else if (FeatureFlags.IS_STUDIO_BUILD) {
throw new NullPointerException("mDragInfo.cell has null parent");
}
@@ -1939,6 +1906,9 @@
if (!returnToOriginalCellToPreventShuffling) {
onNoCellFound(dropTargetLayout);
}
+ if (mDragInfo.cell instanceof LauncherAppWidgetHostView) {
+ d.dragView.detachContentView(/* reattachToPreviousParent= */ true);
+ }
// If we can't find a drop location, we return the item to its original position
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
@@ -2096,9 +2066,6 @@
if (mDragOverlappingLayout != null) {
mDragOverlappingLayout.setIsDragOverlapping(true);
}
- // Invalidating the scrim will also force this CellLayout
- // to be invalidated so that it is highlighted if necessary.
- mLauncher.getDragLayer().getWorkspaceDragScrim().invalidate();
}
public CellLayout getCurrentDragOverlappingLayout() {
@@ -2637,10 +2604,6 @@
}
private Drawable createWidgetDrawable(ItemInfo widgetInfo, View layout) {
- if (layout instanceof LauncherAppWidgetHostView) {
- return new AppWidgetHostViewDrawable((LauncherAppWidgetHostView) layout);
- }
-
int[] unScaledSize = estimateItemSize(widgetInfo);
int visibility = layout.getVisibility();
layout.setVisibility(VISIBLE);
@@ -2721,10 +2684,11 @@
boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET ||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
- if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
+ if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external)
+ && finalView != null
+ && dragView.getContentView() != finalView) {
Drawable crossFadeDrawable = createWidgetDrawable(info, finalView);
- dragView.setCrossFadeDrawable(crossFadeDrawable);
- dragView.crossFade((int) (duration * 0.8f));
+ dragView.crossFadeContent(crossFadeDrawable, (int) (duration * 0.8f));
} else if (isWidget && external) {
scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]);
}
@@ -2972,20 +2936,30 @@
* Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
* animation.
*
+ * @param preferredItemId The id of the preferred item to match to if it exists.
* @param packageName The package name of the app to match.
* @param user The user of the app to match.
*/
- public View getFirstMatchForAppClose(String packageName, UserHandle user) {
- List<CellLayout> cellLayouts = new ArrayList<>(getPanelCount() + 1);
- cellLayouts.add(getHotseat());
- getVisiblePages().forEach(page -> cellLayouts.add((CellLayout) page));
-
- final Workspace.ItemOperator packageAndUser = (ItemInfo info, View view) -> info != null
- && info.getTargetComponent() != null
- && TextUtils.equals(info.getTargetComponent().getPackageName(), packageName)
- && info.user.equals(user);
+ public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user) {
+ final Workspace.ItemOperator preferredItem = (ItemInfo info, View view) ->
+ info != null && info.id == preferredItemId;
+ final Workspace.ItemOperator preferredItemInFolder = (info, view) -> {
+ if (info instanceof FolderInfo) {
+ FolderInfo folderInfo = (FolderInfo) info;
+ for (WorkspaceItemInfo shortcutInfo : folderInfo.contents) {
+ if (preferredItem.evaluate(shortcutInfo, view)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
final Workspace.ItemOperator packageAndUserAndApp = (ItemInfo info, View view) ->
- packageAndUser.evaluate(info, view) && info.itemType == ITEM_TYPE_APPLICATION;
+ info != null
+ && info.getTargetComponent() != null
+ && TextUtils.equals(info.getTargetComponent().getPackageName(), packageName)
+ && info.user.equals(user)
+ && info.itemType == ITEM_TYPE_APPLICATION;
final Workspace.ItemOperator packageAndUserAndAppInFolder = (info, view) -> {
if (info instanceof FolderInfo) {
FolderInfo folderInfo = (FolderInfo) info;
@@ -2998,13 +2972,18 @@
return false;
};
+ List<CellLayout> cellLayouts = new ArrayList<>(getPanelCount() + 1);
+ cellLayouts.add(getHotseat());
+ getVisiblePages().forEach(page -> cellLayouts.add((CellLayout) page));
+
// Order: App icons, app in folder. Items in hotseat get returned first.
if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
- return getFirstMatch(cellLayouts, packageAndUserAndApp, packageAndUserAndAppInFolder);
+ return getFirstMatch(cellLayouts, preferredItem, preferredItemInFolder,
+ packageAndUserAndApp, packageAndUserAndAppInFolder);
} else {
// Do not use Folder as a criteria, since it'll cause a crash when trying to draw
// FolderAdaptiveIcon as the background.
- return getFirstMatch(cellLayouts, packageAndUserAndApp);
+ return getFirstMatch(cellLayouts, preferredItem, packageAndUserAndApp);
}
}
@@ -3296,6 +3275,18 @@
}
}
+ /**
+ * Set the given view's pivot point to match the workspace's, so that it scales together. Since
+ * both this view and workspace can move, transform the point manually instead of using
+ * dragLayer.getDescendantCoordRelativeToSelf and related methods.
+ */
+ public void setPivotToScaleWithSelf(View sibling) {
+ sibling.setPivotY(getPivotY() + getTop()
+ - sibling.getTop() - sibling.getTranslationY());
+ sibling.setPivotX(getPivotX() + getLeft()
+ - sibling.getLeft() - sibling.getTranslationX());
+ }
+
@Override
public int getExpectedHeight() {
return getMeasuredHeight() <= 0 || !mIsLayoutValid
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index f4986f4..aa99d52 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -119,7 +119,7 @@
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
}
- setPivotToScaleWithWorkspace(hotseat);
+ mWorkspace.setPivotToScaleWithSelf(hotseat);
float hotseatScale = hotseatScaleAndTranslation.scale;
if (shouldSpring) {
PendingAnimation pa = (PendingAnimation) propertySetter;
@@ -156,30 +156,19 @@
}
}
- /**
- * Set the given view's pivot point to match the workspace's, so that it scales together. Since
- * both this view and workspace can move, transform the point manually instead of using
- * dragLayer.getDescendantCoordRelativeToSelf and related methods.
- */
- private void setPivotToScaleWithWorkspace(View sibling) {
- sibling.setPivotY(mWorkspace.getPivotY() + mWorkspace.getTop()
- - sibling.getTop() - sibling.getTranslationY());
- sibling.setPivotX(mWorkspace.getPivotX() + mWorkspace.getLeft()
- - sibling.getLeft() - sibling.getTranslationX());
- }
-
public void setScrim(PropertySetter propertySetter, LauncherState state,
StateAnimationConfig config) {
Scrim workspaceDragScrim = mLauncher.getDragLayer().getWorkspaceDragScrim();
propertySetter.setFloat(workspaceDragScrim, SCRIM_PROGRESS,
state.getWorkspaceBackgroundAlpha(mLauncher), LINEAR);
- SysUiScrim sysUiScrim = mLauncher.getDragLayer().getSysUiScrim();
+ SysUiScrim sysUiScrim = mLauncher.getRootView().getSysUiScrim();
propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
- propertySetter.setViewAlpha(mLauncher.getScrimView(),
- state.getWorkspaceScrimAlpha(mLauncher),
+
+ propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
+ state.getWorkspaceScrimColor(mLauncher),
config.getInterpolator(ANIM_WORKSPACE_SCRIM_FADE, LINEAR));
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 41865ce..40f7ab1 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -75,8 +75,9 @@
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener {
- private static final float FLING_VELOCITY_MULTIPLIER = 1000 * .2f;
- // Starts the springs after at least 55% of the animation has passed.
+ private static final float FLING_VELOCITY_MULTIPLIER = 1800f;
+
+ // Starts the springs after at least 25% of the animation has passed.
private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
protected final BaseDraggingActivity mLauncher;
@@ -610,7 +611,7 @@
public void onAnimationUpdate(ValueAnimator valueAnimator) {
if (shouldSpring
&& valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
- absorbSwipeUpVelocity(Math.abs(
+ absorbSwipeUpVelocity(-Math.abs(
Math.round(velocity * FLING_VELOCITY_MULTIPLIER)));
shouldSpring = false;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 66575eb..b1c764c 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -51,7 +51,7 @@
*/
public class AllAppsRecyclerView extends BaseRecyclerView {
private static final String TAG = "AllAppsContainerView";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private AlphabeticalAppsList mApps;
private final int mNumAppsPerRow;
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 0060b83..c61c0d6 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -197,7 +197,7 @@
/**
* Updates the total scroll range but does not update the UI.
*/
- void setScrollRangeDelta(float delta) {
+ public void setScrollRangeDelta(float delta) {
mScrollRangeDelta = delta;
mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta;
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 7a38937..11e831e 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -27,7 +27,6 @@
import com.android.launcher3.Utilities;
-
/**
* Common interpolators used in Launcher
*/
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 9068331..8057475 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -16,6 +16,7 @@
package com.android.launcher3.anim;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
import android.animation.Animator;
@@ -25,6 +26,7 @@
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.graphics.drawable.ColorDrawable;
import android.util.FloatProperty;
import android.util.IntProperty;
import android.view.View;
@@ -85,6 +87,17 @@
}
@Override
+ public void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+ if (view == null || (view.getBackground() instanceof ColorDrawable
+ && ((ColorDrawable) view.getBackground()).getColor() == color)) {
+ return;
+ }
+ ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
+ anim.setInterpolator(interpolator);
+ add(anim);
+ }
+
+ @Override
public <T> void setFloat(T target, FloatProperty<T> property, float value,
TimeInterpolator interpolator) {
if (property.get(target) == value) {
diff --git a/src/com/android/launcher3/anim/PropertySetter.java b/src/com/android/launcher3/anim/PropertySetter.java
index 2ce620b..729523f 100644
--- a/src/com/android/launcher3/anim/PropertySetter.java
+++ b/src/com/android/launcher3/anim/PropertySetter.java
@@ -41,6 +41,15 @@
}
/**
+ * Sets the background color of the provided view using the provided interpolator.
+ */
+ default void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+ if (view != null) {
+ view.setBackgroundColor(color);
+ }
+ }
+
+ /**
* Updates the float property of the target using the provided interpolator
*/
default <T> void setFloat(T target, FloatProperty<T> property, float value,
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 6331ef2..7d5ed60 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -168,7 +168,15 @@
public static final BooleanFlag ENABLE_SMARTSPACE_ENHANCED = new DeviceFlag(
"ENABLE_SMARTSPACE_ENHANCED", false,
"Replace Smartspace with the enhanced version. "
- + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
+ + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
+
+ public static final BooleanFlag ENABLE_SMARTSPACE_FEEDBACK = new DeviceFlag(
+ "ENABLE_SMARTSPACE_FEEDBACK", true,
+ "Adds a menu option to send feedback for Enhanced Smartspace.");
+
+ public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = new DeviceFlag(
+ "ENABLE_SMARTSPACE_DISMISS", false,
+ "Adds a menu option to dismiss the current Enhanced Smartspace card.");
public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS =
getDebugFlag(
@@ -191,10 +199,6 @@
"EXPANDED_SMARTSPACE", false, "Expands smartspace height to two rows. "
+ "Any apps occupying the first row will be removed from workspace.");
- public static final DeviceFlag ENABLE_FOUR_COLUMNS = new DeviceFlag(
- "ENABLE_FOUR_COLUMNS", false, "Uses 4 columns in launcher grid."
- + "Warning: This will permanently alter your home screen items and is not reversible.");
-
// TODO: b/172467144 Remove ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE feature flag.
public static final BooleanFlag ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE = new DeviceFlag(
"ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE", false, "Enables a "
@@ -225,6 +229,9 @@
public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
"Sends a notification whenever launcher encounters an uncaught exception.");
+ public static final BooleanFlag PROTOTYPE_APP_CLOSE = getDebugFlag(
+ "PROTOTYPE_APP_CLOSE", false, "Enables new app close");
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
@@ -234,12 +241,6 @@
}
}
- public static void removeFlag(DebugFlag flag) {
- synchronized (sDebugFlags) {
- sDebugFlags.remove(flag);
- }
- }
-
static List<DebugFlag> getDebugFlags() {
synchronized (sDebugFlags) {
return new ArrayList<>(sDebugFlags);
@@ -317,15 +318,6 @@
.getBoolean(key, defaultValue);
}
- /**
- * Resets value to default value.
- */
- public void reset(Context context) {
- mCurrentValue = defaultValue;
- context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
- .edit().putBoolean(key, defaultValue).apply();
- }
-
@Override
protected StringBuilder appendProps(StringBuilder src) {
return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue);
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index fc635a9..d5a04a6 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -59,6 +59,7 @@
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetCell;
@@ -147,20 +148,31 @@
public boolean onLongClick(View view) {
// Find the position of the preview relative to the touch location.
WidgetImageView img = mWidgetCell.getWidgetView();
+ NavigableAppWidgetHostView appWidgetHostView = mWidgetCell.getAppWidgetHostViewPreview();
// If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
// we abort the drag.
- if (img.getDrawable() == null) {
+ if (img.getDrawable() == null && appWidgetHostView == null) {
return false;
}
- Rect bounds = img.getBitmapBounds();
- bounds.offset(img.getLeft() - (int) mLastTouchPos.x, img.getTop() - (int) mLastTouchPos.y);
-
+ final Rect bounds;
// Start home and pass the draw request params
- PinItemDragListener listener = new PinItemDragListener(mRequest, bounds,
- img.getDrawable().getIntrinsicWidth(), img.getWidth());
-
+ final PinItemDragListener listener;
+ if (appWidgetHostView != null) {
+ bounds = new Rect();
+ appWidgetHostView.getSourceVisualDragBounds(bounds);
+ bounds.offset(appWidgetHostView.getLeft() - (int) mLastTouchPos.x,
+ appWidgetHostView.getTop() - (int) mLastTouchPos.y);
+ listener = new PinItemDragListener(mRequest, bounds,
+ appWidgetHostView.getMeasuredWidth(), appWidgetHostView.getMeasuredWidth());
+ } else {
+ bounds = img.getBitmapBounds();
+ bounds.offset(img.getLeft() - (int) mLastTouchPos.x,
+ img.getTop() - (int) mLastTouchPos.y);
+ listener = new PinItemDragListener(mRequest, bounds,
+ img.getDrawable().getIntrinsicWidth(), img.getWidth());
+ }
// Start a system drag and drop. We use a transparent bitmap as preview for system drag
// as the preview is handled internally by launcher.
@@ -214,7 +226,7 @@
// Cannot add widget
return false;
}
- mWidgetCell.setPreview(PinItemDragListener.getPreview(mRequest));
+ mWidgetCell.setRemoteViewsPreview(PinItemDragListener.getPreview(mRequest));
mAppWidgetManager = new WidgetManagerHelper(this);
mAppWidgetHost = new LauncherAppWidgetHost(this);
@@ -238,6 +250,7 @@
@Override
protected void onPostExecute(WidgetItem item) {
+ mWidgetCell.setPreviewSize(item.spanX, item.spanY);
mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
mWidgetCell.ensurePreview();
}
diff --git a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java b/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java
deleted file mode 100644
index 2135f5d..0000000
--- a/src/com/android/launcher3/dragndrop/AppWidgetHostViewDrawable.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2021 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.launcher3.dragndrop;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-
-import com.android.launcher3.widget.LauncherAppWidgetHostView;
-
-/**
- * A drawable which renders {@link LauncherAppWidgetHostView} to a canvas.
- *
- * TODO(b/183609936) Stop using that class and remove it.
- */
-public final class AppWidgetHostViewDrawable extends Drawable {
-
- private final LauncherAppWidgetHostView mAppWidgetHostView;
- private Paint mPaint = new Paint();
-
- public AppWidgetHostViewDrawable(LauncherAppWidgetHostView appWidgetHostView) {
- mAppWidgetHostView = appWidgetHostView;
- }
-
- @Override
- public void draw(Canvas canvas) {
- int saveCount = canvas.saveLayer(0, 0, getIntrinsicWidth(), getIntrinsicHeight(), mPaint);
- mAppWidgetHostView.draw(canvas);
- canvas.restoreToCount(saveCount);
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mAppWidgetHostView.getMeasuredWidth();
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mAppWidgetHostView.getMeasuredHeight();
- }
-
- @Override
- public int getOpacity() {
- // This is up to app widget provider. We don't know if the host view will cover anything
- // behind the drawable.
- return PixelFormat.UNKNOWN;
- }
-
- @Override
- public void setAlpha(int alpha) {
- mPaint.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mPaint.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
- mPaint.setColorFilter(colorFilter);
- }
-
- @Override
- public ColorFilter getColorFilter() {
- return mPaint.getColorFilter();
- }
-
- /** Returns the {@link LauncherAppWidgetHostView}. */
- public LauncherAppWidgetHostView getAppWidgetHostView() {
- return mAppWidgetHostView;
- }
-}
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 707fd06..981e3a6 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -34,7 +34,6 @@
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
import com.android.launcher3.widget.PendingItemDragHelper;
@@ -143,15 +142,13 @@
// the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
// dragView from being visible. Instead just skip the fade-in animation here.
mLauncher.getDragLayer().setAlpha(1);
-
- dragObject.dragView.setColor(
- mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
+ dragObject.dragView.setAlpha(.5f);
}
@Override
public void onPreDragEnd(DragObject dragObject, boolean dragStarted) {
if (dragStarted) {
- dragObject.dragView.setColor(0);
+ dragObject.dragView.setAlpha(1f);
}
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index b7a70cb..d7f6cdb 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -34,6 +34,8 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
@@ -125,20 +127,23 @@
/**
* Starts a drag.
- * When the drag is started, the UI automatically goes into spring loaded mode. On a successful
- * drop, it is the responsibility of the {@link DropTarget} to exit out of the spring loaded
- * mode. If the drop was cancelled for some reason, the UI will automatically exit out of this mode.
+ *
+ * <p>When the drag is started, the UI automatically goes into spring loaded mode. On a
+ * successful drop, it is the responsibility of the {@link DropTarget} to exit out of the spring
+ * loaded mode. If the drop was cancelled for some reason, the UI will automatically exit out of
+ * this mode.
*
* @param drawable The drawable to be displayed in the drag view. It will be re-scaled to the
- * enlarged size.
- * @param originalView The source view (ie. icon, widget etc.) that is being dragged
- * and which the DragView represents
+ * enlarged size.
+ * @param originalView The source view (ie. icon, widget etc.) that is being dragged and which
+ * the DragView represents
* @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
* @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
* @param source An object representing where the drag originated
* @param dragInfo The data associated with the object that is being dragged
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
- * Makes dragging feel more precise, e.g. you can clip out a transparent border
+ * Makes dragging feel more precise, e.g. you can clip out a transparent
+ * border
*/
public DragView startDrag(
Drawable drawable,
@@ -152,6 +157,61 @@
float initialDragViewScale,
float dragViewScaleOnDrop,
DragOptions options) {
+ return startDrag(drawable, /* view= */ null, originalView, dragLayerX, dragLayerY,
+ source, dragInfo, dragOffset, dragRegion, initialDragViewScale, dragViewScaleOnDrop,
+ options);
+ }
+
+ /**
+ * Starts a drag.
+ *
+ * <p>When the drag is started, the UI automatically goes into spring loaded mode. On a
+ * successful drop, it is the responsibility of the {@link DropTarget} to exit out of the spring
+ * loaded mode. If the drop was cancelled for some reason, the UI will automatically exit out of
+ * this mode.
+ *
+ * @param view The view to be displayed in the drag view. It will be re-scaled to the
+ * enlarged size.
+ * @param originalView The source view (ie. icon, widget etc.) that is being dragged and which
+ * the DragView represents
+ * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
+ * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
+ * @param source An object representing where the drag originated
+ * @param dragInfo The data associated with the object that is being dragged
+ * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
+ * Makes dragging feel more precise, e.g. you can clip out a transparent
+ * border
+ */
+ public DragView startDrag(
+ View view,
+ DraggableView originalView,
+ int dragLayerX,
+ int dragLayerY,
+ DragSource source,
+ ItemInfo dragInfo,
+ Point dragOffset,
+ Rect dragRegion,
+ float initialDragViewScale,
+ float dragViewScaleOnDrop,
+ DragOptions options) {
+ return startDrag(/* drawable= */ null, view, originalView, dragLayerX, dragLayerY,
+ source, dragInfo, dragOffset, dragRegion, initialDragViewScale, dragViewScaleOnDrop,
+ options);
+ }
+
+ private DragView startDrag(
+ @Nullable Drawable drawable,
+ @Nullable View view,
+ DraggableView originalView,
+ int dragLayerX,
+ int dragLayerY,
+ DragSource source,
+ ItemInfo dragInfo,
+ Point dragOffset,
+ Rect dragRegion,
+ float initialDragViewScale,
+ float dragViewScaleOnDrop,
+ DragOptions options) {
if (PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing("Launcher");
}
@@ -182,14 +242,25 @@
final Resources res = mLauncher.getResources();
final float scaleDps = mIsInPreDrag
? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
- final DragView dragView = mDragObject.dragView = new DragView(
- mLauncher,
- drawable,
- registrationX,
- registrationY,
- initialDragViewScale,
- dragViewScaleOnDrop,
- scaleDps);
+ final DragView dragView = mDragObject.dragView = drawable != null
+ ? new DragView(
+ mLauncher,
+ drawable,
+ registrationX,
+ registrationY,
+ initialDragViewScale,
+ dragViewScaleOnDrop,
+ scaleDps)
+ : new DragView(
+ mLauncher,
+ view,
+ view.getMeasuredWidth(),
+ view.getMeasuredHeight(),
+ registrationX,
+ registrationY,
+ initialDragViewScale,
+ dragViewScaleOnDrop,
+ scaleDps);
dragView.setItemInfo(dragInfo);
mDragObject.dragComplete = false;
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 274e033..c2f609c 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -41,13 +41,11 @@
import com.android.launcher3.CellLayout;
import com.android.launcher3.DropTargetBar;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherRootView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Workspace;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.graphics.Scrim;
-import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.BaseDragLayer;
@@ -84,8 +82,6 @@
// Related to adjacent page hints
private final ViewGroupFocusHelper mFocusIndicatorHelper;
private Scrim mWorkspaceDragScrim;
- private SysUiScrim mSysUiScrim;
- private LauncherRootView mRootView;
/**
* Used to create a new DragLayer from XML.
@@ -107,12 +103,6 @@
mDragController = dragController;
recreateControllers();
mWorkspaceDragScrim = new Scrim(this);
-
- // We delegate drawing of the workspace scrim to LauncherRootView (one level up), so as
- // to avoid artifacts when translating the entire drag layer in the -1 transition.
- mRootView = (LauncherRootView) getParent();
- mSysUiScrim = new SysUiScrim(mRootView);
- mRootView.setSysUiScrim(mSysUiScrim);
}
@Override
@@ -526,23 +516,7 @@
super.dispatchDraw(canvas);
}
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mSysUiScrim.setSize(w, h);
- }
-
- @Override
- public void setInsets(Rect insets) {
- super.setInsets(insets);
- mSysUiScrim.onInsetsChanged(insets, mAllowSysuiScrims);
- }
-
public Scrim getWorkspaceDragScrim() {
return mWorkspaceDragScrim;
}
-
- public SysUiScrim getSysUiScrim() {
- return mSysUiScrim;
- }
}
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 0f26ff4..68a8af2 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -16,19 +16,22 @@
package com.android.launcher3.dragndrop;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import android.animation.FloatArrayEvaluator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
@@ -39,7 +42,11 @@
import android.os.Handler;
import android.os.Looper;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -55,22 +62,22 @@
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statemanager.StateManager.StateListener;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.views.BaseDragLayer;
-import java.util.Arrays;
+/** A custom view for rendering an icon, folder, shortcut or widget during drag-n-drop. */
+public class DragView extends FrameLayout implements StateListener<LauncherState> {
-public class DragView extends View implements StateListener<LauncherState> {
- private static final ColorMatrix sTempMatrix1 = new ColorMatrix();
- private static final ColorMatrix sTempMatrix2 = new ColorMatrix();
-
- public static final int COLOR_CHANGE_DURATION = 120;
public static final int VIEW_ZOOM_DURATION = 150;
- private boolean mShouldDraw = true;
- private Drawable mDrawable;
- private Drawable mCrossFadeDrawable;
- @Thunk Paint mPaint;
+ private final View mContent;
+ // The following are only used for rendering mContent directly during drag-n-drop.
+ @Nullable private ViewGroup.LayoutParams mContentViewLayoutParams;
+ @Nullable private ViewGroup mContentViewParent;
+ private int mContentViewInParentViewIndex = -1;
+ private final int mWidth;
+ private final int mHeight;
+
private final int mBlurSizeOutline;
private final int mRegistrationX;
private final int mRegistrationY;
@@ -85,16 +92,8 @@
@Thunk final DragController mDragController;
final FirstFrameAnimatorHelper mFirstFrameAnimatorHelper;
private boolean mHasDrawn = false;
- @Thunk float mCrossFadeProgress = 0f;
- private boolean mAnimationCancelled = false;
- ValueAnimator mAnim;
- // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
- // size. This is ignored for non-icons.
- private float mIntrinsicIconScale = 1f;
-
- @Thunk float[] mCurrentFilter;
- private ValueAnimator mFilterAnimator;
+ final ValueAnimator mAnim;
private int mLastTouchX;
private int mLastTouchY;
@@ -106,7 +105,14 @@
private SpringFloatValue mTranslateX, mTranslateY;
private Path mScaledMaskPath;
private Drawable mBadge;
- private ColorMatrixColorFilter mBaseFilter;
+
+ public DragView(Launcher launcher, Drawable drawable, int registrationX,
+ int registrationY, final float initialScale, final float scaleOnDrop,
+ final float finalScaleDps) {
+ this(launcher, getViewFromDrawable(launcher, drawable),
+ drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
+ registrationX, registrationY, initialScale, scaleOnDrop, finalScaleDps);
+ }
/**
* Construct the drag view.
@@ -114,11 +120,16 @@
* The registration point is the point inside our view that the touch events should
* be centered upon.
* @param launcher The Launcher instance
- * @param drawable The view that we're dragging around. We scale it up when we draw it.
+ * @param content the view content that is attached to the drag view.
+ * @param width the width of the dragView
+ * @param height the height of the dragView
+ * @param initialScale The view that we're dragging around. We scale it up when we draw it.
* @param registrationX The x coordinate of the registration point.
* @param registrationY The y coordinate of the registration point.
+ * @param scaleOnDrop the scale used in the drop animation.
+ * @param finalScaleDps the scale used in the zoom out animation when the drag view is shown.
*/
- public DragView(Launcher launcher, Drawable drawable, int registrationX,
+ public DragView(Launcher launcher, View content, int width, int height, int registrationX,
int registrationY, final float initialScale, final float scaleOnDrop,
final float finalScaleDps) {
super(launcher);
@@ -127,8 +138,19 @@
mDragController = launcher.getDragController();
mFirstFrameAnimatorHelper = new FirstFrameAnimatorHelper(this);
- final float scale = (drawable.getIntrinsicWidth() + finalScaleDps)
- / drawable.getIntrinsicWidth();
+ mContent = content;
+ mWidth = width;
+ mHeight = height;
+ mContentViewLayoutParams = mContent.getLayoutParams();
+ if (mContent.getParent() instanceof ViewGroup) {
+ mContentViewParent = (ViewGroup) mContent.getParent();
+ mContentViewInParentViewIndex = mContentViewParent.indexOfChild(mContent);
+ mContentViewParent.removeView(mContent);
+ }
+
+ addView(content, new LayoutParams(width, height));
+
+ final float scale = (width + finalScaleDps) / width;
// Set the initial scale to avoid any jumps
setScaleX(initialScale);
@@ -146,9 +168,7 @@
}
});
- mDrawable = drawable;
- setDragRegion(new Rect(0, 0, drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight()));
+ setDragRegion(new Rect(0, 0, width, height));
// The point in our scaled bitmap that the touch events are located
mRegistrationX = registrationX;
@@ -158,12 +178,11 @@
mScaleOnDrop = scaleOnDrop;
// Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
- int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
- measure(ms, ms);
- mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
mBlurSizeOutline = getResources().getDimensionPixelSize(R.dimen.blur_size_medium_outline);
setElevation(getResources().getDimension(R.dimen.drag_elevation));
+ setWillNotDraw(false);
}
@Override
@@ -190,145 +209,105 @@
*/
@TargetApi(Build.VERSION_CODES.O)
public void setItemInfo(final ItemInfo info) {
- if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
- info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
- info.itemType != LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
+ if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ && info.itemType != LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
return;
}
// Load the adaptive icon on a background thread and add the view in ui thread.
- MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(new Runnable() {
- @Override
- public void run() {
- Object[] outObj = new Object[1];
- int w = mDrawable.getIntrinsicWidth();
- int h = mDrawable.getIntrinsicHeight();
- Drawable dr = Utilities.getFullDrawable(mLauncher, info, w, h, outObj);
+ MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
+ Object[] outObj = new Object[1];
+ int w = mWidth;
+ int h = mHeight;
+ Drawable dr = Utilities.getFullDrawable(mLauncher, info, w, h, outObj);
- if (dr instanceof AdaptiveIconDrawable) {
- int blurMargin = (int) mLauncher.getResources()
- .getDimension(R.dimen.blur_size_medium_outline) / 2;
+ if (dr instanceof AdaptiveIconDrawable) {
+ int blurMargin = (int) mLauncher.getResources()
+ .getDimension(R.dimen.blur_size_medium_outline) / 2;
- Rect bounds = new Rect(0, 0, w, h);
- bounds.inset(blurMargin, blurMargin);
- // Badge is applied after icon normalization so the bounds for badge should not
- // be scaled down due to icon normalization.
- Rect badgeBounds = new Rect(bounds);
- mBadge = getBadge(mLauncher, info, outObj[0]);
- mBadge.setBounds(badgeBounds);
+ Rect bounds = new Rect(0, 0, w, h);
+ bounds.inset(blurMargin, blurMargin);
+ // Badge is applied after icon normalization so the bounds for badge should not
+ // be scaled down due to icon normalization.
+ Rect badgeBounds = new Rect(bounds);
+ mBadge = getBadge(mLauncher, info, outObj[0]);
+ mBadge.setBounds(badgeBounds);
- // Do not draw the background in case of folder as its translucent
- mShouldDraw = !(dr instanceof FolderAdaptiveIcon);
+ // Do not draw the background in case of folder as its translucent
+ final boolean shouldDrawBackground = !(dr instanceof FolderAdaptiveIcon);
- try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) {
- Drawable nDr; // drawable to be normalized
- if (mShouldDraw) {
- nDr = dr;
- } else {
- // Since we just want the scale, avoid heavy drawing operations
- nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
- }
- Utilities.scaleRectAboutCenter(bounds,
- li.getNormalizer().getScale(nDr, null, null, null));
+ try (LauncherIcons li = LauncherIcons.obtain(mLauncher)) {
+ Drawable nDr; // drawable to be normalized
+ if (shouldDrawBackground) {
+ nDr = dr;
+ } else {
+ // Since we just want the scale, avoid heavy drawing operations
+ nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
-
- // Shrink very tiny bit so that the clip path is smaller than the original bitmap
- // that has anti aliased edges and shadows.
- Rect shrunkBounds = new Rect(bounds);
- Utilities.scaleRectAboutCenter(shrunkBounds, 0.98f);
- adaptiveIcon.setBounds(shrunkBounds);
- final Path mask = adaptiveIcon.getIconMask();
-
- mTranslateX = new SpringFloatValue(DragView.this,
- w * AdaptiveIconDrawable.getExtraInsetFraction());
- mTranslateY = new SpringFloatValue(DragView.this,
- h * AdaptiveIconDrawable.getExtraInsetFraction());
-
- bounds.inset(
- (int) (-bounds.width() * AdaptiveIconDrawable.getExtraInsetFraction()),
- (int) (-bounds.height() * AdaptiveIconDrawable.getExtraInsetFraction())
- );
- mBgSpringDrawable = adaptiveIcon.getBackground();
- if (mBgSpringDrawable == null) {
- mBgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
- }
- mBgSpringDrawable.setBounds(bounds);
- mFgSpringDrawable = adaptiveIcon.getForeground();
- if (mFgSpringDrawable == null) {
- mFgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
- }
- mFgSpringDrawable.setBounds(bounds);
-
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- // Assign the variable on the UI thread to avoid race conditions.
- mScaledMaskPath = mask;
-
- if (info.isDisabled()) {
- FastBitmapDrawable d = new FastBitmapDrawable((Bitmap) null);
- d.setIsDisabled(true);
- mBaseFilter = (ColorMatrixColorFilter) d.getColorFilter();
- }
- updateColorFilter();
- }
- });
+ Utilities.scaleRectAboutCenter(bounds,
+ li.getNormalizer().getScale(nDr, null, null, null));
}
- }});
+ AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
+
+ // Shrink very tiny bit so that the clip path is smaller than the original bitmap
+ // that has anti aliased edges and shadows.
+ Rect shrunkBounds = new Rect(bounds);
+ Utilities.scaleRectAboutCenter(shrunkBounds, 0.98f);
+ adaptiveIcon.setBounds(shrunkBounds);
+ final Path mask = adaptiveIcon.getIconMask();
+
+ mTranslateX = new SpringFloatValue(DragView.this,
+ w * AdaptiveIconDrawable.getExtraInsetFraction());
+ mTranslateY = new SpringFloatValue(DragView.this,
+ h * AdaptiveIconDrawable.getExtraInsetFraction());
+
+ bounds.inset(
+ (int) (-bounds.width() * AdaptiveIconDrawable.getExtraInsetFraction()),
+ (int) (-bounds.height() * AdaptiveIconDrawable.getExtraInsetFraction())
+ );
+ mBgSpringDrawable = adaptiveIcon.getBackground();
+ if (mBgSpringDrawable == null) {
+ mBgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
+ }
+ mBgSpringDrawable.setBounds(bounds);
+ mFgSpringDrawable = adaptiveIcon.getForeground();
+ if (mFgSpringDrawable == null) {
+ mFgSpringDrawable = new ColorDrawable(Color.TRANSPARENT);
+ }
+ mFgSpringDrawable.setBounds(bounds);
+
+ new Handler(Looper.getMainLooper()).post(() -> {
+ // Assign the variable on the UI thread to avoid race conditions.
+ mScaledMaskPath = mask;
+ // Avoid relayout as we do not care about children affecting layout
+ removeAllViewsInLayout();
+
+ if (info.isDisabled()) {
+ FastBitmapDrawable d = new FastBitmapDrawable((Bitmap) null);
+ d.setIsDisabled(true);
+ mBgSpringDrawable.setColorFilter(d.getColorFilter());
+ mFgSpringDrawable.setColorFilter(d.getColorFilter());
+ mBadge.setColorFilter(d.getColorFilter());
+ }
+ invalidate();
+ });
+ }
+ });
}
- @TargetApi(Build.VERSION_CODES.O)
- private void updateColorFilter() {
- if (mCurrentFilter == null) {
- mPaint.setColorFilter(null);
-
- if (mScaledMaskPath != null) {
- mBgSpringDrawable.setColorFilter(mBaseFilter);
- mFgSpringDrawable.setColorFilter(mBaseFilter);
- mBadge.setColorFilter(mBaseFilter);
- }
- } else {
- ColorMatrixColorFilter currentFilter = new ColorMatrixColorFilter(mCurrentFilter);
- mPaint.setColorFilter(currentFilter);
-
- if (mScaledMaskPath != null) {
- if (mBaseFilter != null) {
- mBaseFilter.getColorMatrix(sTempMatrix1);
- sTempMatrix2.set(mCurrentFilter);
- sTempMatrix1.postConcat(sTempMatrix2);
-
- currentFilter = new ColorMatrixColorFilter(sTempMatrix1);
- }
-
- mBgSpringDrawable.setColorFilter(currentFilter);
- mFgSpringDrawable.setColorFilter(currentFilter);
- mBadge.setColorFilter(currentFilter);
- }
+ // TODO(b/183609936): This is only for LauncherAppWidgetHostView that is rendered in a drawable.
+ // Once LauncherAppWidgetHostView is directly rendered in this view, removes this method.
+ @Override
+ public void invalidate() {
+ super.invalidate();
+ if (mContent instanceof ImageView) {
+ mContent.invalidate();
}
-
- invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
- }
-
- /** Sets the scale of the view over the normal workspace icon size. */
- public void setIntrinsicIconScaleFactor(float scale) {
- mIntrinsicIconScale = scale;
- }
-
- public float getIntrinsicIconScaleFactor() {
- return mIntrinsicIconScale;
- }
-
- public int getDragRegionLeft() {
- return mDragRegion.left;
- }
-
- public int getDragRegionTop() {
- return mDragRegion.top;
+ super.onMeasure(makeMeasureSpec(mWidth, EXACTLY), makeMeasureSpec(mHeight, EXACTLY));
}
public int getDragRegionWidth() {
@@ -356,40 +335,11 @@
}
@Override
- protected void onDraw(Canvas canvas) {
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+
+ // Draw after the content
mHasDrawn = true;
-
- if (mShouldDraw) {
- // Always draw the bitmap to mask anti aliasing due to clipPath
- boolean crossFade = mCrossFadeProgress > 0 && mCrossFadeDrawable != null;
- if (crossFade) {
- int alpha = crossFade ? (int) (255 * (1 - mCrossFadeProgress)) : 255;
- mPaint.setAlpha(alpha);
- }
- mDrawable.setColorFilter(mPaint.getColorFilter());
- mDrawable.setAlpha(mPaint.getAlpha());
- mDrawable.setBounds(
- new Rect(0, 0, mDrawable.getIntrinsicWidth(),
- mDrawable.getIntrinsicHeight()));
- mDrawable.draw(canvas);
- if (crossFade) {
- mPaint.setAlpha((int) (255 * mCrossFadeProgress));
- final int saveCount = canvas.save();
- float sX = ((float) mDrawable.getIntrinsicWidth())
- / mCrossFadeDrawable.getIntrinsicWidth();
- float sY = ((float) mDrawable.getIntrinsicHeight())
- / mCrossFadeDrawable.getIntrinsicHeight();
- canvas.scale(sX, sY);
- mCrossFadeDrawable.setColorFilter(mPaint.getColorFilter());
- mCrossFadeDrawable.setAlpha(mPaint.getAlpha());
- mDrawable.setBounds(
- new Rect(0, 0, mDrawable.getIntrinsicWidth(),
- mDrawable.getIntrinsicHeight()));
- mCrossFadeDrawable.draw(canvas);
- canvas.restoreToCount(saveCount);
- }
- }
-
if (mScaledMaskPath != null) {
int cnt = canvas.save();
canvas.clipPath(mScaledMaskPath);
@@ -401,74 +351,27 @@
}
}
- public void setCrossFadeDrawable(Drawable crossFadeDrawable) {
- mCrossFadeDrawable = crossFadeDrawable;
- }
-
- public void crossFade(int duration) {
- ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
- va.setDuration(duration);
- va.setInterpolator(Interpolators.DEACCEL_1_5);
- va.addUpdateListener(a -> {
- mCrossFadeProgress = a.getAnimatedFraction();
- invalidate();
- });
- va.start();
- }
-
- public void setColor(int color) {
- if (mPaint == null) {
- mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ public void crossFadeContent(Drawable crossFadeDrawable, int duration) {
+ if (mContent.getParent() == null) {
+ // If the content is already removed, ignore
+ return;
}
- if (color != 0) {
- ColorMatrix m1 = new ColorMatrix();
- m1.setSaturation(0);
+ View newContent = getViewFromDrawable(getContext(), crossFadeDrawable);
+ newContent.measure(makeMeasureSpec(mWidth, EXACTLY), makeMeasureSpec(mHeight, EXACTLY));
+ newContent.layout(0, 0, mWidth, mHeight);
+ addViewInLayout(newContent, 0, new LayoutParams(mWidth, mHeight));
- ColorMatrix m2 = new ColorMatrix();
- Themes.setColorScaleOnMatrix(color, m2);
- m1.postConcat(m2);
-
- animateFilterTo(m1.getArray());
- } else {
- if (mCurrentFilter == null) {
- updateColorFilter();
- } else {
- animateFilterTo(new ColorMatrix().getArray());
- }
- }
- }
-
- private void animateFilterTo(float[] targetFilter) {
- float[] oldFilter = mCurrentFilter == null ? new ColorMatrix().getArray() : mCurrentFilter;
- mCurrentFilter = Arrays.copyOf(oldFilter, oldFilter.length);
-
- if (mFilterAnimator != null) {
- mFilterAnimator.cancel();
- }
- mFilterAnimator = ValueAnimator.ofObject(new FloatArrayEvaluator(mCurrentFilter),
- oldFilter, targetFilter);
- mFilterAnimator.setDuration(COLOR_CHANGE_DURATION);
- mFilterAnimator.addUpdateListener(new AnimatorUpdateListener() {
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- updateColorFilter();
- }
- });
- mFilterAnimator.start();
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(ObjectAnimator.ofFloat(newContent, VIEW_ALPHA, 0, 1));
+ anim.play(ObjectAnimator.ofFloat(mContent, VIEW_ALPHA, 0));
+ anim.setDuration(duration).setInterpolator(Interpolators.DEACCEL_1_5);
+ anim.start();
}
public boolean hasDrawn() {
return mHasDrawn;
}
- @Override
- public void setAlpha(float alpha) {
- super.setAlpha(alpha);
- mPaint.setAlpha((int) (255 * alpha));
- invalidate();
- }
-
/**
* Create a window containing this view and show it.
*
@@ -479,22 +382,21 @@
mDragLayer.addView(this);
// Start the pick-up animation
- DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
- lp.width = mDrawable.getIntrinsicWidth();
- lp.height = mDrawable.getIntrinsicHeight();
+ BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(mWidth, mHeight);
lp.customPosition = true;
setLayoutParams(lp);
+
+ if (mContent != null) {
+ // At the drag start, the source view visibility is set to invisible.
+ mContent.setVisibility(VISIBLE);
+ }
+
move(touchX, touchY);
// Post the animation to skip other expensive work happening on the first frame
- post(new Runnable() {
- public void run() {
- mAnim.start();
- }
- });
+ post(mAnim::start);
}
public void cancelAnimation() {
- mAnimationCancelled = true;
if (mAnim != null && mAnim.isRunning()) {
mAnim.cancel();
}
@@ -547,6 +449,33 @@
setTranslationY(mLastTouchY - mRegistrationY + mAnimatedShiftY);
}
+
+ /**
+ * Detaches {@link #mContent}, if previously attached, from this view.
+ *
+ * <p>In the case of no change in the drop position, sets {@code reattachToPreviousParent} to
+ * {@code true} to attach the {@link #mContent} back to its previous parent.
+ */
+ public void detachContentView(boolean reattachToPreviousParent) {
+ if (mContent != null && mContentViewParent != null && mContentViewInParentViewIndex >= 0) {
+ removeView(mContent);
+ mContent.setLayoutParams(mContentViewLayoutParams);
+ if (reattachToPreviousParent) {
+ mContentViewParent.addView(mContent, mContentViewInParentViewIndex);
+ }
+ mContentViewParent = null;
+ mContentViewInParentViewIndex = -1;
+ }
+ }
+
+ /**
+ * Removes this view from the {@link DragLayer}.
+ *
+ * <p>If the drag content is a {@link #mContent}, this call doesn't reattach the
+ * {@link #mContent} back to its previous parent. To reattach to previous parent, the caller
+ * should call {@link #detachContentView} with {@code reattachToPreviousParent} sets to true
+ * before this call.
+ */
public void remove() {
if (getParent() != null) {
mDragLayer.removeView(DragView.this);
@@ -561,9 +490,23 @@
return mInitialScale;
}
- /** Returns the current {@link Drawable} that is rendered in this view. */
- public Drawable getDrawable() {
- return mDrawable;
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ /** Returns the current content view that is rendered in the drag view. */
+ public View getContentView() {
+ return mContent;
+ }
+
+ /**
+ * Returns the previous {@link ViewGroup} parent of the {@link #mContent} before the drag
+ * content is attached to this view.
+ */
+ @Nullable
+ public ViewGroup getContentViewParent() {
+ return mContentViewParent;
}
private static class SpringFloatValue {
@@ -583,9 +526,9 @@
};
// Following three values are fine tuned with motion ux designer
- private final static int STIFFNESS = 4000;
- private final static float DAMPENING_RATIO = 1f;
- private final static int PARALLAX_MAX_IN_DP = 8;
+ private static final int STIFFNESS = 4000;
+ private static final float DAMPENING_RATIO = 1f;
+ private static final int PARALLAX_MAX_IN_DP = 8;
private final View mView;
private final SpringAnimation mSpring;
@@ -607,4 +550,10 @@
mSpring.animateToFinalPosition(Utilities.boundToRange(value, -mDelta, mDelta));
}
}
+
+ private static View getViewFromDrawable(Context context, Drawable drawable) {
+ ImageView iv = new ImageView(context);
+ iv.setImageDrawable(drawable);
+ return iv;
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index d166e27..9c1b24d 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -48,7 +48,7 @@
public class FolderNameProvider implements ResourceBasedOverride {
private static final String TAG = "FolderNameProvider";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
/**
* IME usually has up to 3 suggest slots. In total, there are 4 suggest slots as the folder
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index c1f4643..a4e8be6 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -42,7 +42,6 @@
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -433,8 +432,7 @@
int scroll = getScrollForPage(getNextPage()) + hint;
int delta = scroll - getScrollX();
if (delta != 0) {
- mScroller.setInterpolator(Interpolators.DEACCEL);
- mScroller.startScroll(getScrollX(), delta, Folder.SCROLL_HINT_DURATION);
+ mScroller.startScroll(getScrollX(), 0, delta, 0, Folder.SCROLL_HINT_DURATION);
invalidate();
}
}
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 767fffe..5ddf84f 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -50,6 +50,8 @@
*/
public class PreviewBackground extends CellLayout.DelegatedCellDrawing {
+ private static final boolean DRAW_SHADOW = false;
+
private static final int CONSUMPTION_ANIMATION_DURATION = 100;
private final PorterDuffXfermode mShadowPorterDuffXfermode
@@ -163,13 +165,15 @@
// Stroke width is 1dp
mStrokeWidth = context.getResources().getDisplayMetrics().density;
- float radius = getScaledRadius();
- float shadowRadius = radius + mStrokeWidth;
- int shadowColor = Color.argb(SHADOW_OPACITY, 0, 0, 0);
- mShadowShader = new RadialGradient(0, 0, 1,
- new int[] {shadowColor, Color.TRANSPARENT},
- new float[] {radius / shadowRadius, 1},
- Shader.TileMode.CLAMP);
+ if (DRAW_SHADOW) {
+ float radius = getScaledRadius();
+ float shadowRadius = radius + mStrokeWidth;
+ int shadowColor = Color.argb(SHADOW_OPACITY, 0, 0, 0);
+ mShadowShader = new RadialGradient(0, 0, 1,
+ new int[]{shadowColor, Color.TRANSPARENT},
+ new float[]{radius / shadowRadius, 1},
+ Shader.TileMode.CLAMP);
+ }
invalidate();
}
@@ -239,6 +243,9 @@
}
public void drawShadow(Canvas canvas) {
+ if (!DRAW_SHADOW) {
+ return;
+ }
if (mShadowShader == null) {
return;
}
@@ -277,6 +284,9 @@
}
public void fadeInBackgroundShadow() {
+ if (!DRAW_SHADOW) {
+ return;
+ }
if (mShadowAnimator != null) {
mShadowAnimator.cancel();
}
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index 0e61b98..a549750 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -29,11 +29,12 @@
import android.graphics.drawable.Drawable;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -95,7 +96,7 @@
*/
public Drawable createDrawable() {
if (mView instanceof LauncherAppWidgetHostView) {
- return new AppWidgetHostViewDrawable((LauncherAppWidgetHostView) mView);
+ return null;
}
int width = 0;
@@ -116,6 +117,18 @@
height + blurSizeOutline, (c) -> drawDragView(c, scale)));
}
+ /**
+ * Returns the content view if the content should be rendered directly in
+ * {@link com.android.launcher3.dragndrop.DragView}. Otherwise, returns null.
+ */
+ @Nullable
+ public View getContentView() {
+ if (mView instanceof LauncherAppWidgetHostView) {
+ return mView;
+ }
+ return null;
+ }
+
public final void generateDragOutline(Bitmap preview) {
if (FeatureFlags.IS_STUDIO_BUILD && mOutlineGeneratorCallback != null) {
throw new RuntimeException("Drag outline generated twice");
@@ -152,6 +165,22 @@
return scale;
}
+ /** Returns the scale and position of a given view for drag-n-drop. */
+ public float getScaleAndPosition(View view, int[] outPos) {
+ float scale = Launcher.getLauncher(mView.getContext())
+ .getDragLayer().getLocationInDragLayer(mView, outPos);
+ if (mView instanceof LauncherAppWidgetHostView) {
+ // App widgets are technically scaled, but are drawn at their expected size -- so the
+ // app widget scale should not affect the scale of the preview.
+ scale /= ((LauncherAppWidgetHostView) mView).getScaleToFit();
+ }
+
+ outPos[0] = Math.round(outPos[0]
+ - (view.getWidth() - scale * mView.getWidth() * mView.getScaleX()) / 2);
+ outPos[1] = Math.round(outPos[1] - (1 - scale) * view.getHeight() / 2 - previewPadding / 2);
+ return scale;
+ }
+
protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) {
return preview.copy(Bitmap.Config.ALPHA_8, true);
}
diff --git a/src/com/android/launcher3/graphics/IconShape.java b/src/com/android/launcher3/graphics/IconShape.java
index b208a40..2da679c 100644
--- a/src/com/android/launcher3/graphics/IconShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -37,20 +37,14 @@
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.util.TypedValue;
import android.util.Xml;
import android.view.View;
import android.view.ViewOutlineProvider;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.R;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
-import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ClipPathView;
import org.xmlpull.v1.XmlPullParser;
@@ -66,30 +60,16 @@
public abstract class IconShape {
private static IconShape sInstance = new Circle();
- private static Path sShapePath;
private static float sNormalizationScale = ICON_VISIBLE_AREA_FACTOR;
- public static final int DEFAULT_PATH_SIZE = 100;
-
public static IconShape getShape() {
return sInstance;
}
- public static Path getShapePath() {
- if (sShapePath == null) {
- Path p = new Path();
- getShape().addToPath(p, 0, 0, DEFAULT_PATH_SIZE * 0.5f);
- sShapePath = p;
- }
- return sShapePath;
- }
-
public static float getNormalizationScale() {
return sNormalizationScale;
}
- private SparseArray<TypedValue> mAttrs;
-
public boolean enableShapeDetection(){
return false;
};
@@ -102,11 +82,6 @@
public abstract <T extends View & ClipPathView> Animator createRevealAnimator(T target,
Rect startRect, Rect endRect, float endRadius, boolean isReversed);
- @Nullable
- public TypedValue getAttrValue(int attr) {
- return mAttrs == null ? null : mAttrs.get(attr);
- }
-
/**
* Abstract shape where the reveal animation is a derivative of a round rect animation
*/
@@ -410,7 +385,6 @@
final int depth = parser.getDepth();
int[] radiusAttr = new int[] {R.attr.folderIconRadius};
- IntArray keysToIgnore = new IntArray(0);
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
@@ -421,7 +395,6 @@
IconShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
a.recycle();
- shape.mAttrs = Themes.createValueMap(context, attrs, keysToIgnore);
result.add(shape);
}
}
@@ -467,8 +440,6 @@
}
// Initialize shape properties
- drawable.setBounds(0, 0, DEFAULT_PATH_SIZE, DEFAULT_PATH_SIZE);
- sShapePath = new Path(drawable.getIconMask());
sNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
}
}
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index ac0ec5f..13ae866 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,9 +17,6 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.graphics.IconShape.DEFAULT_PATH_SIZE;
-import static com.android.launcher3.graphics.IconShape.getShapePath;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -39,6 +36,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.util.Themes;
@@ -62,6 +60,7 @@
}
};
+ private static final int DEFAULT_PATH_SIZE = 100;
private static final float PROGRESS_WIDTH = 7;
private static final float PROGRESS_GAP = 2;
private static final int MAX_PAINT_ALPHA = 255;
@@ -132,7 +131,7 @@
boolean isDarkMode) {
super(info.bitmap);
mItem = info;
- mShapePath = getShapePath();
+ mShapePath = GraphicsUtils.getShapePath(DEFAULT_PATH_SIZE);
mScaledTrackPath = new Path();
mScaledProgressPath = new Path();
diff --git a/src/com/android/launcher3/graphics/Scrim.java b/src/com/android/launcher3/graphics/Scrim.java
index a151cba..a77e058 100644
--- a/src/com/android/launcher3/graphics/Scrim.java
+++ b/src/com/android/launcher3/graphics/Scrim.java
@@ -22,14 +22,12 @@
import android.util.FloatProperty;
import android.view.View;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
+import com.android.launcher3.R;
/**
* Contains general scrim properties such as wallpaper-extracted color that subclasses can use.
*/
-public class Scrim implements View.OnAttachStateChangeListener,
- WallpaperColorInfo.OnChangeListener {
+public class Scrim {
public static final FloatProperty<Scrim> SCRIM_PROGRESS =
new FloatProperty<Scrim>("scrimProgress") {
@@ -44,8 +42,6 @@
}
};
- protected final Launcher mLauncher;
- protected final WallpaperColorInfo mWallpaperColorInfo;
protected final View mRoot;
protected float mScrimProgress;
@@ -54,48 +50,18 @@
public Scrim(View view) {
mRoot = view;
- mLauncher = Launcher.getLauncher(view.getContext());
- mWallpaperColorInfo = WallpaperColorInfo.INSTANCE.get(mLauncher);
-
- view.addOnAttachStateChangeListener(this);
+ mScrimColor = mRoot.getContext().getColor(R.color.wallpaper_popup_scrim);
}
public void draw(Canvas canvas) {
- canvas.drawColor(setColorAlphaBound(mScrimColor, getScrimAlpha()));
- }
-
- protected int getScrimAlpha() {
- return mScrimAlpha;
+ canvas.drawColor(setColorAlphaBound(mScrimColor, mScrimAlpha));
}
private void setScrimProgress(float progress) {
if (mScrimProgress != progress) {
mScrimProgress = progress;
mScrimAlpha = Math.round(255 * mScrimProgress);
- invalidate();
+ mRoot.invalidate();
}
}
-
- @Override
- public void onViewAttachedToWindow(View view) {
- mWallpaperColorInfo.addOnChangeListener(this);
- onExtractedColorsChanged(mWallpaperColorInfo);
- }
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- mWallpaperColorInfo.removeOnChangeListener(this);
- }
-
- @Override
- public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
- mScrimColor = wallpaperColorInfo.getMainColor();
- if (mScrimAlpha > 0) {
- invalidate();
- }
- }
-
- public void invalidate() {
- mRoot.invalidate();
- }
}
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index d9c648b..c09dac8 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -41,18 +41,16 @@
import android.view.View;
import android.view.WindowInsets;
-import androidx.core.graphics.ColorUtils;
-
+import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.Themes;
/**
* View scrim which draws behind hotseat and workspace
*/
-public class SysUiScrim extends Scrim {
+public class SysUiScrim implements View.OnAttachStateChangeListener {
public static final FloatProperty<SysUiScrim> SYSUI_PROGRESS =
new FloatProperty<SysUiScrim>("sysUiProgress") {
@@ -83,7 +81,6 @@
/**
* Receiver used to get a signal that the user unlocked their device.
- * @see KEYGUARD_ANIMATION For proper signal.
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -99,7 +96,6 @@
}
};
- private static final int DARK_SCRIM_COLOR = 0x55000000;
private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
private static final int ALPHA_MASK_HEIGHT_DP = 500;
private static final int ALPHA_MASK_BITMAP_DP = 200;
@@ -112,6 +108,8 @@
private final Bitmap mBottomMask;
private final int mMaskHeight;
+ private final View mRoot;
+ private final BaseDraggingActivity mActivity;
private final Drawable mTopScrim;
private float mSysUiProgress = 1;
@@ -121,14 +119,15 @@
private float mSysUiAnimMultiplier = 1;
public SysUiScrim(View view) {
- super(view);
+ mRoot = view;
+ mActivity = BaseDraggingActivity.fromContext(view.getContext());
mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
view.getResources().getDisplayMetrics());
mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
mBottomMask = mTopScrim == null ? null : createDitheredAlphaMask();
mHideSysUiScrim = mTopScrim == null;
- onExtractedColorsChanged(mWallpaperColorInfo);
+ view.addOnAttachStateChangeListener(this);
}
/**
@@ -147,7 +146,7 @@
ObjectAnimator oa = createSysuiMultiplierAnim(1);
oa.setDuration(600);
- oa.setStartDelay(mLauncher.getWindow().getTransitionBackgroundFadeDuration());
+ oa.setStartDelay(mActivity.getWindow().getTransitionBackgroundFadeDuration());
oa.start();
mAnimateScrimOnNextDraw = false;
}
@@ -173,20 +172,17 @@
/**
* Determines whether to draw the top and/or bottom scrim based on new insets.
*/
- public void onInsetsChanged(Rect insets, boolean allowSysuiScrims) {
- mDrawTopScrim = allowSysuiScrims
- && mTopScrim != null
- && insets.top > 0;
- mDrawBottomScrim = allowSysuiScrims
- && mBottomMask != null
- && !mLauncher.getDeviceProfile().isVerticalBarLayout()
+ public void onInsetsChanged(Rect insets) {
+ mDrawTopScrim = mTopScrim != null && insets.top > 0;
+ mDrawBottomScrim = mBottomMask != null
+ && !mActivity.getDeviceProfile().isVerticalBarLayout()
&& hasBottomNavButtons();
}
private boolean hasBottomNavButtons() {
- if (Utilities.ATLEAST_Q && mLauncher.getRootView() != null
- && mLauncher.getRootView().getRootWindowInsets() != null) {
- WindowInsets windowInsets = mLauncher.getRootView().getRootWindowInsets();
+ if (Utilities.ATLEAST_Q && mActivity.getRootView() != null
+ && mActivity.getRootView().getRootWindowInsets() != null) {
+ WindowInsets windowInsets = mActivity.getRootView().getRootWindowInsets();
return windowInsets.getTappableElementInsets().bottom > 0;
}
return true;
@@ -194,8 +190,6 @@
@Override
public void onViewAttachedToWindow(View view) {
- super.onViewAttachedToWindow(view);
-
if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
@@ -205,22 +199,11 @@
@Override
public void onViewDetachedFromWindow(View view) {
- super.onViewDetachedFromWindow(view);
if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
mRoot.getContext().unregisterReceiver(mReceiver);
}
}
- @Override
- public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
- // for super light wallpaper it needs to be darken for contrast to workspace
- // for dark wallpapers the text is white so darkening works as well
- mBottomMaskPaint.setColor(ColorUtils.compositeColors(DARK_SCRIM_COLOR,
- wallpaperColorInfo.getMainColor()));
- reapplySysUiAlpha();
- super.onExtractedColorsChanged(wallpaperColorInfo);
- }
-
/**
* Set the width and height of the view being scrimmed
* @param w
@@ -243,7 +226,7 @@
private void reapplySysUiAlpha() {
reapplySysUiAlphaNoInvalidate();
if (!mHideSysUiScrim) {
- invalidate();
+ mRoot.invalidate();
}
}
@@ -256,7 +239,7 @@
}
private Bitmap createDitheredAlphaMask() {
- DisplayMetrics dm = mLauncher.getResources().getDisplayMetrics();
+ DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
int width = ResourceUtils.pxFromDp(ALPHA_MASK_WIDTH_DP, dm);
int gradientHeight = ResourceUtils.pxFromDp(ALPHA_MASK_HEIGHT_DP, dm);
Bitmap dst = Bitmap.createBitmap(width, mMaskHeight, Bitmap.Config.ALPHA_8);
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index fd51ba8..29287d9 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -32,11 +32,13 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
@@ -126,6 +128,12 @@
}
SessionInfo sessionInfo = packageInstaller.getActiveSessionInfo(item.user,
packageName);
+
+ if (!packageInstaller.verifySessionInfo(sessionInfo)) {
+ Log.d(LOG, "Item info failed session info verification: "
+ + workspaceInfo);
+ }
+
List<LauncherActivityInfo> activities = launcherApps
.getActivityList(packageName, item.user);
boolean hasActivity = activities != null && !activities.isEmpty();
@@ -171,7 +179,15 @@
// Save the WorkspaceItemInfo for binding in the workspace
addedItemsFinal.add(itemInfo);
- Log.i(LOG, "Adding item info to workspace: " + itemInfo);
+ // log bitmap and label
+ Log.d(LOG, "Adding item info to workspace: " + itemInfo);
+ if (itemInfo instanceof ItemInfoWithIcon) {
+ ItemInfoWithIcon infoWithIcon = (ItemInfoWithIcon) itemInfo;
+
+ Log.d(LOG, "Item info icon base 64 string: "
+ + infoWithIcon.bitmap.icon == null
+ ? "null" : IOUtils.toBase64String(infoWithIcon.bitmap.icon));
+ }
}
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 6a75e62..7b3e509 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -53,7 +53,7 @@
public class GridSizeMigrationTask {
private static final String TAG = "GridSizeMigrationTask";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
// These are carefully selected weights for various item types (Math.random?), to allow for
// the least absurd migration experience.
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index cee9304..8a1d73e 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -67,7 +67,7 @@
public class GridSizeMigrationTaskV2 {
private static final String TAG = "GridSizeMigrationTaskV2";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private final Context mContext;
private final SQLiteDatabase mDb;
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 836d804..22cb46b 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -130,6 +130,7 @@
// Add the items and clear queue
if (!installQueue.isEmpty()) {
+ // add log
launcher.getModel().addAndBindAddedWorkspaceItems(installQueue);
}
mItems.clear();
@@ -184,14 +185,20 @@
}
private void queuePendingShortcutInfo(PendingInstallShortcutInfo info) {
+ final Exception stackTrace = new Exception();
+
// Queue the item up for adding if launcher has not loaded properly yet
MODEL_EXECUTOR.post(() -> {
Pair<ItemInfo, Object> itemInfo = info.getItemInfo(mContext);
if (itemInfo == null) {
- Log.i(LOG, "Adding PendingInstallShortcutInfo with no attached info to queue.");
+ Log.d(LOG,
+ "Adding PendingInstallShortcutInfo with no attached info to queue.",
+ stackTrace);
} else {
- Log.i(LOG, "Adding PendingInstallShortcutInfo to queue. Attached info: "
- + itemInfo.first);
+ Log.d(LOG,
+ "Adding PendingInstallShortcutInfo to queue. Attached info: "
+ + itemInfo.first,
+ stackTrace);
}
addToQueue(info);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index f6c7c06..79396b1 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -109,6 +109,8 @@
public class LoaderTask implements Runnable {
private static final String TAG = "LoaderTask";
+ private static final boolean DEBUG = true;
+
protected final LauncherAppState mApp;
private final AllAppsList mBgAllAppsList;
protected final BgDataModel mBgDataModel;
@@ -190,7 +192,7 @@
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts);
- logger.addSplit("loadWorkspace");
+ logASplit(logger, "loadWorkspace");
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
// sanitizeData should not be invoked if the workspace is loaded from a db different
@@ -199,30 +201,30 @@
if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
verifyNotStopped();
sanitizeData();
- logger.addSplit("sanitizeData");
+ logASplit(logger, "sanitizeData");
}
verifyNotStopped();
mResults.bindWorkspace();
- logger.addSplit("bindWorkspace");
+ logASplit(logger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
- logger.addSplit("sendFirstScreenActiveInstallsBroadcast");
+ logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
// Take a break
waitForIdle();
- logger.addSplit("step 1 complete");
+ logASplit(logger, "step 1 complete");
verifyNotStopped();
// second step
List<LauncherActivityInfo> allActivityList = loadAllApps();
- logger.addSplit("loadAllApps");
+ logASplit(logger, "loadAllApps");
verifyNotStopped();
mResults.bindAllApps();
- logger.addSplit("bindAllApps");
+ logASplit(logger, "bindAllApps");
verifyNotStopped();
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
@@ -230,54 +232,54 @@
updateHandler.updateIcons(allActivityList,
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
mApp.getModel()::onPackageIconsUpdated);
- logger.addSplit("update icon cache");
+ logASplit(logger, "update icon cache");
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
verifyNotStopped();
- logger.addSplit("save shortcuts in icon cache");
+ logASplit(logger, "save shortcuts in icon cache");
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
mApp.getModel()::onPackageIconsUpdated);
}
// Take a break
waitForIdle();
- logger.addSplit("step 2 complete");
+ logASplit(logger, "step 2 complete");
verifyNotStopped();
// third step
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
- logger.addSplit("loadDeepShortcuts");
+ logASplit(logger, "loadDeepShortcuts");
verifyNotStopped();
mResults.bindDeepShortcuts();
- logger.addSplit("bindDeepShortcuts");
+ logASplit(logger, "bindDeepShortcuts");
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
verifyNotStopped();
- logger.addSplit("save deep shortcuts in icon cache");
+ logASplit(logger, "save deep shortcuts in icon cache");
updateHandler.updateIcons(allDeepShortcuts,
new ShortcutCachingLogic(), (pkgs, user) -> { });
}
// Take a break
waitForIdle();
- logger.addSplit("step 3 complete");
+ logASplit(logger, "step 3 complete");
verifyNotStopped();
// fourth step
List<ComponentWithLabelAndIcon> allWidgetsList =
mBgDataModel.widgetsModel.update(mApp, null);
- logger.addSplit("load widgets");
+ logASplit(logger, "load widgets");
verifyNotStopped();
mResults.bindWidgets();
- logger.addSplit("bindWidgets");
+ logASplit(logger, "bindWidgets");
verifyNotStopped();
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
- logger.addSplit("save widgets in icon cache");
+ logASplit(logger, "save widgets in icon cache");
// fifth step
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
@@ -286,13 +288,13 @@
verifyNotStopped();
updateHandler.finish();
- logger.addSplit("finish icon update");
+ logASplit(logger, "finish icon update");
mModelDelegate.modelLoadComplete();
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
- logger.addSplit("Cancelled");
+ logASplit(logger, "Cancelled");
} finally {
logger.dumpToLog();
}
@@ -977,4 +979,11 @@
return (provider != null) && (provider.provider != null)
&& (provider.provider.getPackageName() != null);
}
+
+ private static void logASplit(final TimingLogger logger, final String label) {
+ logger.addSplit(label);
+ if (DEBUG) {
+ Log.d(TAG, label);
+ }
+ }
}
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index e54f1e7..e388965 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -66,7 +66,7 @@
*/
public class ItemInfo {
- public static final boolean DEBUG = true;
+ public static final boolean DEBUG = false;
public static final int NO_ID = -1;
/**
@@ -366,7 +366,7 @@
return itemBuilder.build();
}
- LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() {
+ protected LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() {
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(user != Process.myUserHandle());
return itemBuilder;
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index a7cd10d..f73d782 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -24,7 +24,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
+import com.android.launcher3.util.Themes;
/**
* A PageIndicator that briefly shows a fraction of a line when moving between pages
@@ -123,7 +123,7 @@
mLauncher = Launcher.getLauncher(context);
mLineHeight = res.getDimensionPixelSize(R.dimen.workspace_page_indicator_line_height);
- boolean darkText = WallpaperColorInfo.INSTANCE.get(context).supportsDarkText();
+ boolean darkText = Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText);
mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
mLinePaint.setColor(darkText ? Color.BLACK : Color.WHITE);
}
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 72f1c58..88db430 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -25,6 +25,7 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
@@ -40,6 +41,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.ItemInstallQueue;
+import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject;
@@ -215,14 +217,8 @@
void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
&& SessionCommitReceiver.isEnabled(mAppContext)
- && verify(sessionInfo) != null
- && sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
- && sessionInfo.getAppIcon() != null
- && !TextUtils.isEmpty(sessionInfo.getAppLabel())
- && !promiseIconAddedForId(sessionInfo.getSessionId())
- && !new PackageManagerHelper(mAppContext).isAppInstalled(
- sessionInfo.getAppPackageName(), getUserHandle(sessionInfo))) {
- Log.i(LOG, "Adding package name to install queue: "
+ && verifySessionInfo(sessionInfo)) {
+ Log.d(LOG, "Adding package name to install queue: "
+ sessionInfo.getAppPackageName());
ItemInstallQueue.INSTANCE.get(mAppContext)
@@ -233,6 +229,37 @@
}
}
+ public boolean verifySessionInfo(PackageInstaller.SessionInfo sessionInfo) {
+ boolean validSessionInfo = verify(sessionInfo) != null
+ && sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
+ && sessionInfo.getAppIcon() != null
+ && !TextUtils.isEmpty(sessionInfo.getAppLabel())
+ && !promiseIconAddedForId(sessionInfo.getSessionId())
+ && !new PackageManagerHelper(mAppContext).isAppInstalled(
+ sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
+
+ if (sessionInfo != null) {
+ Bitmap appIcon = sessionInfo.getAppIcon();
+
+ Log.d(LOG, String.format(
+ "Verifying session info. Valid: %b, Session verified: %b, Install reason valid:"
+ + " %b, App icon: %s, App label: %s, Promise icon added: %b, "
+ + "App installed: %b.",
+ validSessionInfo,
+ verify(sessionInfo) != null,
+ sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER,
+ appIcon == null ? "null" : IOUtils.toBase64String(appIcon),
+ sessionInfo.getAppLabel(),
+ promiseIconAddedForId(sessionInfo.getSessionId()),
+ new PackageManagerHelper(mAppContext).isAppInstalled(
+ sessionInfo.getAppPackageName(), getUserHandle(sessionInfo))));
+ } else {
+ Log.d(LOG, "Verifying session info failed: session info null.");
+ }
+
+ return validSessionInfo;
+ }
+
public InstallSessionTracker registerInstallTracker(InstallSessionTracker.Callback callback) {
InstallSessionTracker tracker = new InstallSessionTracker(this, callback);
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 3736538..c19dfe9 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -16,6 +16,7 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
@@ -48,12 +49,14 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
+import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
@@ -65,7 +68,8 @@
*
* @param <T> The activity on with the popup shows
*/
-public abstract class ArrowPopup<T extends BaseDraggingActivity> extends AbstractFloatingView {
+public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
+ extends AbstractFloatingView {
// +1 for system shortcut view
private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
@@ -139,14 +143,21 @@
mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius,
smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius});
- int primaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
- int secondaryColor = Themes.getAttrColor(context, R.attr.popupColorSecondary);
- ArgbEvaluator argb = new ArgbEvaluator();
- mColors = new int[MAX_NUM_CHILDREN];
- // Interpolate between the two colors, exclusive.
- float step = 1f / (MAX_NUM_CHILDREN + 1);
- for (int i = 0; i < mColors.length; ++i) {
- mColors[i] = (int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
+ boolean isAboveAnotherSurface = getTopOpenViewWithType(mLauncher, TYPE_FOLDER) != null
+ || mLauncher.getStateManager().getState() == LauncherState.ALL_APPS;
+ if (isAboveAnotherSurface) {
+ mColors = new int[] { Themes.getAttrColor(context, R.attr.popupColorNeutral) };
+ } else {
+ int primaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
+ int secondaryColor = Themes.getAttrColor(context, R.attr.popupColorSecondary);
+ ArgbEvaluator argb = new ArgbEvaluator();
+ mColors = new int[MAX_NUM_CHILDREN];
+ // Interpolate between the two colors, exclusive.
+ float step = 1f / (MAX_NUM_CHILDREN + 1);
+ for (int i = 0; i < mColors.length; ++i) {
+ mColors[i] =
+ (int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
+ }
}
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index c282ae8..1659e6d 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -46,6 +46,7 @@
import com.android.launcher3.DropTarget;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
@@ -60,10 +61,10 @@
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationItemView;
import com.android.launcher3.notification.NotificationKeyData;
-import com.android.launcher3.notification.NotificationMainView;
import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
@@ -81,8 +82,8 @@
*
* @param <T> The activity on with the popup shows
*/
-public class PopupContainerWithArrow<T extends BaseDraggingActivity> extends ArrowPopup<T>
- implements DragSource, DragController.DragListener {
+public class PopupContainerWithArrow<T extends StatefulActivity<LauncherState>>
+ extends ArrowPopup<T> implements DragSource, DragController.DragListener {
private final List<DeepShortcutView> mShortcuts = new ArrayList<>();
private final PointF mInterceptTouchDown = new PointF();
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
index e8695c9..217453f 100644
--- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
+++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
@@ -269,6 +269,20 @@
}
PreferenceCategory sandboxCategory = newCategory("Gesture Navigation Sandbox");
sandboxCategory.setSummary("Learn and practice navigation gestures");
+ Preference launchOnboardingTutorialPreference = new Preference(context);
+ launchOnboardingTutorialPreference.setKey("launchOnboardingTutorial");
+ launchOnboardingTutorialPreference.setTitle("Launch Onboarding Tutorial");
+ launchOnboardingTutorialPreference.setSummary("Learn the basic navigation gestures.");
+ launchOnboardingTutorialPreference.setOnPreferenceClickListener(preference -> {
+ startActivity(launchSandboxIntent.putExtra(
+ "tutorial_steps",
+ new String[] {
+ "LEFT_EDGE_BACK_NAVIGATION",
+ "HOME_NAVIGATION",
+ "OVERVIEW_NAVIGATION"}));
+ return true;
+ });
+ sandboxCategory.addPreference(launchOnboardingTutorialPreference);
Preference launchBackTutorialPreference = new Preference(context);
launchBackTutorialPreference.setKey("launchBackTutorial");
launchBackTutorialPreference.setTitle("Launch Back Tutorial");
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index 22c9d5b..8b52016 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -19,8 +19,12 @@
import android.content.Context;
+import androidx.core.graphics.ColorUtils;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
/**
* Scale down workspace/hotseat to hint at going to either overview (on pause) or first home screen.
@@ -49,8 +53,9 @@
}
@Override
- public float getWorkspaceScrimAlpha(Launcher launcher) {
- return 0.4f;
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return ColorUtils.setAlphaComponent(
+ Themes.getAttrColor(launcher, R.attr.overviewScrimColor), 100);
}
@Override
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 39bcdc5..8db1dbe 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -89,7 +89,7 @@
@Override
public float getWorkspaceBackgroundAlpha(Launcher launcher) {
- return 0.3f;
+ return 0.2f;
}
@Override
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 60dd0f3..3296ea5 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -109,10 +109,10 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
- public static final String RECEIVER_LEAK = "b/185385047";
+ public static final String LAUNCHER_NOT_TRANSPOSED = "b/185820525";
public static final String NO_SWIPE_TO_HOME = "b/158017601";
public static final String WORK_PROFILE_REMOVED = "b/159671700";
public static final String TIS_NO_EVENTS = "b/180915942";
public static final String GET_RECENTS_FAILED = "b/177472267";
- public static final String TWO_BUTTON_NORMAL_NOT_OVERVIEW = "b/13714484";
+ public static final String TWO_BUTTON_NORMAL_NOT_OVERVIEW = "b/177316094";
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index a437293..d092f11 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -352,7 +352,7 @@
// case the user started interacting with it before the animation finished.
mLauncher.getStateManager().goToState(targetState, false /* animated */);
}
- mLauncher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(
+ mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
1f).setDuration(0).start();
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 2e54904..ce7dc07 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -180,7 +180,7 @@
LauncherApps launcherApps = launcher.getSystemService(LauncherApps.class);
try {
launcherApps.startPackageInstallerSessionDetailsActivity(sessionInfo, null,
- launcher.getActivityLaunchOptions(v).toBundle());
+ launcher.getActivityLaunchOptions(v, item).toBundle());
return;
} catch (Exception e) {
Log.e(TAG, "Unable to launch market intent for package=" + packageName, e);
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 18e27a4..2fd5efc 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -38,10 +38,8 @@
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import java.util.Collections;
@@ -60,18 +58,23 @@
}
@Override
- public void delegateScrollTo(PagedView pagedView, int secondaryScroll, int minMaxScroll) {
- pagedView.superScrollTo(secondaryScroll, minMaxScroll);
+ public int getPrimaryValue(int x, int y) {
+ return y;
}
@Override
- public void delegateScrollBy(PagedView pagedView, int unboundedScroll, int x, int y) {
- pagedView.scrollTo(pagedView.getScrollX() + x, unboundedScroll + y);
+ public int getSecondaryValue(int x, int y) {
+ return x;
}
@Override
- public void scrollerStartScroll(OverScroller scroller, int newPosition) {
- scroller.startScroll(scroller.getCurrPos(), newPosition - scroller.getCurrPos());
+ public float getPrimaryValue(float x, float y) {
+ return y;
+ }
+
+ @Override
+ public float getSecondaryValue(float x, float y) {
+ return x;
}
@Override
@@ -87,11 +90,6 @@
}
@Override
- public void delegateScrollTo(PagedView pagedView, int primaryScroll) {
- pagedView.superScrollTo(pagedView.getScrollX(), primaryScroll);
- }
-
- @Override
public <T> void set(T target, Int2DAction<T> action, int param) {
action.call(target, 0, param);
}
@@ -241,13 +239,13 @@
}
@Override
- public float getTaskMenuX(float x, View thumbnailView) {
+ public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
return thumbnailView.getMeasuredWidth() + x;
}
@Override
- public float getTaskMenuY(float y, View thumbnailView) {
- return y;
+ public float getTaskMenuY(float y, View thumbnailView, int overScroll) {
+ return y + overScroll;
}
@Override
@@ -256,16 +254,21 @@
}
@Override
- public int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate,
+ public void setTaskMenuLayoutOrientation(DeviceProfile deviceProfile,
LinearLayout taskMenuLayout) {
- return LinearLayout.HORIZONTAL;
+ taskMenuLayout.setOrientation(LinearLayout.HORIZONTAL);
}
@Override
- public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp) {
+ public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp,
+ LinearLayout viewGroup, DeviceProfile deviceProfile) {
+ // Phone fake landscape
+ viewGroup.setOrientation(LinearLayout.VERTICAL);
lp.width = 0;
lp.height = WRAP_CONTENT;
lp.weight = 1;
+ Utilities.setStartMarginForView(viewGroup.findViewById(R.id.text), 0);
+ Utilities.setStartMarginForView(viewGroup.findViewById(R.id.icon), 0);
}
/* ---------- The following are only used by TaskViewTouchHandler. ---------- */
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 560df86..6c2f17e 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -30,8 +30,6 @@
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.PagedView;
-import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
@@ -89,19 +87,23 @@
boolean getRecentsRtlSetting(Resources resources);
float getDegreesRotated();
int getRotation();
+
<T> T getPrimaryValue(T x, T y);
<T> T getSecondaryValue(T x, T y);
- void delegateScrollTo(PagedView pagedView, int secondaryScroll, int primaryScroll);
- /** Uses {@params pagedView}.getScroll[X|Y]() method for the secondary amount*/
- void delegateScrollTo(PagedView pagedView, int primaryScroll);
- void delegateScrollBy(PagedView pagedView, int unboundedScroll, int x, int y);
- void scrollerStartScroll(OverScroller scroller, int newPosition);
+
+ int getPrimaryValue(int x, int y);
+ int getSecondaryValue(int x, int y);
+
+ float getPrimaryValue(float x, float y);
+ float getSecondaryValue(float x, float y);
+
boolean isLayoutNaturalToLauncher();
- float getTaskMenuX(float x, View thumbnailView);
- float getTaskMenuY(float y, View thumbnailView);
+ float getTaskMenuX(float x, View thumbnailView, int overScroll);
+ float getTaskMenuY(float y, View thumbnailView, int overScroll);
int getTaskMenuWidth(View view);
- int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate, LinearLayout taskMenuLayout);
- void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp);
+ void setTaskMenuLayoutOrientation(DeviceProfile deviceProfile, LinearLayout taskMenuLayout);
+ void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp,
+ LinearLayout viewGroup, DeviceProfile deviceProfile);
int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect);
List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp);
FloatProperty getSplitSelectTaskOffset(FloatProperty primary, FloatProperty secondary,
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 86508c4..f6a6448 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -36,10 +36,8 @@
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import java.util.ArrayList;
@@ -58,18 +56,23 @@
}
@Override
- public void delegateScrollTo(PagedView pagedView, int secondaryScroll, int primaryScroll) {
- pagedView.superScrollTo(primaryScroll, secondaryScroll);
+ public int getPrimaryValue(int x, int y) {
+ return x;
}
@Override
- public void delegateScrollBy(PagedView pagedView, int unboundedScroll, int x, int y) {
- pagedView.scrollTo(unboundedScroll + x, pagedView.getScrollY() + y);
+ public int getSecondaryValue(int x, int y) {
+ return y;
}
@Override
- public void scrollerStartScroll(OverScroller scroller, int newPosition) {
- scroller.startScroll(newPosition - scroller.getCurrPos(), scroller.getCurrPos());
+ public float getPrimaryValue(float x, float y) {
+ return x;
+ }
+
+ @Override
+ public float getSecondaryValue(float x, float y) {
+ return y;
}
@Override
@@ -83,11 +86,6 @@
}
@Override
- public void delegateScrollTo(PagedView pagedView, int primaryScroll) {
- pagedView.superScrollTo(primaryScroll, pagedView.getScrollY());
- }
-
- @Override
public <T> void set(T target, Int2DAction<T> action, int param) {
action.call(target, param, 0);
}
@@ -240,12 +238,12 @@
}
@Override
- public float getTaskMenuX(float x, View thumbnailView) {
- return x;
+ public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
+ return x + overScroll;
}
@Override
- public float getTaskMenuY(float y, View thumbnailView) {
+ public float getTaskMenuY(float y, View thumbnailView, int overScroll) {
return y;
}
@@ -255,14 +253,34 @@
}
@Override
- public int getTaskMenuLayoutOrientation(boolean canRecentsActivityRotate,
+ public void setTaskMenuLayoutOrientation(DeviceProfile deviceProfile,
LinearLayout taskMenuLayout) {
- return canRecentsActivityRotate ? taskMenuLayout.getOrientation() : LinearLayout.VERTICAL;
+ if (deviceProfile.isLandscape && !deviceProfile.isTablet) {
+ // Phone landscape
+ taskMenuLayout.setOrientation(LinearLayout.HORIZONTAL);
+ } else {
+ // Phone Portrait, LargeScreen Landscape/Portrait
+ taskMenuLayout.setOrientation(LinearLayout.VERTICAL);
+ }
}
@Override
- public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp) {
- // no-op, defaults are fine
+ public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp,
+ LinearLayout viewGroup, DeviceProfile deviceProfile) {
+ if (deviceProfile.isLandscape && !deviceProfile.isTablet) {
+ // Phone landscape
+ viewGroup.setOrientation(LinearLayout.VERTICAL);
+ lp.width = 0;
+ lp.weight = 1;
+ Utilities.setStartMarginForView(viewGroup.findViewById(R.id.text), 0);
+ Utilities.setStartMarginForView(viewGroup.findViewById(R.id.icon), 0);
+ } else {
+ // Phone Portrait, LargeScreen Landscape/Portrait
+ viewGroup.setOrientation(LinearLayout.HORIZONTAL);
+ lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
+ }
+
+ lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
}
/* ---------- The following are only used by TaskViewTouchHandler. ---------- */
@@ -313,21 +331,31 @@
@Override
public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
List<SplitPositionOption> options = new ArrayList<>(1);
+ // Add both left and right options if we're in tablet mode
// TODO: Add in correct icons
- if (dp.isSeascape()) { // or seascape
- // Add left/right options
+ if (dp.isTablet && dp.isLandscape) {
options.add(new SplitPositionOption(
R.drawable.ic_split_screen, R.string.split_screen_position_right,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
- } else if (dp.isLandscape) {
+ STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
options.add(new SplitPositionOption(
R.drawable.ic_split_screen, R.string.split_screen_position_left,
STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
} else {
- // Only add top option
- options.add(new SplitPositionOption(
- R.drawable.ic_split_screen, R.string.split_screen_position_top,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ if (dp.isSeascape()) {
+ // Add left/right options
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_screen, R.string.split_screen_position_right,
+ STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
+ } else if (dp.isLandscape) {
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_screen, R.string.split_screen_position_left,
+ STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ } else {
+ // Only add top option
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_screen, R.string.split_screen_position_top,
+ STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ }
}
return options;
}
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index bd6e31b..893a274 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -79,13 +79,13 @@
}
@Override
- public float getTaskMenuX(float x, View thumbnailView) {
+ public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
return x;
}
@Override
- public float getTaskMenuY(float y, View thumbnailView) {
- return y + thumbnailView.getMeasuredHeight();
+ public float getTaskMenuY(float y, View thumbnailView, int overScroll) {
+ return y + thumbnailView.getMeasuredHeight() + overScroll;
}
@Override
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
index 59266b4..b5b9c2f 100644
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ b/src/com/android/launcher3/util/ActivityTracker.java
@@ -75,9 +75,8 @@
private boolean handleIntent(T activity, Intent intent, boolean alreadyOnHome) {
if (intent != null && intent.getExtras() != null) {
IBinder stateBinder = intent.getExtras().getBinder(EXTRA_SCHEDULER_CALLBACK);
- if (stateBinder instanceof ObjectWrapper) {
- SchedulerCallback<T> handler =
- ((ObjectWrapper<SchedulerCallback>) stateBinder).get();
+ SchedulerCallback<T> handler = ObjectWrapper.unwrap(stateBinder);
+ if (handler != null) {
if (!handler.init(activity, alreadyOnHome)) {
intent.getExtras().remove(EXTRA_SCHEDULER_CALLBACK);
}
diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java
deleted file mode 100644
index b3b69f6..0000000
--- a/src/com/android/launcher3/util/ConfigMonitor.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.android.launcher3.util;
-
-/**
- * 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.
- */
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.util.Log;
-
-import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
-import com.android.launcher3.util.DisplayController.Info;
-
-import java.util.function.Consumer;
-
-/**
- * {@link BroadcastReceiver} which watches configuration changes and
- * notifies the callback in case changes which affect the device profile occur.
- */
-public class ConfigMonitor extends BroadcastReceiver implements DisplayInfoChangeListener {
-
- private static final String TAG = "ConfigMonitor";
-
- private final Point mTmpPoint1 = new Point();
- private final Point mTmpPoint2 = new Point();
-
- private final Context mContext;
- private final float mFontScale;
- private final int mDensity;
-
- private final int mDisplayId;
- private final Point mRealSize;
- private final Point mSmallestSize, mLargestSize;
-
- private Consumer<Context> mCallback;
-
- public ConfigMonitor(Context context, Consumer<Context> callback) {
- mContext = context;
-
- Configuration config = context.getResources().getConfiguration();
- mFontScale = config.fontScale;
- mDensity = config.densityDpi;
-
- DisplayController.DisplayHolder display = DisplayController.getDefaultDisplay(context);
- display.addChangeListener(this);
- Info displayInfo = display.getInfo();
- mDisplayId = displayInfo.id;
-
- mRealSize = new Point(displayInfo.realSize);
- mSmallestSize = new Point(displayInfo.smallestSize);
- mLargestSize = new Point(displayInfo.largestSize);
-
- mCallback = callback;
-
- // Listen for configuration change
- mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Configuration config = context.getResources().getConfiguration();
- if (mFontScale != config.fontScale || mDensity != config.densityDpi) {
- Log.d(TAG, "Configuration changed.");
- notifyChange();
- }
- }
-
- @Override
- public void onDisplayInfoChanged(Info info, int flags) {
- if (info.id != mDisplayId) {
- return;
- }
- mTmpPoint1.set(info.realSize.x, info.realSize.y);
- if (!mRealSize.equals(mTmpPoint1) && !mRealSize.equals(mTmpPoint1.y, mTmpPoint1.x)) {
- Log.d(TAG, String.format("Display size changed from %s to %s", mRealSize, mTmpPoint1));
- notifyChange();
- return;
- }
-
- mTmpPoint1.set(info.smallestSize.x, info.smallestSize.y);
- mTmpPoint2.set(info.largestSize.x, info.largestSize.y);
- if (!mSmallestSize.equals(mTmpPoint1) || !mLargestSize.equals(mTmpPoint2)) {
- Log.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]",
- mSmallestSize, mLargestSize, mTmpPoint1, mTmpPoint2));
- notifyChange();
- }
- }
-
- private synchronized void notifyChange() {
- if (mCallback != null) {
- Consumer<Context> callback = mCallback;
- mCallback = null;
- MAIN_EXECUTOR.execute(() -> callback.accept(mContext));
- }
- }
-
- public void unregister() {
- try {
- mContext.unregisterReceiver(this);
- DisplayController.getDefaultDisplay(mContext).removeChangeListener(this);
- } catch (Exception e) {
- Log.e(TAG, "Failed to unregister config monitor", e);
- }
- }
-}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index d0e8bb1..75c089e 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -16,21 +16,28 @@
package com.android.launcher3.util;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.ComponentCallbacks;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
-import android.util.DisplayMetrics;
+import android.os.Build;
import android.util.Log;
-import android.util.SparseArray;
import android.view.Display;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
+import androidx.annotation.AnyThread;
+import androidx.annotation.UiThread;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.Utilities;
@@ -39,104 +46,78 @@
/**
* Utility class to cache properties of default display to avoid a system RPC on every call.
*/
-public class DisplayController implements DisplayListener {
+@SuppressLint("NewApi")
+public class DisplayController implements DisplayListener, ComponentCallbacks {
private static final String TAG = "DisplayController";
public static final MainThreadInitializedObject<DisplayController> INSTANCE =
new MainThreadInitializedObject<>(DisplayController::new);
- private final SparseArray<DisplayHolder> mOtherDisplays = new SparseArray<>(0);
- // We store the default display separately, to avoid null checks for primary use case.
- private final DisplayHolder mDefaultDisplay;
+ public static final int CHANGE_SIZE = 1 << 0;
+ public static final int CHANGE_ROTATION = 1 << 1;
+ public static final int CHANGE_FRAME_DELAY = 1 << 2;
+ public static final int CHANGE_DENSITY = 1 << 3;
- private final ArrayList<DisplayListChangeListener> mListListeners = new ArrayList<>();
+ public static final int CHANGE_ALL = CHANGE_SIZE | CHANGE_ROTATION
+ | CHANGE_FRAME_DELAY | CHANGE_DENSITY;
+
+ private final Context mContext;
+ private final DisplayManager mDM;
+
+ // Null for SDK < S
+ private final Context mWindowContext;
+
+ private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
+ private Info mInfo;
private DisplayController(Context context) {
- mDefaultDisplay = DisplayHolder.create(context, DEFAULT_DISPLAY);
+ mContext = context;
+ mDM = context.getSystemService(DisplayManager.class);
- DisplayManager dm = context.getSystemService(DisplayManager.class);
- dm.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
- }
-
- @Override
- public final void onDisplayAdded(int displayId) {
- DisplayHolder holder = DisplayHolder.create(mDefaultDisplay.mDisplayContext, displayId);
- if (holder == null) {
- // Display is already removed by the time we dot this.
- return;
- }
- synchronized (mOtherDisplays) {
- mOtherDisplays.put(displayId, holder);
- }
- MAIN_EXECUTOR.execute(() -> mListListeners.forEach(l-> l.onDisplayAdded(holder)));
- }
-
- @Override
- public final void onDisplayRemoved(int displayId) {
- synchronized (mOtherDisplays) {
- mOtherDisplays.remove(displayId);
- }
- MAIN_EXECUTOR.execute(() -> mListListeners.forEach(l-> l.onDisplayRemoved(displayId)));
- }
-
- /**
- * Returns the holder corresponding to the given display
- */
- public DisplayHolder getHolder(int displayId) {
- if (displayId == mDefaultDisplay.mId) {
- return mDefaultDisplay;
+ Display display = mDM.getDisplay(DEFAULT_DISPLAY);
+ if (Utilities.ATLEAST_S) {
+ mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
+ mWindowContext.registerComponentCallbacks(this);
} else {
- synchronized (mOtherDisplays) {
- return mOtherDisplays.get(displayId);
- }
+ mWindowContext = null;
+ SimpleBroadcastReceiver configChangeReceiver =
+ new SimpleBroadcastReceiver(this::onConfigChanged);
+ mContext.registerReceiver(configChangeReceiver,
+ new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
}
+
+ mInfo = new Info(getContext(display), display);
+ mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
}
- /**
- * Adds a listener for display list changes
- */
- public void addListChangeListener(DisplayListChangeListener listener) {
- mListListeners.add(listener);
- }
+ @Override
+ public final void onDisplayAdded(int displayId) { }
- /**
- * Removes a previously added display list change listener
- */
- public void removeListChangeListener(DisplayListChangeListener listener) {
- mListListeners.remove(listener);
- }
+ @Override
+ public final void onDisplayRemoved(int displayId) { }
+ @WorkerThread
@Override
public final void onDisplayChanged(int displayId) {
- DisplayHolder holder = getHolder(displayId);
- if (holder != null) {
- holder.handleOnChange();
+ if (displayId != DEFAULT_DISPLAY) {
+ return;
}
+ Display display = mDM.getDisplay(DEFAULT_DISPLAY);
+ if (display == null) {
+ return;
+ }
+ if (Utilities.ATLEAST_S) {
+ // Only check for refresh rate. Everything else comes from component callbacks
+ if (getSingleFrameMs(display) == mInfo.singleFrameMs) {
+ return;
+ }
+ }
+ handleInfoChange(display);
}
public static int getSingleFrameMs(Context context) {
- return getDefaultDisplay(context).getInfo().singleFrameMs;
- }
-
- public static DisplayHolder getDefaultDisplay(Context context) {
- return INSTANCE.get(context).mDefaultDisplay;
- }
-
- /**
- * A listener to receiving addition or removal of new displays
- */
- public interface DisplayListChangeListener {
-
- /**
- * Called when a new display is added
- */
- void onDisplayAdded(DisplayHolder holder);
-
- /**
- * Called when a previously added display is removed
- */
- void onDisplayRemoved(int displayId);
+ return INSTANCE.get(context).getInfo().singleFrameMs;
}
/**
@@ -144,150 +125,131 @@
*/
public interface DisplayInfoChangeListener {
- void onDisplayInfoChanged(Info info, int flags);
+ /**
+ * Invoked when display info has changed.
+ * @param context updated context associated with the display.
+ * @param info updated display information.
+ * @param flags bitmask indicating type of change.
+ */
+ void onDisplayInfoChanged(Context context, Info info, int flags);
}
- public static class DisplayHolder {
-
- public static final int CHANGE_SIZE = 1 << 0;
- public static final int CHANGE_ROTATION = 1 << 1;
- public static final int CHANGE_FRAME_DELAY = 1 << 2;
-
- public static final int CHANGE_ALL = CHANGE_SIZE | CHANGE_ROTATION | CHANGE_FRAME_DELAY;
-
- final Context mDisplayContext;
- final int mId;
- private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
- private DisplayController.Info mInfo;
-
- private DisplayHolder(Context displayContext) {
- mDisplayContext = displayContext;
- // Note that the Display object must be obtained from DisplayManager which is
- // associated to the display context, so the Display is isolated from Activity and
- // Application to provide the actual state of device that excludes the additional
- // adjustment and override.
- mInfo = new DisplayController.Info(mDisplayContext);
- mId = mInfo.id;
- }
-
- public void addChangeListener(DisplayInfoChangeListener listener) {
- mListeners.add(listener);
- }
-
- public void removeChangeListener(DisplayInfoChangeListener listener) {
- mListeners.remove(listener);
- }
-
- public DisplayController.Info getInfo() {
- return mInfo;
- }
-
- /** Creates and up-to-date DisplayController.Info for the given context. */
- @Nullable
- public Info createInfoForContext(Context context) {
- Display display = Utilities.ATLEAST_R ? context.getDisplay() : null;
- if (display == null) {
- display = context.getSystemService(DisplayManager.class).getDisplay(mId);
- }
- if (display == null) {
- return null;
- }
- // Refresh the Context the prevent stale DisplayMetrics.
- Context displayContext = context.getApplicationContext().createDisplayContext(display);
- return new Info(displayContext, display);
- }
-
- public Context getDisplayContext() {
- return mDisplayContext;
- }
-
- protected void handleOnChange() {
- Info oldInfo = mInfo;
- Info newInfo = createInfoForContext(mDisplayContext);
- if (newInfo == null) {
- return;
- }
-
- int change = 0;
- if (newInfo.hasDifferentSize(oldInfo)) {
- change |= CHANGE_SIZE;
- }
- if (newInfo.rotation != oldInfo.rotation) {
- change |= CHANGE_ROTATION;
- }
- if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
- change |= CHANGE_FRAME_DELAY;
- }
-
- if (change != 0) {
- mInfo = newInfo;
- final int flags = change;
- MAIN_EXECUTOR.execute(() -> notifyChange(flags));
+ /**
+ * Only used for pre-S
+ */
+ private void onConfigChanged(Intent intent) {
+ Configuration config = mContext.getResources().getConfiguration();
+ if (config.fontScale != config.fontScale || mInfo.densityDpi != config.densityDpi) {
+ Log.d(TAG, "Configuration changed, notifying listeners");
+ Display display = mDM.getDisplay(DEFAULT_DISPLAY);
+ if (display != null) {
+ handleInfoChange(display);
}
}
+ }
- private void notifyChange(int flags) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- mListeners.get(i).onDisplayInfoChanged(mInfo, flags);
- }
+ @UiThread
+ @Override
+ @TargetApi(Build.VERSION_CODES.S)
+ public final void onConfigurationChanged(Configuration config) {
+ Display display = mWindowContext.getDisplay();
+ if (config.densityDpi != mInfo.densityDpi
+ || config.fontScale != mInfo.fontScale
+ || display.getRotation() != mInfo.rotation
+ || !mInfo.mScreenSizeDp.equals(
+ Math.min(config.screenHeightDp, config.screenWidthDp),
+ Math.max(config.screenHeightDp, config.screenWidthDp))) {
+ handleInfoChange(display);
+ }
+ }
+
+ @Override
+ public final void onLowMemory() { }
+
+ public void addChangeListener(DisplayInfoChangeListener listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeChangeListener(DisplayInfoChangeListener listener) {
+ mListeners.remove(listener);
+ }
+
+ public Info getInfo() {
+ return mInfo;
+ }
+
+ private Context getContext(Display display) {
+ return Utilities.ATLEAST_S ? mWindowContext : mContext.createDisplayContext(display);
+ }
+
+ @AnyThread
+ private void handleInfoChange(Display display) {
+ Info oldInfo = mInfo;
+ Context context = getContext(display);
+ Info newInfo = new Info(context, display);
+ int change = 0;
+ if (newInfo.hasDifferentSize(oldInfo)) {
+ change |= CHANGE_SIZE;
+ }
+ if (newInfo.rotation != oldInfo.rotation) {
+ change |= CHANGE_ROTATION;
+ }
+ if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
+ change |= CHANGE_FRAME_DELAY;
+ }
+ if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
+ change |= CHANGE_DENSITY;
}
- private static DisplayHolder create(Context context, int id) {
- DisplayManager dm = context.getSystemService(DisplayManager.class);
- Display display = dm.getDisplay(id);
- if (display == null) {
- return null;
- }
- // Use application context to create display context so that it can have its own
- // Resources.
- Context displayContext = context.getApplicationContext().createDisplayContext(display);
- return new DisplayHolder(displayContext);
+ if (change != 0) {
+ mInfo = newInfo;
+ final int flags = change;
+ MAIN_EXECUTOR.execute(() -> notifyChange(context, flags));
+ }
+ }
+
+ private void notifyChange(Context context, int flags) {
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ mListeners.get(i).onDisplayInfoChanged(context, mInfo, flags);
}
}
public static class Info {
public final int id;
- public final int rotation;
public final int singleFrameMs;
+ // Configuration properties
+ public final int rotation;
+ public final float fontScale;
+ public final int densityDpi;
+
+ private final Point mScreenSizeDp;
+
public final Point realSize;
public final Point smallestSize;
public final Point largestSize;
- public final DisplayMetrics metrics;
-
- @VisibleForTesting
- public Info(int id, int rotation, int singleFrameMs, Point realSize, Point smallestSize,
- Point largestSize, DisplayMetrics metrics) {
- this.id = id;
- this.rotation = rotation;
- this.singleFrameMs = singleFrameMs;
- this.realSize = realSize;
- this.smallestSize = smallestSize;
- this.largestSize = largestSize;
- this.metrics = metrics;
- }
-
- private Info(Context context) {
- this(context, context.getSystemService(DisplayManager.class)
- .getDisplay(DEFAULT_DISPLAY));
- }
-
public Info(Context context, Display display) {
id = display.getDisplayId();
+
rotation = display.getRotation();
- float refreshRate = display.getRefreshRate();
- singleFrameMs = refreshRate > 0 ? (int) (1000 / refreshRate) : 16;
+ Configuration config = context.getResources().getConfiguration();
+ fontScale = config.fontScale;
+ densityDpi = config.densityDpi;
+ mScreenSizeDp = new Point(
+ Math.min(config.screenHeightDp, config.screenWidthDp),
+ Math.max(config.screenHeightDp, config.screenWidthDp));
+
+ singleFrameMs = getSingleFrameMs(display);
realSize = new Point();
smallestSize = new Point();
largestSize = new Point();
+
display.getRealSize(realSize);
display.getCurrentSizeRange(smallestSize, largestSize);
-
- metrics = context.getResources().getDisplayMetrics();
}
private boolean hasDifferentSize(Info info) {
@@ -307,4 +269,9 @@
return false;
}
}
+
+ private static int getSingleFrameMs(Display display) {
+ float refreshRate = display.getRefreshRate();
+ return refreshRate > 0 ? (int) (1000 / refreshRate) : 16;
+ }
}
diff --git a/src/com/android/launcher3/util/EdgeEffectCompat.java b/src/com/android/launcher3/util/EdgeEffectCompat.java
new file mode 100644
index 0000000..491582b
--- /dev/null
+++ b/src/com/android/launcher3/util/EdgeEffectCompat.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.launcher3.util;
+
+import android.content.Context;
+import android.widget.EdgeEffect;
+
+import com.android.launcher3.Utilities;
+
+/**
+ * Extension of {@link EdgeEffect} to allow backwards compatibility
+ */
+public class EdgeEffectCompat extends EdgeEffect {
+
+ public EdgeEffectCompat(Context context) {
+ super(context);
+ }
+
+ @Override
+ public float getDistance() {
+ return Utilities.ATLEAST_S ? super.getDistance() : 0;
+ }
+
+ @Override
+ public float onPullDistance(float deltaDistance, float displacement) {
+ if (Utilities.ATLEAST_S) {
+ return super.onPullDistance(deltaDistance, displacement);
+ } else {
+ onPull(deltaDistance, displacement);
+ return deltaDistance;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
index 9d0ad22..c9aa51c 100644
--- a/src/com/android/launcher3/util/FlingAnimation.java
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -70,9 +70,6 @@
mAnimationTimeFraction = ((float) mDuration) / (mDuration + DRAG_END_DELAY);
- // Don't highlight the icon as it's animating
- mDragObject.dragView.setColor(0);
-
final int duration = mDuration + DRAG_END_DELAY;
final long startTime = AnimationUtils.currentAnimationTimeMillis();
diff --git a/src/com/android/launcher3/util/IOUtils.java b/src/com/android/launcher3/util/IOUtils.java
index 1cec0ec..d7fa905 100644
--- a/src/com/android/launcher3/util/IOUtils.java
+++ b/src/com/android/launcher3/util/IOUtils.java
@@ -16,7 +16,9 @@
package com.android.launcher3.util;
+import android.graphics.Bitmap;
import android.os.FileUtils;
+import android.util.Base64;
import android.util.Log;
import com.android.launcher3.Utilities;
@@ -50,6 +52,12 @@
return out.toByteArray();
}
+ public static String toBase64String(Bitmap bitmap) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
+ return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
+ }
+
public static long copy(InputStream from, OutputStream to) throws IOException {
if (Utilities.ATLEAST_Q) {
return FileUtils.copy(from, to);
diff --git a/src/com/android/launcher3/util/ObjectWrapper.java b/src/com/android/launcher3/util/ObjectWrapper.java
index e5b4707..a715821 100644
--- a/src/com/android/launcher3/util/ObjectWrapper.java
+++ b/src/com/android/launcher3/util/ObjectWrapper.java
@@ -42,4 +42,11 @@
public static IBinder wrap(Object obj) {
return new ObjectWrapper<>(obj);
}
+
+ public static <T> T unwrap(IBinder binder) {
+ if (binder instanceof ObjectWrapper) {
+ return ((ObjectWrapper<T>) binder).get();
+ }
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/util/OverScroller.java b/src/com/android/launcher3/util/OverScroller.java
deleted file mode 100644
index 87e6986..0000000
--- a/src/com/android/launcher3/util/OverScroller.java
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
- * Copyright (C) 2010 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.launcher3.util;
-
-import static com.android.launcher3.anim.Interpolators.SCROLL;
-
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.hardware.SensorManager;
-import android.util.Log;
-import android.view.ViewConfiguration;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-
-import androidx.dynamicanimation.animation.FloatPropertyCompat;
-import androidx.dynamicanimation.animation.SpringAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
-
-import com.android.launcher3.R;
-import com.android.systemui.plugins.ResourceProvider;
-
-/**
- * Based on {@link android.widget.OverScroller} supporting only 1-d scrolling and with more
- * customization options.
- */
-public class OverScroller {
- private int mMode;
-
- private final SplineOverScroller mScroller;
-
- private TimeInterpolator mInterpolator;
-
- private final boolean mFlywheel;
-
- private static final int DEFAULT_DURATION = 250;
- private static final int SCROLL_MODE = 0;
- private static final int FLING_MODE = 1;
-
- /**
- * Creates an OverScroller with a viscous fluid scroll interpolator and flywheel.
- * @param context
- */
- public OverScroller(Context context) {
- this(context, null);
- }
-
- /**
- * Creates an OverScroller with flywheel enabled.
- * @param context The context of this application.
- * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
- * be used.
- */
- public OverScroller(Context context, Interpolator interpolator) {
- this(context, interpolator, true);
- }
-
- /**
- * Creates an OverScroller.
- * @param context The context of this application.
- * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
- * be used.
- * @param flywheel If true, successive fling motions will keep on increasing scroll speed.
- */
- public OverScroller(Context context, Interpolator interpolator, boolean flywheel) {
- if (interpolator == null) {
- mInterpolator = SCROLL;
- } else {
- mInterpolator = interpolator;
- }
- mFlywheel = flywheel;
- mScroller = new SplineOverScroller(context);
- }
-
- public void setInterpolator(TimeInterpolator interpolator) {
- if (interpolator == null) {
- mInterpolator = SCROLL;
- } else {
- mInterpolator = interpolator;
- }
- }
-
- /**
- * The amount of friction applied to flings. The default value
- * is {@link ViewConfiguration#getScrollFriction}.
- *
- * @param friction A scalar dimension-less value representing the coefficient of
- * friction.
- */
- public final void setFriction(float friction) {
- mScroller.setFriction(friction);
- }
-
- /**
- *
- * Returns whether the scroller has finished scrolling.
- *
- * @return True if the scroller has finished scrolling, false otherwise.
- */
- public final boolean isFinished() {
- return mScroller.mFinished;
- }
-
- /**
- * Force the finished field to a particular value. Contrary to
- * {@link #abortAnimation()}, forcing the animation to finished
- * does NOT cause the scroller to move to the final x and y
- * position.
- *
- * @param finished The new finished value.
- */
- public final void forceFinished(boolean finished) {
- mScroller.mFinished = finished;
- }
-
- /**
- * Returns the current offset in the scroll.
- *
- * @return The new offset as an absolute distance from the origin.
- */
- public final int getCurrPos() {
- return mScroller.mCurrentPosition;
- }
-
- /**
- * Returns the absolute value of the current velocity.
- *
- * @return The original velocity less the deceleration, norm of the X and Y velocity vector.
- */
- public float getCurrVelocity() {
- return mScroller.mCurrVelocity;
- }
-
- /**
- * Returns the start offset in the scroll.
- *
- * @return The start offset as an absolute distance from the origin.
- */
- public final int getStartPos() {
- return mScroller.mStart;
- }
-
- /**
- * Returns where the scroll will end. Valid only for "fling" scrolls.
- *
- * @return The final offset as an absolute distance from the origin.
- */
- public final int getFinalPos() {
- return mScroller.mFinal;
- }
-
- /**
- * Returns how long the scroll event will take, in milliseconds.
- *
- * Note that if mScroller.mState == SPRING, this duration is ignored, so can only
- * serve as an estimate for how long the spring-controlled scroll will take.
- *
- * @return The duration of the scroll in milliseconds.
- */
- public final int getDuration() {
- return mScroller.mDuration;
- }
-
- /**
- * Extend the scroll animation. This allows a running animation to scroll
- * further and longer, when used with {@link #setFinalPos(int)}.
- *
- * @param extend Additional time to scroll in milliseconds.
- * @see #setFinalPos(int)
- */
- public void extendDuration(int extend) {
- mScroller.extendDuration(extend);
- }
-
- /**
- * Sets the final position for this scroller.
- *
- * @param newPos The new offset as an absolute distance from the origin.
- * @see #extendDuration(int)
- */
- public void setFinalPos(int newPos) {
- mScroller.setFinalPosition(newPos);
- }
-
- /**
- * Call this when you want to know the new location. If it returns true, the
- * animation is not yet finished.
- */
- public boolean computeScrollOffset() {
- if (isFinished()) {
- return false;
- }
-
- switch (mMode) {
- case SCROLL_MODE:
- if (isSpringing()) {
- return true;
- }
- long time = AnimationUtils.currentAnimationTimeMillis();
- // Any scroller can be used for time, since they were started
- // together in scroll mode. We use X here.
- final long elapsedTime = time - mScroller.mStartTime;
-
- final int duration = mScroller.mDuration;
- if (elapsedTime < duration) {
- final float q = mInterpolator.getInterpolation(elapsedTime / (float) duration);
- mScroller.updateScroll(q);
- } else {
- abortAnimation();
- }
- break;
-
- case FLING_MODE:
- if (!mScroller.mFinished) {
- if (!mScroller.update()) {
- if (!mScroller.continueWhenFinished()) {
- mScroller.finish();
- }
- }
- }
-
- break;
- }
-
- return true;
- }
-
- /**
- * Start scrolling by providing a starting point and the distance to travel.
- * The scroll will use the default value of 250 milliseconds for the
- * duration.
- *
- * @param start Starting horizontal scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param delta Distance to travel. Positive numbers will scroll the
- * content to the left.
- */
- public void startScroll(int start, int delta) {
- startScroll(start, delta, DEFAULT_DURATION);
- }
-
- /**
- * Start scrolling by providing a starting point and the distance to travel.
- *
- * @param start Starting scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param delta Distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param duration Duration of the scroll in milliseconds.
- */
- public void startScroll(int start, int delta, int duration) {
- mMode = SCROLL_MODE;
- mScroller.startScroll(start, delta, duration);
- }
-
- /**
- * Start scrolling using a spring by providing a starting point and the distance to travel.
- *
- * @param start Starting scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param delta Distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param duration Duration of the scroll in milliseconds.
- * @param velocity The starting velocity for the spring in px per ms.
- */
- public void startScrollSpring(int start, int delta, int duration, float velocity) {
- mMode = SCROLL_MODE;
- mScroller.mState = mScroller.SPRING;
- mScroller.startScroll(start, delta, duration, velocity);
- }
-
- /**
- * Call this when you want to 'spring back' into a valid coordinate range.
- *
- * @param start Starting X coordinate
- * @param min Minimum valid X value
- * @param max Maximum valid X value
- * @return true if a springback was initiated, false if startX and startY were
- * already within the valid range.
- */
- public boolean springBack(int start, int min, int max) {
- mMode = FLING_MODE;
- return mScroller.springback(start, min, max);
- }
-
- public void fling(int start, int velocity, int min, int max) {
- fling(start, velocity, min, max, 0);
- }
-
- /**
- * Start scrolling based on a fling gesture. The distance traveled will
- * depend on the initial velocity of the fling.
- * @param start Starting point of the scroll (X)
- * @param velocity Initial velocity of the fling (X) measured in pixels per
- * second.
- * @param min Minimum X value. The scroller will not scroll past this point
- * unless overX > 0. If overfling is allowed, it will use minX as
- * a springback boundary.
- * @param max Maximum X value. The scroller will not scroll past this point
-* unless overX > 0. If overfling is allowed, it will use maxX as
-* a springback boundary.
- * @param over Overfling range. If > 0, horizontal overfling in either
-* direction will be possible.
- */
- public void fling(int start, int velocity, int min, int max, int over) {
- // Continue a scroll or fling in progress
- if (mFlywheel && !isFinished()) {
- float oldVelocityX = mScroller.mCurrVelocity;
- if (Math.signum(velocity) == Math.signum(oldVelocityX)) {
- velocity += oldVelocityX;
- }
- }
-
- mMode = FLING_MODE;
- mScroller.fling(start, velocity, min, max, over);
- }
-
- /**
- * Notify the scroller that we've reached a horizontal boundary.
- * Normally the information to handle this will already be known
- * when the animation is started, such as in a call to one of the
- * fling functions. However there are cases where this cannot be known
- * in advance. This function will transition the current motion and
- * animate from startX to finalX as appropriate.
- * @param start Starting/current X position
- * @param finalPos Desired final X position
- * @param over Magnitude of overscroll allowed. This should be the maximum
- */
- public void notifyEdgeReached(int start, int finalPos, int over) {
- mScroller.notifyEdgeReached(start, finalPos, over);
- }
-
- /**
- * Returns whether the current Scroller is currently returning to a valid position.
- * Valid bounds were provided by the
- * {@link #fling(int, int, int, int, int)} method.
- *
- * One should check this value before calling
- * {@link #startScroll(int, int)} as the interpolation currently in progress
- * to restore a valid position will then be stopped. The caller has to take into account
- * the fact that the started scroll will start from an overscrolled position.
- *
- * @return true when the current position is overscrolled and in the process of
- * interpolating back to a valid value.
- */
- public boolean isOverScrolled() {
- return (!mScroller.mFinished && mScroller.mState != SplineOverScroller.SPLINE);
- }
-
- /**
- * Stops the animation. Contrary to {@link #forceFinished(boolean)},
- * aborting the animating causes the scroller to move to the final x and y
- * positions.
- *
- * @see #forceFinished(boolean)
- */
- public void abortAnimation() {
- mScroller.finish();
- }
-
- /**
- * Returns the time elapsed since the beginning of the scrolling.
- *
- * @return The elapsed time in milliseconds.
- *
- * @hide
- */
- public int timePassed() {
- final long time = AnimationUtils.currentAnimationTimeMillis();
- return (int) (time - mScroller.mStartTime);
- }
-
- public boolean isSpringing() {
- return mScroller.mState == SplineOverScroller.SPRING && !isFinished();
- }
-
- static class SplineOverScroller {
- // Initial position
- private int mStart;
-
- // Current position
- private int mCurrentPosition;
-
- // Final position
- private int mFinal;
-
- // Initial velocity
- private int mVelocity;
-
- // Current velocity
- private float mCurrVelocity;
-
- // Constant current deceleration
- private float mDeceleration;
-
- // Animation starting time, in system milliseconds
- private long mStartTime;
-
- // Animation duration, in milliseconds
- private int mDuration;
-
- // Duration to complete spline component of animation
- private int mSplineDuration;
-
- // Distance to travel along spline animation
- private int mSplineDistance;
-
- // Whether the animation is currently in progress
- private boolean mFinished;
-
- // The allowed overshot distance before boundary is reached.
- private int mOver;
-
- // Fling friction
- private float mFlingFriction = ViewConfiguration.getScrollFriction();
-
- // Current state of the animation.
- private int mState = SPLINE;
-
- private Context mContext;
- private SpringAnimation mSpring;
-
- // Constant gravity value, used in the deceleration phase.
- private static final float GRAVITY = 2000.0f;
-
- // A context-specific coefficient adjusted to physical values.
- private float mPhysicalCoeff;
-
- private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
- private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
- private static final float START_TENSION = 0.5f;
- private static final float END_TENSION = 1.0f;
- private static final float P1 = START_TENSION * INFLEXION;
- private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
-
- private static final int NB_SAMPLES = 100;
- private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
- private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
-
- private static final int SPLINE = 0;
- private static final int CUBIC = 1;
- private static final int BALLISTIC = 2;
- private static final int SPRING = 3;
-
- private static final FloatPropertyCompat<SplineOverScroller> SPRING_PROPERTY =
- new FloatPropertyCompat<SplineOverScroller>("splineOverScrollerSpring") {
- @Override
- public float getValue(SplineOverScroller scroller) {
- return scroller.mCurrentPosition;
- }
-
- @Override
- public void setValue(SplineOverScroller scroller, float value) {
- scroller.mCurrentPosition = (int) value;
- }
- };
-
- static {
- float x_min = 0.0f;
- float y_min = 0.0f;
- for (int i = 0; i < NB_SAMPLES; i++) {
- final float alpha = (float) i / NB_SAMPLES;
-
- float x_max = 1.0f;
- float x, tx, coef;
- while (true) {
- x = x_min + (x_max - x_min) / 2.0f;
- coef = 3.0f * x * (1.0f - x);
- tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
- if (Math.abs(tx - alpha) < 1E-5) break;
- if (tx > alpha) x_max = x;
- else x_min = x;
- }
- SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;
-
- float y_max = 1.0f;
- float y, dy;
- while (true) {
- y = y_min + (y_max - y_min) / 2.0f;
- coef = 3.0f * y * (1.0f - y);
- dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
- if (Math.abs(dy - alpha) < 1E-5) break;
- if (dy > alpha) y_max = y;
- else y_min = y;
- }
- SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
- }
- SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
- }
-
- void setFriction(float friction) {
- mFlingFriction = friction;
- }
-
- SplineOverScroller(Context context) {
- mContext = context;
- mFinished = true;
- final float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
- mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2)
- * 39.37f // inch/meter
- * ppi
- * 0.84f; // look and feel tuning
- }
-
- void updateScroll(float q) {
- if (mState == SPRING) {
- return;
- }
- mCurrentPosition = mStart + Math.round(q * (mFinal - mStart));
- }
-
- /*
- * Get a signed deceleration that will reduce the velocity.
- */
- static private float getDeceleration(int velocity) {
- return velocity > 0 ? -GRAVITY : GRAVITY;
- }
-
- /*
- * Modifies mDuration to the duration it takes to get from start to newFinal using the
- * spline interpolation. The previous duration was needed to get to oldFinal.
- */
- private void adjustDuration(int start, int oldFinal, int newFinal) {
- final int oldDistance = oldFinal - start;
- final int newDistance = newFinal - start;
- final float x = Math.abs((float) newDistance / oldDistance);
- final int index = (int) (NB_SAMPLES * x);
- if (index < NB_SAMPLES) {
- final float x_inf = (float) index / NB_SAMPLES;
- final float x_sup = (float) (index + 1) / NB_SAMPLES;
- final float t_inf = SPLINE_TIME[index];
- final float t_sup = SPLINE_TIME[index + 1];
- final float timeCoef = t_inf + (x - x_inf) / (x_sup - x_inf) * (t_sup - t_inf);
- mDuration *= timeCoef;
- }
- }
-
- void startScroll(int start, int distance, int duration) {
- startScroll(start, distance, duration, 0);
- }
-
- void startScroll(int start, int distance, int duration, float velocity) {
- mFinished = false;
-
- mCurrentPosition = mStart = start;
- mFinal = start + distance;
-
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mDuration = duration;
-
- if (mSpring != null) {
- mSpring.cancel();
- }
-
- if (mState == SPRING) {
- mSpring = new SpringAnimation(this, SPRING_PROPERTY);
-
- ResourceProvider rp = DynamicResource.provider(mContext);
- float stiffness = rp.getFloat(R.dimen.horizontal_spring_stiffness);
- float damping = rp.getFloat(R.dimen.horizontal_spring_damping_ratio);
- mSpring.setSpring(new SpringForce(mFinal)
- .setStiffness(stiffness)
- .setDampingRatio(damping));
- mSpring.setStartVelocity(velocity);
- mSpring.animateToFinalPosition(mFinal);
- mSpring.addEndListener((animation, canceled, value, velocity1) -> {
- mSpring = null;
- finish();
- mState = SPLINE;
- });
- }
- // Unused
- mDeceleration = 0.0f;
- mVelocity = 0;
- }
-
- void finish() {
- if (mSpring != null && mSpring.isRunning()) mSpring.cancel();
-
- mCurrentPosition = mFinal;
- // Not reset since WebView relies on this value for fast fling.
- // TODO: restore when WebView uses the fast fling implemented in this class.
- // mCurrVelocity = 0.0f;
- mFinished = true;
- }
-
- void setFinalPosition(int position) {
- mFinal = position;
- if (mState == SPRING && mSpring != null) {
- mSpring.animateToFinalPosition(mFinal);
- }
- mSplineDistance = mFinal - mStart;
- mFinished = false;
- }
-
- void extendDuration(int extend) {
- final long time = AnimationUtils.currentAnimationTimeMillis();
- final int elapsedTime = (int) (time - mStartTime);
- mDuration = mSplineDuration = elapsedTime + extend;
- mFinished = false;
- }
-
- boolean springback(int start, int min, int max) {
- mFinished = true;
-
- mCurrentPosition = mStart = mFinal = start;
- mVelocity = 0;
-
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mDuration = 0;
-
- if (start < min) {
- startSpringback(start, min, 0);
- } else if (start > max) {
- startSpringback(start, max, 0);
- }
-
- return !mFinished;
- }
-
- private void startSpringback(int start, int end, int velocity) {
- // mStartTime has been set
- mFinished = false;
- mState = CUBIC;
- mCurrentPosition = mStart = start;
- mFinal = end;
- final int delta = start - end;
- mDeceleration = getDeceleration(delta);
- // TODO take velocity into account
- mVelocity = -delta; // only sign is used
- mOver = Math.abs(delta);
- mDuration = (int) (1000.0 * Math.sqrt(-2.0 * delta / mDeceleration));
- }
-
- void fling(int start, int velocity, int min, int max, int over) {
- mOver = over;
- mFinished = false;
- mCurrVelocity = mVelocity = velocity;
- mDuration = mSplineDuration = 0;
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mCurrentPosition = mStart = start;
-
- if (start > max || start < min) {
- startAfterEdge(start, min, max, velocity);
- return;
- }
-
- mState = SPLINE;
- double totalDistance = 0.0;
-
- if (velocity != 0) {
- mDuration = mSplineDuration = getSplineFlingDuration(velocity);
- totalDistance = getSplineFlingDistance(velocity);
- }
-
- mSplineDistance = (int) (totalDistance * Math.signum(velocity));
- mFinal = start + mSplineDistance;
-
- // Clamp to a valid final position
- if (mFinal < min) {
- adjustDuration(mStart, mFinal, min);
- mFinal = min;
- }
-
- if (mFinal > max) {
- adjustDuration(mStart, mFinal, max);
- mFinal = max;
- }
- }
-
- private double getSplineDeceleration(int velocity) {
- return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
- }
-
- private double getSplineFlingDistance(int velocity) {
- final double l = getSplineDeceleration(velocity);
- final double decelMinusOne = DECELERATION_RATE - 1.0;
- return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
- }
-
- /* Returns the duration, expressed in milliseconds */
- private int getSplineFlingDuration(int velocity) {
- final double l = getSplineDeceleration(velocity);
- final double decelMinusOne = DECELERATION_RATE - 1.0;
- return (int) (1000.0 * Math.exp(l / decelMinusOne));
- }
-
- private void fitOnBounceCurve(int start, int end, int velocity) {
- // Simulate a bounce that started from edge
- final float durationToApex = - velocity / mDeceleration;
- // The float cast below is necessary to avoid integer overflow.
- final float velocitySquared = (float) velocity * velocity;
- final float distanceToApex = velocitySquared / 2.0f / Math.abs(mDeceleration);
- final float distanceToEdge = Math.abs(end - start);
- final float totalDuration = (float) Math.sqrt(
- 2.0 * (distanceToApex + distanceToEdge) / Math.abs(mDeceleration));
- mStartTime -= (int) (1000.0f * (totalDuration - durationToApex));
- mCurrentPosition = mStart = end;
- mVelocity = (int) (- mDeceleration * totalDuration);
- }
-
- private void startBounceAfterEdge(int start, int end, int velocity) {
- mDeceleration = getDeceleration(velocity == 0 ? start - end : velocity);
- fitOnBounceCurve(start, end, velocity);
- onEdgeReached();
- }
-
- private void startAfterEdge(int start, int min, int max, int velocity) {
- if (start > min && start < max) {
- Log.e("OverScroller", "startAfterEdge called from a valid position");
- mFinished = true;
- return;
- }
- final boolean positive = start > max;
- final int edge = positive ? max : min;
- final int overDistance = start - edge;
- boolean keepIncreasing = overDistance * velocity >= 0;
- if (keepIncreasing) {
- // Will result in a bounce or a to_boundary depending on velocity.
- startBounceAfterEdge(start, edge, velocity);
- } else {
- final double totalDistance = getSplineFlingDistance(velocity);
- if (totalDistance > Math.abs(overDistance)) {
- fling(start, velocity, positive ? min : start, positive ? start : max, mOver);
- } else {
- startSpringback(start, edge, velocity);
- }
- }
- }
-
- void notifyEdgeReached(int start, int end, int over) {
- // mState is used to detect successive notifications
- if (mState == SPLINE) {
- mOver = over;
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- // We were in fling/scroll mode before: current velocity is such that distance to
- // edge is increasing. This ensures that startAfterEdge will not start a new fling.
- startAfterEdge(start, end, end, (int) mCurrVelocity);
- }
- }
-
- private void onEdgeReached() {
- // mStart, mVelocity and mStartTime were adjusted to their values when edge was reached.
- // The float cast below is necessary to avoid integer overflow.
- final float velocitySquared = (float) mVelocity * mVelocity;
- float distance = velocitySquared / (2.0f * Math.abs(mDeceleration));
- final float sign = Math.signum(mVelocity);
-
- if (distance > mOver) {
- // Default deceleration is not sufficient to slow us down before boundary
- mDeceleration = - sign * velocitySquared / (2.0f * mOver);
- distance = mOver;
- }
-
- mOver = (int) distance;
- mState = BALLISTIC;
- mFinal = mStart + (int) (mVelocity > 0 ? distance : -distance);
- mDuration = - (int) (1000.0f * mVelocity / mDeceleration);
- }
-
- boolean continueWhenFinished() {
- switch (mState) {
- case SPLINE:
- // Duration from start to null velocity
- if (mDuration < mSplineDuration) {
- // If the animation was clamped, we reached the edge
- mCurrentPosition = mStart = mFinal;
- // TODO Better compute speed when edge was reached
- mVelocity = (int) mCurrVelocity;
- mDeceleration = getDeceleration(mVelocity);
- mStartTime += mDuration;
- onEdgeReached();
- } else {
- // Normal stop, no need to continue
- return false;
- }
- break;
- case BALLISTIC:
- mStartTime += mDuration;
- startSpringback(mFinal, mStart, 0);
- break;
- case CUBIC:
- return false;
- }
-
- update();
- return true;
- }
-
- /*
- * Update the current position and velocity for current time. Returns
- * true if update has been done and false if animation duration has been
- * reached.
- */
- boolean update() {
- if (mState == SPRING) {
- return mFinished;
- }
-
- final long time = AnimationUtils.currentAnimationTimeMillis();
- final long currentTime = time - mStartTime;
-
- if (currentTime == 0) {
- // Skip work but report that we're still going if we have a nonzero duration.
- return mDuration > 0;
- }
- if (currentTime > mDuration) {
- return false;
- }
-
- double distance = 0.0;
- switch (mState) {
- case SPLINE: {
- final float t = (float) currentTime / mSplineDuration;
- final int index = (int) (NB_SAMPLES * t);
- float distanceCoef = 1.f;
- float velocityCoef = 0.f;
- if (index < NB_SAMPLES) {
- final float t_inf = (float) index / NB_SAMPLES;
- final float t_sup = (float) (index + 1) / NB_SAMPLES;
- final float d_inf = SPLINE_POSITION[index];
- final float d_sup = SPLINE_POSITION[index + 1];
- velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
- distanceCoef = d_inf + (t - t_inf) * velocityCoef;
- }
-
- distance = distanceCoef * mSplineDistance;
- mCurrVelocity = velocityCoef * mSplineDistance / mSplineDuration * 1000.0f;
- break;
- }
-
- case BALLISTIC: {
- final float t = currentTime / 1000.0f;
- mCurrVelocity = mVelocity + mDeceleration * t;
- distance = mVelocity * t + mDeceleration * t * t / 2.0f;
- break;
- }
-
- case CUBIC: {
- final float t = (float) (currentTime) / mDuration;
- final float t2 = t * t;
- final float sign = Math.signum(mVelocity);
- distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2);
- mCurrVelocity = sign * mOver * 6.0f * (- t + t2);
- break;
- }
- }
-
- mCurrentPosition = mStart + (int) Math.round(distance);
-
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/OverlayEdgeEffect.java b/src/com/android/launcher3/util/OverlayEdgeEffect.java
new file mode 100644
index 0000000..8d455c6
--- /dev/null
+++ b/src/com/android/launcher3/util/OverlayEdgeEffect.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 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.launcher3.util;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.widget.EdgeEffect;
+
+import com.android.launcher3.Utilities;
+import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
+
+/**
+ * Extension of {@link EdgeEffect} which shows the Launcher overlay
+ */
+public class OverlayEdgeEffect extends EdgeEffectCompat {
+
+ private final LauncherOverlay mOverlay;
+ private final boolean mIsRtl;
+
+ private float mDistance;
+ private boolean mIsScrolling;
+
+ public OverlayEdgeEffect(Context context, LauncherOverlay overlay) {
+ super(context);
+ mOverlay = overlay;
+ mIsRtl = Utilities.isRtl(context.getResources());
+
+ }
+
+ @Override
+ public float getDistance() {
+ return mDistance;
+ }
+
+ public float onPullDistance(float deltaDistance, float displacement) {
+ mDistance = Math.max(0f, deltaDistance + mDistance);
+ if (!mIsScrolling) {
+ mOverlay.onScrollInteractionBegin();
+ mIsScrolling = true;
+ }
+ mOverlay.onScrollChange(mDistance, mIsRtl);
+ return mDistance > 0 ? deltaDistance : 0;
+ }
+
+ @Override
+ public void onAbsorb(int velocity) { }
+
+ @Override
+ public boolean isFinished() {
+ return mDistance <= 0;
+ }
+
+ @Override
+ public void onRelease() {
+ if (mIsScrolling) {
+ mDistance = 0;
+ mOverlay.onScrollInteractionEnd();
+ mIsScrolling = false;
+ }
+ }
+
+ @Override
+ public boolean draw(Canvas canvas) {
+ return false;
+ }
+
+ public void finish() {
+ mDistance = 0;
+ }
+}
diff --git a/src/com/android/launcher3/util/RunnableList.java b/src/com/android/launcher3/util/RunnableList.java
index 55add14..644537b 100644
--- a/src/com/android/launcher3/util/RunnableList.java
+++ b/src/com/android/launcher3/util/RunnableList.java
@@ -29,6 +29,9 @@
* Ads a runnable to this list
*/
public void add(Runnable runnable) {
+ if (runnable == null) {
+ return;
+ }
if (mDestroyed) {
runnable.run();
return;
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index 50166c3..630df7e 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -30,7 +30,7 @@
public static final int UI_STATE_BASE_WINDOW = 0;
public static final int UI_STATE_SCRIM_VIEW = 1;
public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
- public static final int UI_STATE_OVERVIEW = 3;
+ public static final int UI_STATE_FULLSCREEN_TASK = 3;
public static final int UI_STATE_ALLAPPS = 4;
public static final int FLAG_LIGHT_NAV = 1 << 0;
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index e8a0635..11b856e 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -16,6 +16,10 @@
package com.android.launcher3.util;
+import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_TEXT;
+import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
+
+import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -29,35 +33,40 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.GraphicsUtils;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
/**
* Various utility methods associated with theming.
*/
+@SuppressWarnings("NewApi")
public class Themes {
public static int getActivityThemeRes(Context context) {
- WallpaperColorInfo wallpaperColorInfo = WallpaperColorInfo.INSTANCE.get(context);
- boolean darkTheme;
- if (Utilities.ATLEAST_Q) {
- Configuration configuration = context.getResources().getConfiguration();
- int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
- darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
- } else {
- darkTheme = wallpaperColorInfo.isDark();
- }
+ int colorHints = Utilities.ATLEAST_P ? context.getSystemService(WallpaperManager.class)
+ .getWallpaperColors(WallpaperManager.FLAG_SYSTEM).getColorHints()
+ : 0;
+ return getActivityThemeRes(context, colorHints);
+ }
+
+ public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
+ Configuration configuration = context.getResources().getConfiguration();
+ int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ boolean darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
+
+ boolean supportsDarkText = Utilities.ATLEAST_S
+ && (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
+ boolean isMainColorDark = Utilities.ATLEAST_S
+ && (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
if (darkTheme) {
- return wallpaperColorInfo.supportsDarkText() ?
- R.style.AppTheme_Dark_DarkText : wallpaperColorInfo.isMainColorDark() ?
- R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
+ return supportsDarkText ? R.style.AppTheme_Dark_DarkText
+ : isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
} else {
- return wallpaperColorInfo.supportsDarkText() ?
- R.style.AppTheme_DarkText : wallpaperColorInfo.isMainColorDark() ?
- R.style.AppTheme_DarkMainColor : R.style.AppTheme;
+ return supportsDarkText ? R.style.AppTheme_DarkText
+ : isMainColorDark ? R.style.AppTheme_DarkMainColor : R.style.AppTheme;
}
}
+
public static String getDefaultBodyFont(Context context) {
TypedArray ta = context.obtainStyledAttributes(android.R.style.TextAppearance_DeviceDefault,
new int[]{android.R.attr.fontFamily});
diff --git a/src/com/android/launcher3/util/TranslateEdgeEffect.java b/src/com/android/launcher3/util/TranslateEdgeEffect.java
new file mode 100644
index 0000000..8fdc8df
--- /dev/null
+++ b/src/com/android/launcher3/util/TranslateEdgeEffect.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.launcher3.util;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.RenderNode;
+import android.widget.EdgeEffect;
+
+/**
+ * Extension of {@link EdgeEffect} which translates the content instead of the default
+ * platform implementation
+ */
+@SuppressWarnings("NewApi")
+public class TranslateEdgeEffect extends EdgeEffectCompat {
+
+ private final RenderNode mNode;
+
+ public TranslateEdgeEffect(Context context) {
+ super(context);
+ mNode = new RenderNode("TranslateEdgeEffect");
+ }
+
+ @Override
+ public boolean draw(Canvas canvas) {
+ return false;
+ }
+
+ public boolean getTranslationShift(float[] out) {
+ Canvas c = mNode.beginRecording(1, 1);
+ boolean result = super.draw(c);
+ mNode.endRecording();
+
+ out[0] = getDistance();
+ return result;
+ }
+}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 1939d15..01c0b56 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -23,11 +23,8 @@
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import android.annotation.TargetApi;
-import android.app.WallpaperInfo;
import android.app.WallpaperManager;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -42,15 +39,11 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.launcher3.util.TouchController;
import java.io.PrintWriter;
@@ -117,9 +110,6 @@
protected final T mActivity;
private final MultiValueAlpha mMultiValueAlpha;
private final WallpaperManager mWallpaperManager;
- private final SimpleBroadcastReceiver mWallpaperChangeReceiver =
- new SimpleBroadcastReceiver(this::onWallpaperChanged);
- private final String[] mWallpapersWithoutSysuiScrims;
// All the touch controllers for the view
protected TouchController[] mControllers;
@@ -130,15 +120,11 @@
private TouchCompleteListener mTouchCompleteListener;
- protected boolean mAllowSysuiScrims = true;
-
public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
super(context, attrs);
mActivity = (T) ActivityContext.lookupContext(context);
mMultiValueAlpha = new MultiValueAlpha(this, alphaChannelCount);
mWallpaperManager = context.getSystemService(WallpaperManager.class);
- mWallpapersWithoutSysuiScrims = getResources().getStringArray(
- R.array.live_wallpapers_remove_sysui_scrims);
}
/**
@@ -562,46 +548,4 @@
}
return super.dispatchApplyWindowInsets(insets);
}
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mWallpaperChangeReceiver.register(mActivity, Intent.ACTION_WALLPAPER_CHANGED);
- onWallpaperChanged(null);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mActivity.unregisterReceiver(mWallpaperChangeReceiver);
- }
-
- private void onWallpaperChanged(Intent unusedBroadcastIntent) {
- WallpaperInfo newWallpaperInfo = mWallpaperManager.getWallpaperInfo();
- boolean oldAllowSysuiScrims = mAllowSysuiScrims;
- mAllowSysuiScrims = computeAllowSysuiScrims(newWallpaperInfo);
- if (mAllowSysuiScrims != oldAllowSysuiScrims) {
- // Reapply insets so scrim can be removed or re-added if necessary.
- setInsets(mInsets);
- }
- }
-
- /**
- * Determines whether we can scrim the status bar and nav bar for the given wallpaper by
- * checking against a list of live wallpapers that we don't show the scrims on.
- */
- private boolean computeAllowSysuiScrims(@Nullable WallpaperInfo newWallpaperInfo) {
- if (newWallpaperInfo == null) {
- // Static wallpapers need scrim unless determined otherwise by wallpaperColors.
- return true;
- }
- ComponentName newWallpaper = newWallpaperInfo.getComponent();
- for (String wallpaperWithoutScrim : mWallpapersWithoutSysuiScrims) {
- if (newWallpaper.equals(ComponentName.unflattenFromString(wallpaperWithoutScrim))) {
- // New wallpaper does not need a scrim.
- return false;
- }
- }
- return true;
- }
}
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 4e82336..a66b3f9 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -15,10 +15,13 @@
*/
package com.android.launcher3.views;
+import static com.android.launcher3.Utilities.boundToRange;
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
+import static java.lang.Math.max;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -143,10 +146,9 @@
/**
* Update the icon UI to match the provided parameters during an animation frame
*/
- public void update(RectF rect, float progress, float shapeProgressStart,
- float cornerRadius, boolean isOpening, View container,
- DeviceProfile dp, boolean isVerticalBarLayout) {
-
+ public void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
+ int fgIconAlpha, boolean isOpening, View container, DeviceProfile dp,
+ boolean isVerticalBarLayout) {
MarginLayoutParams lp = (MarginLayoutParams) container.getLayoutParams();
float dX = mIsRtl
@@ -166,7 +168,7 @@
return;
}
- update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
+ update(rect, progress, shapeProgressStart, cornerRadius, fgIconAlpha, isOpening, scale,
minSize, lp, isVerticalBarLayout, dp);
container.setPivotX(0);
@@ -178,8 +180,8 @@
}
private void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
- boolean isOpening, float scale, float minSize, MarginLayoutParams parentLp,
- boolean isVerticalBarLayout, DeviceProfile dp) {
+ int fgIconAlpha, boolean isOpening, float scale, float minSize,
+ MarginLayoutParams parentLp, boolean isVerticalBarLayout, DeviceProfile dp) {
float dX = mIsRtl
? rect.left - (dp.widthPx - parentLp.getMarginStart() - parentLp.width)
: rect.left - parentLp.getMarginStart();
@@ -187,9 +189,9 @@
// shapeRevealProgress = 1 when progress = shapeProgressStart + SHAPE_PROGRESS_DURATION
float toMax = isOpening ? 1 / SHAPE_PROGRESS_DURATION : 1f;
- float shapeRevealProgress = Utilities.boundToRange(mapToRange(
- Math.max(shapeProgressStart, progress), shapeProgressStart, 1f, 0, toMax,
- LINEAR), 0, 1);
+
+ float shapeRevealProgress = boundToRange(mapToRange(max(shapeProgressStart, progress),
+ shapeProgressStart, 1f, 0, toMax, LINEAR), 0, 1);
if (isVerticalBarLayout) {
mOutline.right = (int) (rect.width() / scale);
@@ -231,6 +233,8 @@
sTmpRect.offset(diffX, diffY);
mForeground.setBounds(sTmpRect);
} else {
+ mForeground.setAlpha(fgIconAlpha);
+
// Spring the foreground relative to the icon's movement within the DragLayer.
int diffX = (int) (dX / dp.availableWidthPx * FG_TRANS_X_FACTOR);
int diffY = (int) (dY / dp.availableHeightPx * FG_TRANS_Y_FACTOR);
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 96268ce..d49320b 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -100,6 +100,8 @@
private ListenerView mListenerView;
private Runnable mFastFinishRunnable;
+ private float mIconOffsetY;
+
public FloatingIconView(Context context) {
this(context, null);
}
@@ -136,16 +138,18 @@
/**
* Positions this view to match the size and location of {@param rect}.
- * @param alpha The alpha to set this view.
+ * @param alpha The alpha[0, 1] of the entire floating view.
+ * @param fgIconAlpha The alpha[0-255] of the foreground layer of the icon (if applicable).
* @param progress A value from [0, 1] that represents the animation progress.
* @param shapeProgressStart The progress value at which to start the shape reveal.
* @param cornerRadius The corner radius of {@param rect}.
+ * @param isOpening True if view is used for app open animation, false for app close animation.
*/
- public void update(RectF rect, float alpha, float progress, float shapeProgressStart,
- float cornerRadius, boolean isOpening) {
+ public void update(float alpha, int fgIconAlpha, RectF rect, float progress,
+ float shapeProgressStart, float cornerRadius, boolean isOpening) {
setAlpha(alpha);
- mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening,
- this, mLauncher.getDeviceProfile(), mIsVerticalBarLayout);
+ mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, fgIconAlpha,
+ isOpening, this, mLauncher.getDeviceProfile(), mIsVerticalBarLayout);
}
@Override
@@ -478,11 +482,19 @@
@Override
public void onAnimationRepeat(Animator animator) {}
+ /**
+ * Offsets and updates the position of this view by {@param y}.
+ */
+ public void setPositionOffsetY(float y) {
+ mIconOffsetY = y;
+ onGlobalLayout();
+ }
+
@Override
public void onGlobalLayout() {
- if (mOriginalIcon.isAttachedToWindow() && mPositionOut != null) {
- getLocationBoundsForView(mLauncher, mOriginalIcon, mIsOpening,
- sTmpRectF);
+ if (mOriginalIcon != null && mOriginalIcon.isAttachedToWindow() && mPositionOut != null) {
+ getLocationBoundsForView(mLauncher, mOriginalIcon, mIsOpening, sTmpRectF);
+ sTmpRectF.offset(0, mIconOffsetY);
if (!sTmpRectF.equals(mPositionOut)) {
updatePosition(sTmpRectF, (InsettableFrameLayout.LayoutParams) getLayoutParams());
if (mOnTargetChangeRunnable != null) {
@@ -617,6 +629,7 @@
mClipIconView.recycle();
mBtvDrawable.setBackground(null);
mFastFinishRunnable = null;
+ mIconOffsetY = 0;
}
private static class IconLoadResult {
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 011f6de..e2e3be7 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -97,7 +97,7 @@
// Remove after some time, to avoid flickering
Executors.MAIN_EXECUTOR.getHandler().postDelayed(mRemoveViewRunnable,
- DisplayController.getDefaultDisplay(mLauncher).getInfo().singleFrameMs);
+ DisplayController.INSTANCE.get(mLauncher).getInfo().singleFrameMs);
}
private void removeViewFromParent() {
@@ -158,7 +158,7 @@
if (mContract == null) {
return;
}
- View icon = mLauncher.getWorkspace().getFirstMatchForAppClose(
+ View icon = mLauncher.getWorkspace().getFirstMatchForAppClose(-1,
mContract.componentName.getPackageName(), mContract.user);
boolean iconChanged = mIcon != icon;
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index c9424de..5387a3e 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -19,16 +19,15 @@
import android.content.Context;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import androidx.core.graphics.ColorUtils;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
import com.android.launcher3.util.SystemUiController;
-import com.android.launcher3.util.Themes;
/**
* Simple scrim which draws a flat color
@@ -36,13 +35,10 @@
public class ScrimView extends View implements Insettable {
private static final float STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.9f;
- private final boolean mIsScrimDark;
private SystemUiController mSystemUiController;
public ScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
- mIsScrimDark = ColorUtils.calculateLuminance(
- Themes.getAttrColor(context, R.attr.allAppsScrimColor)) < 0.5f;
setFocusable(false);
}
@@ -61,6 +57,12 @@
}
@Override
+ public void setBackgroundColor(int color) {
+ updateSysUiColors();
+ super.setBackgroundColor(color);
+ }
+
+ @Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
updateSysUiColors();
@@ -72,7 +74,7 @@
boolean forceChange =
getVisibility() == VISIBLE && getAlpha() > STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD;
if (forceChange) {
- getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !mIsScrimDark);
+ getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !isScrimDark());
} else {
getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0);
}
@@ -80,8 +82,18 @@
private SystemUiController getSystemUiController() {
if (mSystemUiController == null) {
- mSystemUiController = Launcher.getLauncher(getContext()).getSystemUiController();
+ mSystemUiController = BaseActivity.fromContext(getContext()).getSystemUiController();
}
return mSystemUiController;
}
+
+ private boolean isScrimDark() {
+ if (!(getBackground() instanceof ColorDrawable)) {
+ throw new IllegalStateException(
+ "ScrimView must have a ColorDrawable background, this one has: "
+ + getBackground());
+ }
+ return ColorUtils.calculateLuminance(
+ ((ColorDrawable) getBackground()).getColor()) < 0.5f;
+ }
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 95b887c..a7ecb07 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -35,7 +35,6 @@
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemLongClickListener;
-import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
@@ -56,9 +55,8 @@
}
protected int getScrimColor(Context context) {
- WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
- return setColorAlphaBound(colors.getSecondaryColor(), alpha);
+ return setColorAlphaBound(context.getColor(R.color.wallpaper_popup_scrim), alpha);
}
@Override
@@ -114,7 +112,7 @@
}
PendingItemDragHelper dragHelper = new PendingItemDragHelper(v);
- dragHelper.setRemoteViewsPreview(v.getPreview());
+ dragHelper.setRemoteViewsPreview(v.getRemoteViewsPreview());
dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview());
if (image.getDrawable() != null) {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 0d53f20..620604a 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -72,6 +72,8 @@
// Maintains a list of widget ids which are supposed to be auto advanced.
private static final SparseBooleanArray sAutoAdvanceWidgetIds = new SparseBooleanArray();
+ // Maximum duration for which updates can be deferred.
+ private static final long UPDATE_LOCK_TIMEOUT_MILLIS = 1000;
protected final LayoutInflater mInflater;
@@ -110,6 +112,9 @@
}
}
};
+ private final Object mUpdateLock = new Object();
+ private long mDeferUpdatesUntilMillis = 0;
+ private RemoteViews mMostRecentRemoteViews;
public LauncherAppWidgetHostView(Context context) {
super(context);
@@ -165,6 +170,11 @@
@Override
public void updateAppWidget(RemoteViews remoteViews) {
+ synchronized (mUpdateLock) {
+ mMostRecentRemoteViews = remoteViews;
+ if (SystemClock.uptimeMillis() < mDeferUpdatesUntilMillis) return;
+ }
+
super.updateAppWidget(remoteViews);
// The provider info or the views might have changed.
@@ -198,6 +208,34 @@
return false;
}
+ /**
+ * Begin deferring the application of any {@link RemoteViews} updates made through
+ * {@link #updateAppWidget(RemoteViews)} until {@link #endDeferringUpdates()} has been called or
+ * the next {@link #updateAppWidget(RemoteViews)} call after {@link #UPDATE_LOCK_TIMEOUT_MILLIS}
+ * have elapsed.
+ */
+ public void beginDeferringUpdates() {
+ synchronized (mUpdateLock) {
+ mDeferUpdatesUntilMillis = SystemClock.uptimeMillis() + UPDATE_LOCK_TIMEOUT_MILLIS;
+ }
+ }
+
+ /**
+ * Stop deferring the application of {@link RemoteViews} updates made through
+ * {@link #updateAppWidget(RemoteViews)} and apply the most recently received update.
+ */
+ public void endDeferringUpdates() {
+ RemoteViews remoteViews;
+ synchronized (mUpdateLock) {
+ mDeferUpdatesUntilMillis = 0;
+ remoteViews = mMostRecentRemoteViews;
+ mMostRecentRemoteViews = null;
+ }
+ if (remoteViews != null) {
+ updateAppWidget(remoteViews);
+ }
+ }
+
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
DragLayer dragLayer = mLauncher.getDragLayer();
@@ -339,7 +377,7 @@
// The layout depends on the orientation.
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
int parentViewWidth = parentView == null ? 0 : parentView.getWidth();
- xOffset = screenHeight - mWorkspace.getPaddingRight() - parentViewWidth;
+ xOffset = screenWidth - mWorkspace.getPaddingRight() - parentViewWidth;
} else {
int parentViewPaddingLeft = parentView == null ? 0 : parentView.getPaddingLeft();
xOffset = mWorkspace.getPaddingLeft() + parentViewPaddingLeft;
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index e78d517..cea4de7 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -23,6 +23,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
+import android.view.View.MeasureSpec;
import android.widget.RemoteViews;
import androidx.annotation.Nullable;
@@ -33,7 +34,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
-import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.graphics.DragPreviewProvider;
@@ -54,7 +54,7 @@
private int[] mEstimatedCellSize;
@Nullable private RemoteViews mRemoteViewsPreview;
- @Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
+ @Nullable private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
private final float mEnforcedRoundedCornersForWidget;
public PendingItemDragHelper(View view) {
@@ -72,9 +72,9 @@
mRemoteViewsPreview = remoteViewsPreview;
}
- /** Sets a {@link LauncherAppWidgetHostView} which shows a preview layout of an app widget. */
+ /** Sets a {@link NavigableAppWidgetHostView} which shows a preview layout of an app widget. */
public void setAppWidgetHostViewPreview(
- @Nullable LauncherAppWidgetHostView appWidgetHostViewPreview) {
+ @Nullable NavigableAppWidgetHostView appWidgetHostViewPreview) {
mAppWidgetHostViewPreview = appWidgetHostViewPreview;
}
@@ -93,6 +93,8 @@
LauncherAppState app = LauncherAppState.getInstance(launcher);
Drawable preview = null;
+ final int previewWidth;
+ final int previewHeight;
final float scale;
final Point dragOffset;
final Rect dragRegion;
@@ -109,17 +111,29 @@
int[] previewSizeBeforeScale = new int[1];
if (mRemoteViewsPreview != null) {
- preview = new FastBitmapDrawable(
- WidgetCell.generateFromRemoteViews(launcher, mRemoteViewsPreview,
- createWidgetInfo.info, maxWidth, previewSizeBeforeScale));
+ mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(launcher);
+ mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1,
+ ((PendingAddWidgetInfo) mAddInfo).info);
+ DeviceProfile deviceProfile = launcher.getDeviceProfile();
+ Rect padding = new Rect();
+ mAppWidgetHostViewPreview.getWidgetInset(deviceProfile, padding);
+ mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
+ padding.bottom);
+ mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
+ int width =
+ deviceProfile.cellWidthPx * mAddInfo.spanX + padding.left + padding.right;
+ int height =
+ deviceProfile.cellHeightPx * mAddInfo.spanY + padding.top + padding.bottom;
+ mAppWidgetHostViewPreview.measure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
if (mAppWidgetHostViewPreview != null) {
- preview = new AppWidgetHostViewDrawable(mAppWidgetHostViewPreview);
previewSizeBeforeScale[0] = mAppWidgetHostViewPreview.getMeasuredWidth();
launcher.getDragController()
.addDragListener(new AppWidgetHostViewDragListener(launcher));
}
- if (preview == null) {
+ if (preview == null && mAppWidgetHostViewPreview == null) {
Drawable p = new FastBitmapDrawable(
app.getWidgetCache().generateWidgetPreview(launcher,
createWidgetInfo.info, maxWidth, null,
@@ -140,7 +154,14 @@
previewBounds.left += padding;
previewBounds.right -= padding;
}
- scale = previewBounds.width() / (float) preview.getIntrinsicWidth();
+ if (mAppWidgetHostViewPreview != null) {
+ previewWidth = mAppWidgetHostViewPreview.getMeasuredWidth();
+ previewHeight = mAppWidgetHostViewPreview.getMeasuredHeight();
+ } else {
+ previewWidth = preview.getIntrinsicWidth();
+ previewHeight = preview.getIntrinsicHeight();
+ }
+ scale = previewBounds.width() / (float) previewWidth;
launcher.getDragController().addDragListener(new WidgetHostViewLoader(launcher, mView));
dragOffset = null;
@@ -152,8 +173,10 @@
LauncherIcons li = LauncherIcons.obtain(launcher);
preview = new FastBitmapDrawable(
li.createScaledBitmapWithoutShadow(icon, 0));
+ previewWidth = preview.getIntrinsicWidth();
+ previewHeight = preview.getIntrinsicHeight();
li.recycle();
- scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getIntrinsicWidth();
+ scale = ((float) launcher.getDeviceProfile().iconSizePx) / previewWidth;
dragOffset = new Point(previewPadding / 2, previewPadding / 2);
@@ -181,13 +204,19 @@
launcher.getWorkspace().prepareDragWithProvider(this);
int dragLayerX = screenPos.x + previewBounds.left
- + (int) ((scale * preview.getIntrinsicWidth() - preview.getIntrinsicWidth()) / 2);
+ + (int) ((scale * previewWidth - previewWidth) / 2);
int dragLayerY = screenPos.y + previewBounds.top
- + (int) ((scale * preview.getIntrinsicHeight() - preview.getIntrinsicHeight()) / 2);
+ + (int) ((scale * previewHeight - previewHeight) / 2);
// Start the drag
- launcher.getDragController().startDrag(preview, draggableView, dragLayerX, dragLayerY,
- source, mAddInfo, dragOffset, dragRegion, scale, scale, options);
+ if (mAppWidgetHostViewPreview != null) {
+ launcher.getDragController().startDrag(mAppWidgetHostViewPreview, draggableView,
+ dragLayerX, dragLayerY, source, mAddInfo, dragOffset, dragRegion, scale, scale,
+ options);
+ } else {
+ launcher.getDragController().startDrag(preview, draggableView, dragLayerX, dragLayerY,
+ source, mAddInfo, dragOffset, dragRegion, scale, scale, options);
+ }
}
@Override
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index c08160b..3fcd3f7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -46,7 +46,6 @@
import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BaseIconFactory;
-import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.RoundDrawableWrapper;
import com.android.launcher3.model.WidgetItem;
@@ -100,8 +99,8 @@
private final CheckLongPressHelper mLongPressHelper;
private final float mEnforcedCornerRadius;
- private RemoteViews mPreview;
- private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
+ private RemoteViews mRemoteViewsPreview;
+ private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
public WidgetCell(Context context) {
this(context, null);
@@ -143,12 +142,13 @@
mWidgetDescription = findViewById(R.id.widget_description);
}
- public void setPreview(RemoteViews view) {
- mPreview = view;
+ public void setRemoteViewsPreview(RemoteViews view) {
+ mRemoteViewsPreview = view;
}
- public RemoteViews getPreview() {
- return mPreview;
+ @Nullable
+ public RemoteViews getRemoteViewsPreview() {
+ return mRemoteViewsPreview;
}
/**
@@ -172,7 +172,7 @@
mActiveRequest.cancel();
mActiveRequest = null;
}
- mPreview = null;
+ mRemoteViewsPreview = null;
if (mAppWidgetHostViewPreview != null) {
mWidgetImageContainer.removeView(mAppWidgetHostViewPreview);
}
@@ -180,7 +180,7 @@
}
public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) {
- applyPreviewLayout(item);
+ applyPreviewOnAppWidgetHostView(item);
mItem = item;
mWidgetName.setText(mItem.label);
@@ -206,9 +206,26 @@
}
}
- private void applyPreviewLayout(WidgetItem item) {
+
+ private void applyPreviewOnAppWidgetHostView(WidgetItem item) {
+ if (mRemoteViewsPreview != null) {
+ mAppWidgetHostViewPreview = new NavigableAppWidgetHostView(getContext()) {
+ @Override
+ protected boolean shouldAllowDirectClick() {
+ return false;
+ }
+ };
+ mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, item.widgetInfo);
+ Rect padding = new Rect();
+ mAppWidgetHostViewPreview.getWidgetInset(mActivity.getDeviceProfile(), padding);
+ mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
+ padding.bottom);
+ mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
+ return;
+ }
+
if (ATLEAST_S
- && mPreview == null
+ && mRemoteViewsPreview == null
&& item.widgetInfo != null
&& item.widgetInfo.previewLayout != Resources.ID_NULL) {
mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(getContext());
@@ -234,7 +251,7 @@
}
@Nullable
- public LauncherAppWidgetHostView getAppWidgetHostViewPreview() {
+ public NavigableAppWidgetHostView getAppWidgetHostViewPreview() {
return mAppWidgetHostViewPreview;
}
@@ -303,15 +320,6 @@
}
public void ensurePreview() {
- if (mPreview != null && mActiveRequest == null) {
- Bitmap preview = generateFromRemoteViews(
- mActivity, mPreview, mItem.widgetInfo, mPresetPreviewSize, new int[1]);
- if (preview != null) {
- applyPreview(new FastBitmapDrawable(preview));
- return;
- }
- }
-
if (mAppWidgetHostViewPreview != null) {
setContainerSize(mPreviewWidth, mPreviewHeight);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
@@ -385,53 +393,4 @@
super.onInitializeAccessibilityNodeInfo(info);
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
}
-
- /**
- * Generates a bitmap by inflating {@param views}.
- * @see com.android.launcher3.WidgetPreviewLoader#generateWidgetPreview
- *
- * TODO: Consider moving this to the background thread.
- */
- public static Bitmap generateFromRemoteViews(BaseActivity activity, RemoteViews views,
- LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
- try {
- return generateFromView(activity, views.apply(activity, new FrameLayout(activity)),
- info, previewSize, preScaledWidthOut);
- } catch (Exception e) {
- return null;
- }
- }
-
- private static Bitmap generateFromView(BaseActivity activity, View v,
- LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
-
- DeviceProfile dp = activity.getDeviceProfile();
- int viewWidth = dp.cellWidthPx * info.spanX;
- int viewHeight = dp.cellHeightPx * info.spanY;
-
- v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY));
-
- viewWidth = v.getMeasuredWidth();
- viewHeight = v.getMeasuredHeight();
- v.layout(0, 0, viewWidth, viewHeight);
-
- preScaledWidthOut[0] = viewWidth;
- final int bitmapWidth, bitmapHeight;
- final float scale;
- if (viewWidth > previewSize) {
- scale = ((float) previewSize) / viewWidth;
- bitmapWidth = previewSize;
- bitmapHeight = (int) (viewHeight * scale);
- } else {
- scale = 1;
- bitmapWidth = viewWidth;
- bitmapHeight = viewHeight;
- }
-
- return BitmapRenderer.createSoftwareBitmap(bitmapWidth, bitmapHeight, c -> {
- c.scale(scale, scale);
- v.draw(c);
- });
- }
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 155a285..f18b63e 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -20,6 +20,7 @@
import android.animation.PropertyValuesHolder;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.IntProperty;
@@ -71,6 +72,7 @@
private Rect mInsets;
private final int mMaxTableHeight;
private int mMaxHorizontalSpan = 4;
+ private Configuration mCurrentConfiguration;
public WidgetsBottomSheet(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -85,6 +87,7 @@
// Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
// take over the entire view vertically.
mMaxTableHeight = deviceProfile.inv.numRows * 2 / 3 * deviceProfile.cellHeightPx;
+ mCurrentConfiguration = new Configuration(getResources().getConfiguration());
}
@Override
@@ -212,6 +215,14 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ if (mCurrentConfiguration.orientation != newConfig.orientation) {
+ mInsets.setEmpty();
+ }
+ mCurrentConfiguration.updateFrom(newConfig);
+ }
+
+ @Override
protected Pair<View, String> getAccessibilityTarget() {
return Pair.create(findViewById(R.id.title), getContext().getString(
mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
diff --git a/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java b/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java
index 66bb363..4a60983 100644
--- a/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java
+++ b/src/com/android/launcher3/widget/dragndrop/AppWidgetHostViewDragListener.java
@@ -17,7 +17,6 @@
import com.android.launcher3.DropTarget;
import com.android.launcher3.Launcher;
-import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -26,7 +25,6 @@
public final class AppWidgetHostViewDragListener implements DragController.DragListener {
private final Launcher mLauncher;
private DropTarget.DragObject mDragObject;
- private AppWidgetHostViewDrawable mAppWidgetHostViewDrawable;
private LauncherAppWidgetHostView mAppWidgetHostView;
public AppWidgetHostViewDragListener(Launcher launcher) {
@@ -35,11 +33,9 @@
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions unused) {
- if (dragObject.dragView.getDrawable() instanceof AppWidgetHostViewDrawable) {
+ if (dragObject.dragView.getContentView() instanceof LauncherAppWidgetHostView) {
mDragObject = dragObject;
- mAppWidgetHostViewDrawable =
- (AppWidgetHostViewDrawable) mDragObject.dragView.getDrawable();
- mAppWidgetHostView = mAppWidgetHostViewDrawable.getAppWidgetHostView();
+ mAppWidgetHostView = (LauncherAppWidgetHostView) dragObject.dragView.getContentView();
mAppWidgetHostView.startDrag(this);
} else {
mLauncher.getDragController().removeDragListener(this);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java b/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
index 2366609..42896ba 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
@@ -181,8 +181,8 @@
}
if (newRow instanceof WidgetsListSearchHeaderEntry
&& curRow instanceof WidgetsListSearchHeaderEntry) {
- return ((WidgetsListSearchHeaderEntry) newRow).hasEntryUpdated()
- || !curRow.equals(newRow);
+ // Always refresh search header entries to reset rounded corners in their view holder.
+ return true;
}
return false;
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 2bba316..8f5d4dc 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -50,6 +50,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.model.WidgetItem;
@@ -220,7 +221,7 @@
WidgetsRecyclerView currentRecyclerView =
mAdapters.get(currentActivePage).mWidgetsRecyclerView;
- updateNoWidgetsView(currentAdapterHolder);
+ updateRecyclerViewVisibility(currentAdapterHolder);
attachScrollbarToRecyclerView(currentRecyclerView);
resetExpandedHeaders();
}
@@ -231,22 +232,17 @@
reset();
}
- private void updateNoWidgetsView(AdapterHolder adapterHolder) {
+ private void updateRecyclerViewVisibility(AdapterHolder adapterHolder) {
boolean isWidgetAvailable = adapterHolder.mWidgetsListAdapter.getItemCount() > 0;
adapterHolder.mWidgetsRecyclerView.setVisibility(isWidgetAvailable ? VISIBLE : GONE);
- // Always resets the text in case this is updated by search.
- mNoWidgetsView.setText(R.string.no_widgets_available);
+ mNoWidgetsView.setText(
+ adapterHolder.mAdapterType == AdapterHolder.SEARCH
+ ? R.string.no_search_results
+ : R.string.no_widgets_available);
mNoWidgetsView.setVisibility(isWidgetAvailable ? GONE : VISIBLE);
}
- private void updateNoSearchResultsView(boolean isVisible) {
- mNoWidgetsView.setVisibility(isVisible ? VISIBLE : GONE);
- if (isVisible) {
- mNoWidgetsView.setText(R.string.no_search_results);
- }
- }
-
private void reset() {
mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView.scrollToTop();
if (mHasWorkProfile) {
@@ -278,6 +274,7 @@
super.onAttachedToWindow();
mLauncher.getAppWidgetHost().addProviderChangeListener(this);
notifyWidgetProvidersChanged();
+ onRecommendedWidgetsBound();
}
@Override
@@ -392,16 +389,22 @@
@Override
public void onWidgetsBound() {
+ if (mIsInSearchMode) {
+ return;
+ }
List<WidgetsListBaseEntry> allWidgets = mLauncher.getPopupDataProvider().getAllWidgets();
AdapterHolder primaryUserAdapterHolder = mAdapters.get(AdapterHolder.PRIMARY);
primaryUserAdapterHolder.mWidgetsListAdapter.setWidgets(allWidgets);
- updateNoWidgetsView(primaryUserAdapterHolder);
if (mHasWorkProfile) {
+ mViewPager.setVisibility(VISIBLE);
+ mTabsView.setVisibility(VISIBLE);
AdapterHolder workUserAdapterHolder = mAdapters.get(AdapterHolder.WORK);
workUserAdapterHolder.mWidgetsListAdapter.setWidgets(allWidgets);
onActivePageChanged(mViewPager.getCurrentPage());
+ } else {
+ updateRecyclerViewVisibility(primaryUserAdapterHolder);
}
}
@@ -415,6 +418,7 @@
@Override
public void exitSearchMode() {
+ if (!mIsInSearchMode) return;
onSearchResults(new ArrayList<>());
setViewVisibilityBasedOnSearch(/*isInSearchMode=*/ false);
if (mHasWorkProfile) {
@@ -428,25 +432,30 @@
@Override
public void onSearchResults(List<WidgetsListBaseEntry> entries) {
mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setWidgetsOnSearch(entries);
- updateNoSearchResultsView(
- mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.getItemCount() == 0);
+ updateRecyclerViewVisibility(mAdapters.get(AdapterHolder.SEARCH));
mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView.scrollToTop();
}
private void setViewVisibilityBasedOnSearch(boolean isInSearchMode) {
mIsInSearchMode = isInSearchMode;
- mSearchAndRecommendationViewHolder.mRecommendedWidgetsTable
- .setVisibility(isInSearchMode ? GONE : VISIBLE);
- if (mHasWorkProfile) {
- mViewPager.setVisibility(isInSearchMode ? GONE : VISIBLE);
- mTabsView.setVisibility(isInSearchMode ? GONE : VISIBLE);
+ if (isInSearchMode) {
+ mSearchAndRecommendationViewHolder.mRecommendedWidgetsTable.setVisibility(GONE);
+ if (mHasWorkProfile) {
+ mViewPager.setVisibility(GONE);
+ mTabsView.setVisibility(GONE);
+ } else {
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView.setVisibility(GONE);
+ }
+ updateRecyclerViewVisibility(mAdapters.get(AdapterHolder.SEARCH));
+ // Hide no search results view to prevent it from flashing on enter search.
+ mNoWidgetsView.setVisibility(GONE);
} else {
- mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView
- .setVisibility(isInSearchMode ? GONE : VISIBLE);
+ mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView.setVisibility(GONE);
+ // Visibility of recommended widgets, recycler views and headers are handled in methods
+ // below.
+ onRecommendedWidgetsBound();
+ onWidgetsBound();
}
- mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView
- .setVisibility(mIsInSearchMode ? VISIBLE : GONE);
- mNoWidgetsView.setVisibility(GONE);
}
private void resetExpandedHeaders() {
@@ -456,6 +465,9 @@
@Override
public void onRecommendedWidgetsBound() {
+ if (mIsInSearchMode) {
+ return;
+ }
List<WidgetItem> recommendedWidgets =
mLauncher.getPopupDataProvider().getRecommendedWidgets();
WidgetsRecommendationTableLayout table =
@@ -466,8 +478,8 @@
Log.d(TAG, "Header view height is 0 when inflating recommended widgets");
}
float maxTableHeight =
- (mLauncher.getDeviceProfile().heightPx - mTabsHeight - getHeaderViewHeight())
- * RECOMMENDATION_TABLE_HEIGHT_RATIO;
+ (mLauncher.getDeviceProfile().availableHeightPx - mTabsHeight
+ - getHeaderViewHeight()) * RECOMMENDATION_TABLE_HEIGHT_RATIO;
List<ArrayList<WidgetItem>> recommendedWidgetsInTable =
WidgetsTableUtils.groupWidgetItemsIntoTable(recommendedWidgets,
mMaxSpansPerRow);
@@ -646,7 +658,8 @@
}
private boolean hasSeenEducationTip() {
- return mLauncher.getSharedPrefs().getBoolean(WIDGETS_EDUCATION_TIP_SEEN, false);
+ return mLauncher.getSharedPrefs().getBoolean(WIDGETS_EDUCATION_TIP_SEEN, false)
+ || Utilities.IS_RUNNING_IN_TEST_HARNESS;
}
/** A holder class for holding adapters & their corresponding recycler view. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index d9c9d4d..0504e74 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -186,8 +186,10 @@
* Resets any expanded widget header.
*/
public void resetExpandedHeader() {
- mWidgetsContentVisiblePackageUserKey = null;
- updateVisibleEntries();
+ if (mWidgetsContentVisiblePackageUserKey != null) {
+ mWidgetsContentVisiblePackageUserKey = null;
+ updateVisibleEntries();
+ }
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index 8794a4a..ccf3187 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -19,7 +19,10 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -94,6 +97,32 @@
mTitle = findViewById(R.id.app_title);
mSubtitle = findViewById(R.id.app_subtitle);
mExpandToggle = findViewById(R.id.toggle);
+ findViewById(R.id.app_container).setAccessibilityDelegate(new AccessibilityDelegate() {
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ if (mIsExpanded) {
+ info.removeAction(AccessibilityNodeInfo.ACTION_EXPAND);
+ info.addAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
+ } else {
+ info.removeAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
+ info.addAction(AccessibilityNodeInfo.ACTION_EXPAND);
+ }
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_EXPAND:
+ case AccessibilityNodeInfo.ACTION_COLLAPSE:
+ callOnClick();
+ return true;
+ default:
+ return super.performAccessibilityAction(host, action, args);
+ }
+ }
+ });
}
/**
@@ -106,7 +135,9 @@
// Use the entire touch area of this view to expand / collapse an app widgets section.
setOnClickListener(view -> {
setExpanded(!mIsExpanded);
- onExpandChangeListener.onExpansionChange(mIsExpanded);
+ if (onExpandChangeListener != null) {
+ onExpandChangeListener.onExpansionChange(mIsExpanded);
+ }
});
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 1bfffc2..2d3f1a0 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -42,8 +42,9 @@
private static final String TAG = "WidgetsRecommendationTableLayout";
private static final float DOWN_SCALE_RATIO = 0.9f;
private static final float MAX_DOWN_SCALE_RATIO = 0.5f;
- private final DeviceProfile mDeviceProfile;
+ private final float mWidgetsRecommendationTableVerticalPadding;
private final float mWidgetCellTextViewsHeight;
+ private final float mWidgetPreviewPadding;
private float mRecommendationTableMaxHeight = Float.MAX_VALUE;
@Nullable private OnLongClickListener mWidgetCellOnLongClickListener;
@@ -56,9 +57,12 @@
public WidgetsRecommendationTableLayout(Context context, AttributeSet attrs) {
super(context, attrs);
- mDeviceProfile = Launcher.getLauncher(context).getDeviceProfile();
// There are 1 row for title, 1 row for dimension and 2 rows for description.
+ mWidgetsRecommendationTableVerticalPadding = 2 * getResources()
+ .getDimensionPixelSize(R.dimen.widget_cell_vertical_padding);
mWidgetCellTextViewsHeight = 4 * getResources().getDimension(R.dimen.widget_cell_font_size);
+ mWidgetPreviewPadding = 2 * getResources()
+ .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
}
/** Sets a {@link android.view.View.OnLongClickListener} for all widget cells in this table. */
@@ -142,13 +146,14 @@
return new RecommendationTableData(List.of(), previewScale);
}
// A naive estimation of the widgets recommendation table height without inflation.
- float totalHeight = 0;
+ float totalHeight = mWidgetsRecommendationTableVerticalPadding;
+ DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
for (int i = 0; i < recommendedWidgetsInTable.size(); i++) {
List<WidgetItem> widgetItems = recommendedWidgetsInTable.get(i);
float rowHeight = 0;
for (int j = 0; j < widgetItems.size(); j++) {
- float previewHeight = widgetItems.get(j).spanY * mDeviceProfile.allAppsCellHeightPx
- * previewScale;
+ float previewHeight = widgetItems.get(j).spanY * deviceProfile.cellHeightPx
+ * previewScale + mWidgetPreviewPadding;
rowHeight = Math.max(rowHeight, previewHeight + mWidgetCellTextViewsHeight);
}
totalHeight += rowHeight;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index 69672f2..eb821d4 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -116,6 +116,7 @@
public void onUpdateScrollbar(int dy) {
// Skip early if widgets are not bound.
if (isModelNotReady()) {
+ mScrollbar.setThumbOffsetY(-1);
return;
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/WallpaperColorInfo.java b/src_ui_overrides/com/android/launcher3/uioverrides/WallpaperColorInfo.java
deleted file mode 100644
index b3aa365..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/WallpaperColorInfo.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 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.launcher3.uioverrides;
-
-import static android.app.WallpaperManager.FLAG_SYSTEM;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.util.Pair;
-
-import com.android.launcher3.uioverrides.dynamicui.ColorExtractionAlgorithm;
-import com.android.launcher3.uioverrides.dynamicui.WallpaperColorsCompat;
-import com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompat;
-import com.android.launcher3.util.MainThreadInitializedObject;
-
-import java.util.ArrayList;
-
-public class WallpaperColorInfo implements WallpaperManagerCompat.OnColorsChangedListenerCompat {
-
- private static final int MAIN_COLOR_LIGHT = 0xffdadce0;
- private static final int MAIN_COLOR_DARK = 0xff202124;
- private static final int MAIN_COLOR_REGULAR = 0xff000000;
-
- private static final int FALLBACK_COLOR = Color.WHITE;
-
- public static final MainThreadInitializedObject<WallpaperColorInfo> INSTANCE =
- new MainThreadInitializedObject<>(WallpaperColorInfo::new);
-
- private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
- private final WallpaperManagerCompat mWallpaperManager;
- private final ColorExtractionAlgorithm mExtractionType;
- private int mMainColor;
- private int mSecondaryColor;
- private boolean mIsDark;
- private boolean mSupportsDarkText;
-
- private OnChangeListener[] mTempListeners;
-
- private WallpaperColorInfo(Context context) {
- mWallpaperManager = WallpaperManagerCompat.getInstance(context);
- mWallpaperManager.addOnColorsChangedListener(this);
- mExtractionType = new ColorExtractionAlgorithm();
- update(mWallpaperManager.getWallpaperColors(FLAG_SYSTEM));
- }
-
- public int getMainColor() {
- return mMainColor;
- }
-
- public int getSecondaryColor() {
- return mSecondaryColor;
- }
-
- public boolean isDark() {
- return mIsDark;
- }
-
- public boolean supportsDarkText() {
- return mSupportsDarkText;
- }
-
- public boolean isMainColorDark() {
- return mMainColor == MAIN_COLOR_DARK;
- }
-
- @Override
- public void onColorsChanged(WallpaperColorsCompat colors, int which) {
- if ((which & FLAG_SYSTEM) != 0) {
- update(colors);
- notifyChange();
- }
- }
-
- private void update(WallpaperColorsCompat wallpaperColors) {
- Pair<Integer, Integer> colors = mExtractionType.extractInto(wallpaperColors);
- if (colors != null) {
- mMainColor = colors.first;
- mSecondaryColor = colors.second;
- } else {
- mMainColor = FALLBACK_COLOR;
- mSecondaryColor = FALLBACK_COLOR;
- }
- mSupportsDarkText = wallpaperColors != null
- ? (wallpaperColors.getColorHints()
- & WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT) > 0 : false;
- mIsDark = wallpaperColors != null
- ? (wallpaperColors.getColorHints()
- & WallpaperColorsCompat.HINT_SUPPORTS_DARK_THEME) > 0 : false;
- }
-
- public void addOnChangeListener(OnChangeListener listener) {
- mListeners.add(listener);
- }
-
- public void removeOnChangeListener(OnChangeListener listener) {
- mListeners.remove(listener);
- }
-
- private void notifyChange() {
- OnChangeListener[] copy =
- mTempListeners != null && mTempListeners.length == mListeners.size() ?
- mTempListeners : new OnChangeListener[mListeners.size()];
-
- // Create a new array to avoid concurrent modification when the activity destroys itself.
- mTempListeners = mListeners.toArray(copy);
- for (OnChangeListener listener : mTempListeners) {
- listener.onExtractedColorsChanged(this);
- }
- }
-
- public interface OnChangeListener {
- void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo);
- }
-}
\ No newline at end of file
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java
deleted file mode 100644
index 780a0f0..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright (C) 2017 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.launcher3.uioverrides.dynamicui;
-
-import android.graphics.Color;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Range;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.graphics.ColorUtils;
-
-import com.android.launcher3.Utilities;
-
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Implementation of tonal color extraction
- **/
-public class ColorExtractionAlgorithm {
-
- private static final String TAG = "Tonal";
-
- // Used for tonal palette fitting
- private static final float FIT_WEIGHT_H = 1.0f;
- private static final float FIT_WEIGHT_S = 1.0f;
- private static final float FIT_WEIGHT_L = 10.0f;
-
- public static final int MAIN_COLOR_LIGHT = 0xffb0b0b0;
- public static final int SECONDARY_COLOR_LIGHT = 0xff9e9e9e;
- public static final int MAIN_COLOR_DARK = 0xff212121;
- public static final int SECONDARY_COLOR_DARK = 0xff000000;
-
- // Temporary variable to avoid allocations
- private float[] mTmpHSL = new float[3];
-
- public Pair<Integer, Integer> extractInto(WallpaperColorsCompat inWallpaperColors) {
- if (inWallpaperColors == null) {
- return applyFallback(inWallpaperColors);
- }
-
- final List<Integer> mainColors = getMainColors(inWallpaperColors);
- final int mainColorsSize = mainColors.size();
- final boolean supportsDarkText = (inWallpaperColors.getColorHints() &
- WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT) != 0;
-
- if (mainColorsSize == 0) {
- return applyFallback(inWallpaperColors);
- }
- // Tonal is not really a sort, it takes a color from the extracted
- // palette and finds a best fit amongst a collection of pre-defined
- // palettes. The best fit is tweaked to be closer to the source color
- // and replaces the original palette
-
- // Get the most preeminent, non-disallowed color.
- Integer bestColor = 0;
- final float[] hsl = new float[3];
- for (int i = 0; i < mainColorsSize; i++) {
- final int colorValue = mainColors.get(i);
- ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
- Color.blue(colorValue), hsl);
-
- // Stop when we find a color that meets our criteria
- if (!isDisallowed(hsl)) {
- bestColor = colorValue;
- break;
- }
- }
-
- // Fail if not found
- if (bestColor == null) {
- return applyFallback(inWallpaperColors);
- }
-
- int colorValue = bestColor;
- ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
- hsl);
-
- // The Android HSL definition requires the hue to go from 0 to 360 but
- // the Material Tonal Palette defines hues from 0 to 1.
- hsl[0] /= 360f;
-
- // Find the palette that contains the closest color
- TonalPalette palette = findTonalPalette(hsl[0], hsl[1]);
- if (palette == null) {
- Log.w(TAG, "Could not find a tonal palette!");
- return applyFallback(inWallpaperColors);
- }
-
- // Figure out what's the main color index in the optimal palette
- int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]);
- if (fitIndex == -1) {
- Log.w(TAG, "Could not find best fit!");
- return applyFallback(inWallpaperColors);
- }
-
- // Generate the 10 colors palette by offsetting each one of them
- float[] h = fit(palette.h, hsl[0], fitIndex,
- Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
- float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
- float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
-
- int primaryIndex = fitIndex;
- int mainColor = getColorInt(primaryIndex, h, s, l);
-
- // We might want use the fallback in case the extracted color is brighter than our
- // light fallback or darker than our dark fallback.
- ColorUtils.colorToHSL(mainColor, mTmpHSL);
- final float mainLuminosity = mTmpHSL[2];
- ColorUtils.colorToHSL(MAIN_COLOR_LIGHT, mTmpHSL);
- final float lightLuminosity = mTmpHSL[2];
- if (mainLuminosity > lightLuminosity) {
- return applyFallback(inWallpaperColors);
- }
- ColorUtils.colorToHSL(MAIN_COLOR_DARK, mTmpHSL);
- final float darkLuminosity = mTmpHSL[2];
- if (mainLuminosity < darkLuminosity) {
- return applyFallback(inWallpaperColors);
- }
-
- // Dark colors:
- // Stops at 4th color, only lighter if dark text is supported
- if (supportsDarkText) {
- primaryIndex = h.length - 1;
- } else if (fitIndex < 2) {
- primaryIndex = 0;
- } else {
- primaryIndex = Math.min(fitIndex, 3);
- }
- int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
- int secondaryColor = getColorInt(secondaryIndex, h, s, l);
-
- return new Pair<>(mainColor, secondaryColor);
- }
-
- public static Pair<Integer, Integer> applyFallback(WallpaperColorsCompat inWallpaperColors) {
- boolean light = inWallpaperColors != null
- && (inWallpaperColors.getColorHints()
- & WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT)!= 0;
- int innerColor = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
- int outerColor = light ? SECONDARY_COLOR_LIGHT : SECONDARY_COLOR_DARK;
- return new Pair<>(innerColor, outerColor);
- }
-
- private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) {
- mTmpHSL[0] = fract(h[fitIndex]) * 360.0f;
- mTmpHSL[1] = s[fitIndex];
- mTmpHSL[2] = l[fitIndex];
- return ColorUtils.HSLToColor(mTmpHSL);
- }
-
- /**
- * Checks if a given color exists in the disallowed_colors list.
- * @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
- * @return true if color should be avoided
- */
- private boolean isDisallowed(float[] hsl) {
- for (ColorRange badRange: DISALLOWED_COLORS) {
- if (badRange.containsColor(hsl[0], hsl[1], hsl[2])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Offsets all colors by a delta, clamping values that go beyond what's
- * supported on the color space.
- * @param data what you want to fit
- * @param v how big should be the offset
- * @param index which index to calculate the delta against
- * @param min minimum accepted value (clamp)
- * @param max maximum accepted value (clamp)
- * @return new shifted palette
- */
- private static float[] fit(float[] data, float v, int index, float min, float max) {
- float[] fitData = new float[data.length];
- float delta = v - data[index];
-
- for (int i = 0; i < data.length; i++) {
- fitData[i] = Utilities.boundToRange(data[i] + delta, min, max);
- }
-
- return fitData;
- }
-
- /**
- * Finds the closest color in a palette, given another HSL color
- *
- * @param palette where to search
- * @param h hue
- * @param s saturation
- * @param l lightness
- * @return closest index or -1 if palette is empty.
- */
- private static int bestFit(@NonNull TonalPalette palette, float h, float s, float l) {
- int minErrorIndex = -1;
- float minError = Float.POSITIVE_INFINITY;
-
- for (int i = 0; i < palette.h.length; i++) {
- float error =
- FIT_WEIGHT_H * Math.abs(h - palette.h[i])
- + FIT_WEIGHT_S * Math.abs(s - palette.s[i])
- + FIT_WEIGHT_L * Math.abs(l - palette.l[i]);
- if (error < minError) {
- minError = error;
- minErrorIndex = i;
- }
- }
-
- return minErrorIndex;
- }
-
- @Nullable
- private static TonalPalette findTonalPalette(float h, float s) {
- // Fallback to a grey palette if the color is too desaturated.
- // This avoids hue shifts.
- if (s < 0.05f) {
- return GREY_PALETTE;
- }
-
- TonalPalette best = null;
- float error = Float.POSITIVE_INFINITY;
-
- for (int i = 0; i < TONAL_PALETTES.length; i++) {
- final TonalPalette candidate = TONAL_PALETTES[i];
-
- if (h >= candidate.minHue && h <= candidate.maxHue) {
- best = candidate;
- break;
- }
-
- if (candidate.maxHue > 1.0f && h >= 0.0f && h <= fract(candidate.maxHue)) {
- best = candidate;
- break;
- }
-
- if (candidate.minHue < 0.0f && h >= fract(candidate.minHue) && h <= 1.0f) {
- best = candidate;
- break;
- }
-
- if (h <= candidate.minHue && candidate.minHue - h < error) {
- best = candidate;
- error = candidate.minHue - h;
- } else if (h >= candidate.maxHue && h - candidate.maxHue < error) {
- best = candidate;
- error = h - candidate.maxHue;
- } else if (candidate.maxHue > 1.0f && h >= fract(candidate.maxHue)
- && h - fract(candidate.maxHue) < error) {
- best = candidate;
- error = h - fract(candidate.maxHue);
- } else if (candidate.minHue < 0.0f && h <= fract(candidate.minHue)
- && fract(candidate.minHue) - h < error) {
- best = candidate;
- error = fract(candidate.minHue) - h;
- }
- }
-
- return best;
- }
-
- private static float fract(float v) {
- return v - (float) Math.floor(v);
- }
-
- static class TonalPalette {
- final float[] h;
- final float[] s;
- final float[] l;
- final float minHue;
- final float maxHue;
-
- TonalPalette(float[] h, float[] s, float[] l) {
- if (h.length != s.length || s.length != l.length) {
- throw new IllegalArgumentException("All arrays should have the same size. h: "
- + Arrays.toString(h) + " s: " + Arrays.toString(s) + " l: "
- + Arrays.toString(l));
- }
-
- this.h = h;
- this.s = s;
- this.l = l;
-
- float minHue = Float.POSITIVE_INFINITY;
- float maxHue = Float.NEGATIVE_INFINITY;
-
- for (float v : h) {
- minHue = Math.min(v, minHue);
- maxHue = Math.max(v, maxHue);
- }
-
- this.minHue = minHue;
- this.maxHue = maxHue;
- }
- }
-
- // Data definition of Material Design tonal palettes
- // When the sort type is set to TONAL, these palettes are used to find
- // a best fit. Each palette is defined as 22 HSL colors
- private static final TonalPalette[] TONAL_PALETTES = {
- new TonalPalette(
- new float[] {1f, 1f, 0.991f, 0.991f, 0.9833333333333333f, 0f, 0f, 0f,
- 0.01134380453752181f, 0.015625000000000003f, 0.024193548387096798f,
- 0.027397260273972573f, 0.017543859649122865f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8434782608695652f, 1f, 1f, 1f, 1f,
- 1f},
- new float[] {0.04f, 0.09f, 0.14f, 0.2f, 0.27450980392156865f,
- 0.34901960784313724f, 0.4235294117647059f, 0.5490196078431373f,
- 0.6254901960784314f, 0.6862745098039216f, 0.7568627450980392f,
- 0.8568627450980393f, 0.9254901960784314f}
- ),
- new TonalPalette(
- new float[] {0.638f, 0.638f, 0.6385767790262171f, 0.6301169590643275f,
- 0.6223958333333334f, 0.6151079136690647f, 0.6065400843881856f,
- 0.5986964618249534f, 0.5910746812386157f, 0.5833333333333334f,
- 0.5748031496062993f, 0.5582010582010583f},
- new float[] {1f, 1f, 1f, 1f, 0.9014084507042253f, 0.8128654970760234f,
- 0.7979797979797981f, 0.7816593886462883f, 0.778723404255319f, 1f, 1f,
- 1f},
- new float[] {0.05f, 0.12f, 0.17450980392156862f, 0.2235294117647059f,
- 0.2784313725490196f, 0.3352941176470588f, 0.388235294117647f,
- 0.44901960784313727f, 0.5392156862745098f, 0.6509803921568628f,
- 0.7509803921568627f, 0.8764705882352941f}
- ),
- new TonalPalette(
- new float[] {0.563f, 0.569f, 0.5666f, 0.5669934640522876f, 0.5748031496062993f,
- 0.5595238095238095f, 0.5473118279569893f, 0.5393258426966292f,
- 0.5315955766192734f, 0.524031007751938f, 0.5154711673699016f,
- 0.508080808080808f, 0.5f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8847736625514403f, 1f, 1f,
- 1f},
- new float[] {0.07f, 0.12f, 0.16f, 0.2f, 0.24901960784313726f,
- 0.27450980392156865f, 0.30392156862745096f, 0.34901960784313724f,
- 0.4137254901960784f, 0.47647058823529415f, 0.5352941176470588f,
- 0.6764705882352942f, 0.8f}
- ),
- new TonalPalette(
- new float[] {0.508f, 0.511f, 0.508f, 0.508f, 0.5082304526748972f,
- 0.5069444444444444f, 0.5f, 0.5f, 0.5f, 0.48724954462659376f,
- 0.4800347222222222f, 0.4755134281200632f, 0.4724409448818897f,
- 0.4671052631578947f},
- new float[] {1f, 1f, 1f, 1f, 1f, 0.8888888888888887f, 0.9242424242424242f, 1f,
- 1f, 0.8133333333333332f, 0.7868852459016393f, 1f, 1f, 1f},
- new float[] {0.04f, 0.06f, 0.08f, 0.12f, 0.1588235294117647f,
- 0.21176470588235297f, 0.25882352941176473f, 0.3f, 0.34901960784313724f,
- 0.44117647058823534f, 0.5215686274509804f, 0.5862745098039216f,
- 0.7509803921568627f, 0.8509803921568627f}
- ),
- new TonalPalette(
- new float[] {0.333f, 0.333f, 0.333f, 0.3333333333333333f, 0.3333333333333333f,
- 0.34006734006734f, 0.34006734006734f, 0.34006734006734f,
- 0.34259259259259256f, 0.3475783475783476f, 0.34767025089605735f,
- 0.3467741935483871f, 0.3703703703703704f},
- new float[] {0.70f, 0.72f, 0.69f, 0.6703296703296703f, 0.728813559322034f,
- 0.5657142857142856f, 0.5076923076923077f, 0.3944223107569721f,
- 0.6206896551724138f, 0.8931297709923666f, 1f, 1f, 1f},
- new float[] {0.05f, 0.08f, 0.14f, 0.1784313725490196f, 0.23137254901960785f,
- 0.3431372549019608f, 0.38235294117647056f, 0.49215686274509807f,
- 0.6588235294117647f, 0.7431372549019608f, 0.8176470588235294f,
- 0.8784313725490196f, 0.9294117647058824f}
- ),
- new TonalPalette(
- new float[] {0.161f, 0.163f, 0.163f, 0.162280701754386f, 0.15032679738562088f,
- 0.15879265091863518f, 0.16236559139784948f, 0.17443868739205526f,
- 0.17824074074074076f, 0.18674698795180725f, 0.18692449355432778f,
- 0.1946778711484594f, 0.18604651162790695f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[] {0.05f, 0.08f, 0.11f, 0.14901960784313725f, 0.2f,
- 0.24901960784313726f, 0.30392156862745096f, 0.3784313725490196f,
- 0.4235294117647059f, 0.48823529411764705f, 0.6450980392156863f,
- 0.7666666666666666f, 0.8313725490196078f}
- ),
- new TonalPalette(
- new float[] {0.108f, 0.105f, 0.105f, 0.105f, 0.10619469026548674f,
- 0.11924686192468618f, 0.13046448087431692f, 0.14248366013071895f,
- 0.1506024096385542f, 0.16220238095238093f, 0.16666666666666666f,
- 0.16666666666666666f, 0.162280701754386f, 0.15686274509803924f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[] {0.17f, 0.22f, 0.28f, 0.35f, 0.44313725490196076f,
- 0.46862745098039216f, 0.47843137254901963f, 0.5f, 0.5117647058823529f,
- 0.5607843137254902f, 0.6509803921568628f, 0.7509803921568627f,
- 0.8509803921568627f, 0.9f}
- ),
- new TonalPalette(
- new float[] {0.036f, 0.036f, 0.036f, 0.036f, 0.03561253561253561f,
- 0.05098039215686275f, 0.07516339869281045f, 0.09477124183006536f,
- 0.1150326797385621f, 0.134640522875817f, 0.14640522875816991f,
- 0.1582397003745319f, 0.15773809523809523f, 0.15359477124183002f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[] {0.19f, 0.26f, 0.34f, 0.39f, 0.4588235294117647f, 0.5f, 0.5f, 0.5f,
- 0.5f, 0.5f, 0.5f, 0.6509803921568628f, 0.7803921568627451f, 0.9f}
- ),
- new TonalPalette(
- new float[] {0.955f, 0.961f, 0.958f, 0.9596491228070175f, 0.9593837535014005f,
- 0.9514767932489452f, 0.943859649122807f, 0.9396825396825397f,
- 0.9395424836601307f, 0.9393939393939394f, 0.9362745098039216f,
- 0.9754098360655739f, 0.9824561403508771f},
- new float[] {0.87f, 0.85f, 0.85f, 0.84070796460177f, 0.8206896551724138f,
- 0.7979797979797981f, 0.7661290322580644f, 0.9051724137931036f,
- 1f, 1f, 1f, 1f, 1f},
- new float[] {0.06f, 0.11f, 0.16f, 0.22156862745098038f, 0.2843137254901961f,
- 0.388235294117647f, 0.48627450980392156f, 0.5450980392156863f,
- 0.6f, 0.6764705882352942f, 0.8f, 0.8803921568627451f,
- 0.9254901960784314f}
- ),
- new TonalPalette(
- new float[] {0.866f, 0.855f, 0.841025641025641f, 0.8333333333333334f,
- 0.8285256410256411f, 0.821522309711286f, 0.8083333333333333f,
- 0.8046594982078853f, 0.8005822416302766f, 0.7842377260981912f,
- 0.7771084337349398f, 0.7747747747747749f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
- 0.737142857142857f, 0.6434108527131781f, 0.46835443037974644f},
- new float[] {0.05f, 0.08f, 0.12745098039215685f, 0.15490196078431373f,
- 0.20392156862745098f, 0.24901960784313726f, 0.3137254901960784f,
- 0.36470588235294116f, 0.44901960784313727f, 0.6568627450980392f,
- 0.7470588235294118f, 0.8450980392156863f}
- ),
- new TonalPalette(
- new float[] {0.925f, 0.93f, 0.938f, 0.947f, 0.955952380952381f,
- 0.9681069958847737f, 0.9760479041916167f, 0.9873563218390804f, 0f, 0f,
- 0.009057971014492771f, 0.026748971193415648f,
- 0.041666666666666616f, 0.05303030303030304f},
- new float[] {1f, 1f, 1f, 1f, 1f, 0.8350515463917526f, 0.6929460580912863f,
- 0.6387665198237885f, 0.6914893617021276f, 0.7583892617449666f,
- 0.8070175438596495f, 0.9310344827586209f, 1f, 1f},
- new float[] {0.10f, 0.13f, 0.17f, 0.2f, 0.27450980392156865f,
- 0.3803921568627451f, 0.4725490196078432f, 0.5549019607843138f,
- 0.6313725490196078f, 0.707843137254902f, 0.7764705882352941f,
- 0.8294117647058823f, 0.9058823529411765f, 0.9568627450980391f}
- ),
- new TonalPalette(
- new float[] {0.733f, 0.736f, 0.744f, 0.7514619883040936f, 0.7679738562091503f,
- 0.7802083333333333f, 0.7844311377245509f, 0.796875f,
- 0.8165618448637316f, 0.8487179487179487f, 0.8582375478927203f,
- 0.8562091503267975f, 0.8666666666666667f},
- new float[] {1f, 1f, 1f, 1f, 1f, 0.8163265306122449f, 0.6653386454183268f,
- 0.7547169811320753f, 0.929824561403509f, 0.9558823529411766f,
- 0.9560439560439562f, 1f, 1f},
- new float[] {0.07f, 0.12f, 0.17f, 0.2235294117647059f, 0.3f,
- 0.38431372549019605f, 0.492156862745098f, 0.5843137254901961f,
- 0.6647058823529411f, 0.7333333333333334f, 0.8215686274509804f, 0.9f,
- 0.9411764705882353f}
- ),
- new TonalPalette(
- new float[] {0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
- 0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
- 0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
- 0.6666666666666666f, 0.6666666666666666f},
- new float[] {0.25f, 0.24590163934426232f, 0.17880794701986752f,
- 0.14606741573033713f, 0.13761467889908252f, 0.14893617021276592f,
- 0.16756756756756758f, 0.20312500000000017f, 0.26086956521739135f,
- 0.29999999999999966f, 0.5000000000000004f},
- new float[] {0.18f, 0.2392156862745098f, 0.296078431372549f,
- 0.34901960784313724f, 0.4274509803921569f, 0.5392156862745098f,
- 0.6372549019607843f, 0.7490196078431373f, 0.8196078431372549f,
- 0.8823529411764706f, 0.9372549019607843f}
- ),
- new TonalPalette(
- new float[] {0.938f, 0.944f, 0.952f, 0.961f, 0.9678571428571429f,
- 0.9944812362030905f, 0f, 0f,
- 0.0047348484848484815f, 0.00316455696202532f, 0f,
- 0.9980392156862745f, 0.9814814814814816f, 0.9722222222222221f},
- new float[] {1f, 1f, 1f, 1f, 1f, 0.7023255813953488f, 0.6638655462184874f,
- 0.6521739130434782f, 0.7719298245614035f, 0.8315789473684211f,
- 0.6867469879518071f, 0.7264957264957265f, 0.8181818181818182f,
- 0.8181818181818189f},
- new float[] {0.08f, 0.13f, 0.18f, 0.23f, 0.27450980392156865f,
- 0.4215686274509804f,
- 0.4666666666666667f, 0.503921568627451f, 0.5529411764705883f,
- 0.6274509803921569f, 0.6745098039215687f, 0.7705882352941176f,
- 0.892156862745098f, 0.9568627450980391f}
- ),
- new TonalPalette(
- new float[] {0.88f, 0.888f, 0.897f, 0.9052287581699346f, 0.9112021857923498f,
- 0.9270152505446624f, 0.9343137254901961f, 0.9391534391534391f,
- 0.9437984496124031f, 0.943661971830986f, 0.9438943894389439f,
- 0.9426229508196722f, 0.9444444444444444f},
- new float[] {1f, 1f, 1f, 1f, 0.8133333333333332f, 0.7927461139896375f,
- 0.7798165137614679f, 0.7777777777777779f, 0.8190476190476191f,
- 0.8255813953488372f, 0.8211382113821142f, 0.8133333333333336f,
- 0.8000000000000006f},
- new float[] {0.08f, 0.12f, 0.16f, 0.2f, 0.29411764705882354f,
- 0.3784313725490196f, 0.42745098039215684f, 0.4764705882352941f,
- 0.5882352941176471f, 0.6627450980392157f, 0.7588235294117647f,
- 0.8529411764705882f, 0.9411764705882353f}
- ),
- new TonalPalette(
- new float[] {0.669f, 0.680f, 0.6884057971014492f, 0.6974789915966387f,
- 0.7079889807162534f, 0.7154471544715447f, 0.7217741935483872f,
- 0.7274143302180687f, 0.7272727272727273f, 0.7258064516129031f,
- 0.7252252252252251f, 0.7333333333333333f},
- new float[] {0.81f, 0.81f, 0.8214285714285715f, 0.6878612716763006f,
- 0.6080402010050251f, 0.5774647887323943f, 0.5391304347826086f,
- 0.46724890829694316f, 0.4680851063829788f, 0.462686567164179f,
- 0.45679012345678977f, 0.4545454545454551f},
- new float[] {0.12f, 0.16f, 0.2196078431372549f, 0.33921568627450976f,
- 0.39019607843137255f, 0.4176470588235294f, 0.45098039215686275f,
- 0.5509803921568628f, 0.6313725490196078f, 0.7372549019607844f,
- 0.8411764705882353f, 0.9352941176470588f}
- ),
- new TonalPalette(
- new float[] {0.6470588235294118f, 0.6516666666666667f, 0.6464174454828661f,
- 0.6441441441441442f, 0.6432748538011696f, 0.6416666666666667f,
- 0.6402439024390243f, 0.6412429378531074f, 0.6435185185185186f,
- 0.6428571428571429f},
- new float[] {0.8095238095238095f, 0.6578947368421053f, 0.5721925133689839f,
- 0.5362318840579711f, 0.5f, 0.4424778761061947f, 0.44086021505376327f,
- 0.44360902255639095f, 0.4499999999999997f, 0.4375000000000006f},
- new float[] {0.16470588235294117f, 0.2980392156862745f, 0.36666666666666664f,
- 0.40588235294117647f, 0.44705882352941173f,
- 0.5568627450980392f, 0.6352941176470588f, 0.7392156862745098f,
- 0.8431372549019608f, 0.9372549019607843f}
- ),
- new TonalPalette(
- new float[] {0.469f, 0.46732026143790845f, 0.4718614718614719f,
- 0.4793650793650794f, 0.48071625344352614f, 0.4829683698296837f,
- 0.484375f, 0.4841269841269842f, 0.48444444444444457f,
- 0.48518518518518516f, 0.4907407407407408f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 0.6274509803921569f, 0.41832669322709176f,
- 0.41899441340782106f, 0.4128440366972478f, 0.4090909090909088f},
- new float[] {0.07f, 0.1f, 0.15098039215686274f, 0.20588235294117646f,
- 0.2372549019607843f, 0.26862745098039215f, 0.4f, 0.5078431372549019f,
- 0.6490196078431372f, 0.7862745098039216f, 0.9137254901960784f}
- ),
- new TonalPalette(
- new float[] {0.542f, 0.5444444444444444f, 0.5555555555555556f,
- 0.5555555555555556f, 0.553763440860215f, 0.5526315789473684f,
- 0.5555555555555556f, 0.5555555555555555f, 0.5555555555555556f,
- 0.5512820512820514f, 0.5666666666666667f},
- new float[] {0.25f, 0.24590163934426232f, 0.19148936170212766f,
- 0.1791044776119403f, 0.18343195266272191f, 0.18446601941747576f,
- 0.1538461538461539f, 0.15625000000000003f, 0.15328467153284678f,
- 0.15662650602409653f, 0.151515151515151f},
- new float[] {0.05f, 0.1196078431372549f, 0.1843137254901961f,
- 0.2627450980392157f,
- 0.33137254901960783f, 0.403921568627451f, 0.5411764705882354f,
- 0.6235294117647059f, 0.7313725490196079f, 0.8372549019607843f,
- 0.9352941176470588f}
- ),
- new TonalPalette(
- new float[] {0.022222222222222223f, 0.02469135802469136f, 0.031249999999999997f,
- 0.03947368421052631f, 0.04166666666666668f,
- 0.043650793650793655f, 0.04411764705882352f, 0.04166666666666652f,
- 0.04444444444444459f, 0.05555555555555529f},
- new float[] {0.33333333333333337f, 0.2783505154639175f, 0.2580645161290323f,
- 0.25675675675675674f, 0.2528735632183908f, 0.17500000000000002f,
- 0.15315315315315312f, 0.15189873417721522f,
- 0.15789473684210534f, 0.15789473684210542f},
- new float[] {0.08823529411764705f, 0.19019607843137254f, 0.2431372549019608f,
- 0.2901960784313725f, 0.3411764705882353f, 0.47058823529411764f,
- 0.5647058823529412f, 0.6901960784313725f, 0.8137254901960784f,
- 0.9254901960784314f}
- ),
- new TonalPalette(
- new float[] {0.027f, 0.03f, 0.038f, 0.044f, 0.050884955752212385f,
- 0.07254901960784313f, 0.0934640522875817f,
- 0.10457516339869281f, 0.11699346405228758f,
- 0.1255813953488372f, 0.1268939393939394f, 0.12533333333333332f,
- 0.12500000000000003f, 0.12777777777777777f},
- new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[] {0.25f, 0.3f, 0.35f, 0.4f, 0.44313725490196076f, 0.5f, 0.5f, 0.5f,
- 0.5f, 0.5784313725490196f,
- 0.6549019607843137f, 0.7549019607843137f, 0.8509803921568627f,
- 0.9411764705882353f}
- )
- };
-
- private static final TonalPalette GREY_PALETTE = new TonalPalette(
- new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
- new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
- new float[]{0.08f, 0.11f, 0.14901960784313725f, 0.2f, 0.2980392156862745f, 0.4f,
- 0.4980392156862745f, 0.6196078431372549f, 0.7176470588235294f,
- 0.8196078431372549f, 0.9176470588235294f, 0.9490196078431372f}
- );
-
- @SuppressWarnings("WeakerAccess")
- static final ColorRange[] DISALLOWED_COLORS = new ColorRange[] {
-
- // Red
- new ColorRange(
- new Range<>(0f, 20f) /* H */,
- new Range<>(0.7f, 1f) /* S */,
- new Range<>(0.21f, 0.79f)) /* L */,
- new ColorRange(
- new Range<>(0f, 20f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.355f, 0.653f)),
-
- // Red Orange
- new ColorRange(
- new Range<>(20f, 40f),
- new Range<>(0.7f, 1f),
- new Range<>(0.28f, 0.643f)),
- new ColorRange(
- new Range<>(20f, 40f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.414f, 0.561f)),
- new ColorRange(
- new Range<>(20f, 40f),
- new Range<>(0f, 3f),
- new Range<>(0.343f, 0.584f)),
-
- // Orange
- new ColorRange(
- new Range<>(40f, 60f),
- new Range<>(0.7f, 1f),
- new Range<>(0.173f, 0.349f)),
- new ColorRange(
- new Range<>(40f, 60f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.233f, 0.427f)),
- new ColorRange(
- new Range<>(40f, 60f),
- new Range<>(0f, 0.3f),
- new Range<>(0.231f, 0.484f)),
-
- // Yellow 60
- new ColorRange(
- new Range<>(60f, 80f),
- new Range<>(0.7f, 1f),
- new Range<>(0.488f, 0.737f)),
- new ColorRange(
- new Range<>(60f, 80f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.673f, 0.837f)),
-
- // Yellow Green 80
- new ColorRange(
- new Range<>(80f, 100f),
- new Range<>(0.7f, 1f),
- new Range<>(0.469f, 0.61f)),
-
- // Yellow green 100
- new ColorRange(
- new Range<>(100f, 120f),
- new Range<>(0.7f, 1f),
- new Range<>(0.388f, 0.612f)),
- new ColorRange(
- new Range<>(100f, 120f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.424f, 0.541f)),
-
- // Green
- new ColorRange(
- new Range<>(120f, 140f),
- new Range<>(0.7f, 1f),
- new Range<>(0.375f, 0.52f)),
- new ColorRange(
- new Range<>(120f, 140f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.435f, 0.524f)),
-
- // Green Blue 140
- new ColorRange(
- new Range<>(140f, 160f),
- new Range<>(0.7f, 1f),
- new Range<>(0.496f, 0.641f)),
-
- // Seafoam
- new ColorRange(
- new Range<>(160f, 180f),
- new Range<>(0.7f, 1f),
- new Range<>(0.496f, 0.567f)),
-
- // Cyan
- new ColorRange(
- new Range<>(180f, 200f),
- new Range<>(0.7f, 1f),
- new Range<>(0.52f, 0.729f)),
-
- // Blue
- new ColorRange(
- new Range<>(220f, 240f),
- new Range<>(0.7f, 1f),
- new Range<>(0.396f, 0.571f)),
- new ColorRange(
- new Range<>(220f, 240f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.425f, 0.551f)),
-
- // Blue Purple 240
- new ColorRange(
- new Range<>(240f, 260f),
- new Range<>(0.7f, 1f),
- new Range<>(0.418f, 0.639f)),
- new ColorRange(
- new Range<>(220f, 240f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.441f, 0.576f)),
-
- // Blue Purple 260
- new ColorRange(
- new Range<>(260f, 280f),
- new Range<>(0.3f, 1f), // Bigger range
- new Range<>(0.461f, 0.553f)),
-
- // Fuchsia
- new ColorRange(
- new Range<>(300f, 320f),
- new Range<>(0.7f, 1f),
- new Range<>(0.484f, 0.588f)),
- new ColorRange(
- new Range<>(300f, 320f),
- new Range<>(0.3f, 0.7f),
- new Range<>(0.48f, 0.592f)),
-
- // Pink
- new ColorRange(
- new Range<>(320f, 340f),
- new Range<>(0.7f, 1f),
- new Range<>(0.466f, 0.629f)),
-
- // Soft red
- new ColorRange(
- new Range<>(340f, 360f),
- new Range<>(0.7f, 1f),
- new Range<>(0.437f, 0.596f))
- };
-
- /**
- * Representation of an HSL color range.
- * <ul>
- * <li>hsl[0] is Hue [0 .. 360)</li>
- * <li>hsl[1] is Saturation [0...1]</li>
- * <li>hsl[2] is Lightness [0...1]</li>
- * </ul>
- */
- static class ColorRange {
- private Range<Float> mHue;
- private Range<Float> mSaturation;
- private Range<Float> mLightness;
-
- ColorRange(Range<Float> hue, Range<Float> saturation, Range<Float> lightness) {
- mHue = hue;
- mSaturation = saturation;
- mLightness = lightness;
- }
-
- boolean containsColor(float h, float s, float l) {
- if (!mHue.contains(h)) {
- return false;
- } else if (!mSaturation.contains(s)) {
- return false;
- } else if (!mLightness.contains(l)) {
- return false;
- }
- return true;
- }
-
- float[] getCenter() {
- return new float[] {
- mHue.getLower() + (mHue.getUpper() - mHue.getLower()) / 2f,
- mSaturation.getLower() + (mSaturation.getUpper() - mSaturation.getLower()) / 2f,
- mLightness.getLower() + (mLightness.getUpper() - mLightness.getLower()) / 2f
- };
- }
-
- @Override
- public String toString() {
- return String.format("H: %s, S: %s, L %s", mHue, mSaturation, mLightness);
- }
- }
-
- private static List<Integer> getMainColors(WallpaperColorsCompat wallpaperColors) {
- LinkedList<Integer> colors = new LinkedList<>();
- if (wallpaperColors.getPrimaryColor() != 0) {
- colors.add(wallpaperColors.getPrimaryColor());
- }
- if (wallpaperColors.getSecondaryColor() != 0) {
- colors.add(wallpaperColors.getSecondaryColor());
- }
- if (wallpaperColors.getTertiaryColor() != 0) {
- colors.add(wallpaperColors.getTertiaryColor());
- }
- return colors;
- }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperColorsCompat.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperColorsCompat.java
deleted file mode 100644
index d984a84..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperColorsCompat.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 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.launcher3.uioverrides.dynamicui;
-
-/**
- * A compatibility layer around platform implementation of WallpaperColors
- */
-public class WallpaperColorsCompat {
-
- public static final int HINT_SUPPORTS_DARK_TEXT = 0x1;
- public static final int HINT_SUPPORTS_DARK_THEME = 0x2;
-
- private final int mPrimaryColor;
- private final int mSecondaryColor;
- private final int mTertiaryColor;
- private final int mColorHints;
-
- public WallpaperColorsCompat(int primaryColor, int secondaryColor, int tertiaryColor,
- int colorHints) {
- mPrimaryColor = primaryColor;
- mSecondaryColor = secondaryColor;
- mTertiaryColor = tertiaryColor;
- mColorHints = colorHints;
- }
-
- public int getPrimaryColor() {
- return mPrimaryColor;
- }
-
- public int getSecondaryColor() {
- return mSecondaryColor;
- }
-
- public int getTertiaryColor() {
- return mTertiaryColor;
- }
-
- public int getColorHints() {
- return mColorHints;
- }
-
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java
deleted file mode 100644
index 9dbe47c..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 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.launcher3.uioverrides.dynamicui;
-
-import android.content.Context;
-import android.os.Build;
-
-import androidx.annotation.Nullable;
-
-public abstract class WallpaperManagerCompat {
-
- private static final Object sInstanceLock = new Object();
- private static WallpaperManagerCompat sInstance;
-
- public static WallpaperManagerCompat getInstance(Context context) {
- synchronized (sInstanceLock) {
- if (sInstance == null) {
- context = context.getApplicationContext();
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
- try {
- sInstance = new WallpaperManagerCompatVOMR1(context);
- } catch (Throwable e) {
- // The wallpaper APIs do not yet exist
- }
- }
- if (sInstance == null) {
- sInstance = new WallpaperManagerCompatVL(context);
- }
- }
- return sInstance;
- }
- }
-
-
- public abstract @Nullable WallpaperColorsCompat getWallpaperColors(int which);
-
- public abstract void addOnColorsChangedListener(OnColorsChangedListenerCompat listener);
-
- /**
- * Interface definition for a callback to be invoked when colors change on a wallpaper.
- */
- public interface OnColorsChangedListenerCompat {
-
- void onColorsChanged(WallpaperColorsCompat colors, int which);
- }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java
deleted file mode 100644
index 500fdc3..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2017 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.launcher3.uioverrides.dynamicui;
-
-import static android.app.WallpaperManager.FLAG_SYSTEM;
-
-import static com.android.launcher3.Utilities.getDevicePrefs;
-
-import android.app.WallpaperInfo;
-import android.app.WallpaperManager;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.launcher3.icons.ColorExtractor;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import androidx.annotation.Nullable;
-
-public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
-
- private static final String TAG = "WMCompatVL";
-
- private static final String VERSION_PREFIX = "1,";
- private static final String KEY_COLORS = "wallpaper_parsed_colors";
- private static final String ACTION_EXTRACTION_COMPLETE =
- "com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL.EXTRACTION_COMPLETE";
-
- public static final int WALLPAPER_COMPAT_JOB_ID = 1;
-
- private final ArrayList<OnColorsChangedListenerCompat> mListeners = new ArrayList<>();
-
- private final Context mContext;
- private WallpaperColorsCompat mColorsCompat;
-
- WallpaperManagerCompatVL(Context context) {
- mContext = context;
-
- String colors = getDevicePrefs(mContext).getString(KEY_COLORS, "");
- int wallpaperId = -1;
- if (colors.startsWith(VERSION_PREFIX)) {
- Pair<Integer, WallpaperColorsCompat> storedValue = parseValue(colors);
- wallpaperId = storedValue.first;
- mColorsCompat = storedValue.second;
- }
-
- if (wallpaperId == -1 || wallpaperId != getWallpaperId(context)) {
- reloadColors();
- }
- context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- reloadColors();
- }
- }, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
-
- // Register a receiver for results
- String permission = null;
- // Find a permission which only we can use.
- try {
- for (PermissionInfo info : context.getPackageManager().getPackageInfo(
- context.getPackageName(),
- PackageManager.GET_PERMISSIONS).permissions) {
- if ((info.protectionLevel & PermissionInfo.PROTECTION_SIGNATURE) != 0) {
- permission = info.name;
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- // Something went wrong. ignore
- Log.d(TAG, "Unable to get permission info", e);
- }
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- handleResult(intent.getStringExtra(KEY_COLORS));
- }
- }, new IntentFilter(ACTION_EXTRACTION_COMPLETE), permission, new Handler());
- }
-
- @Nullable
- @Override
- public WallpaperColorsCompat getWallpaperColors(int which) {
- return which == FLAG_SYSTEM ? mColorsCompat : null;
- }
-
- @Override
- public void addOnColorsChangedListener(OnColorsChangedListenerCompat listener) {
- mListeners.add(listener);
- }
-
- private void reloadColors() {
- JobInfo job = new JobInfo.Builder(WALLPAPER_COMPAT_JOB_ID,
- new ComponentName(mContext, ColorExtractionService.class))
- .setMinimumLatency(0).build();
- ((JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(job);
- }
-
- private void handleResult(String result) {
- getDevicePrefs(mContext).edit().putString(KEY_COLORS, result).apply();
- mColorsCompat = parseValue(result).second;
- for (OnColorsChangedListenerCompat listener : mListeners) {
- listener.onColorsChanged(mColorsCompat, FLAG_SYSTEM);
- }
- }
-
- private static final int getWallpaperId(Context context) {
- return context.getSystemService(WallpaperManager.class).getWallpaperId(FLAG_SYSTEM);
- }
-
- /**
- * Parses the stored value and returns the wallpaper id and wallpaper colors.
- */
- private static Pair<Integer, WallpaperColorsCompat> parseValue(String value) {
- String[] parts = value.split(",");
- Integer wallpaperId = Integer.parseInt(parts[1]);
- if (parts.length == 2) {
- // There is no wallpaper color info present, eg when live wallpaper has no preview.
- return Pair.create(wallpaperId, null);
- }
-
- int primary = parts.length > 2 ? Integer.parseInt(parts[2]) : 0;
- int secondary = parts.length > 3 ? Integer.parseInt(parts[3]) : 0;
- int tertiary = parts.length > 4 ? Integer.parseInt(parts[4]) : 0;
-
- return Pair.create(wallpaperId, new WallpaperColorsCompat(primary, secondary, tertiary,
- 0 /* hints */));
- }
-
- /**
- * Intent service to handle color extraction
- */
- public static class ColorExtractionService extends JobService implements Runnable {
- private static final int MAX_WALLPAPER_EXTRACTION_AREA = 112 * 112;
-
- private HandlerThread mWorkerThread;
- private Handler mWorkerHandler;
- private ColorExtractor mColorExtractor;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mWorkerThread = new HandlerThread("ColorExtractionService");
- mWorkerThread.start();
- mWorkerHandler = new Handler(mWorkerThread.getLooper());
- mColorExtractor = new ColorExtractor();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mWorkerThread.quit();
- }
-
- @Override
- public boolean onStartJob(final JobParameters jobParameters) {
- mWorkerHandler.post(this);
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters jobParameters) {
- mWorkerHandler.removeCallbacksAndMessages(null);
- return true;
- }
-
- /**
- * Extracts the wallpaper colors and sends the result back through the receiver.
- */
- @Override
- public void run() {
- int wallpaperId = getWallpaperId(this);
-
- Bitmap bitmap = null;
- Drawable drawable = null;
-
- WallpaperManager wm = WallpaperManager.getInstance(this);
- WallpaperInfo info = wm.getWallpaperInfo();
- if (info != null) {
- // For live wallpaper, extract colors from thumbnail
- drawable = info.loadThumbnail(getPackageManager());
- } else {
- try (ParcelFileDescriptor fd = wm.getWallpaperFile(FLAG_SYSTEM)) {
- BitmapRegionDecoder decoder = BitmapRegionDecoder
- .newInstance(fd.getFileDescriptor(), false);
-
- int requestedArea = decoder.getWidth() * decoder.getHeight();
- BitmapFactory.Options options = new BitmapFactory.Options();
-
- if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
- double areaRatio =
- (double) requestedArea / MAX_WALLPAPER_EXTRACTION_AREA;
- double nearestPowOf2 =
- Math.floor(Math.log(areaRatio) / (2 * Math.log(2)));
- options.inSampleSize = (int) Math.pow(2, nearestPowOf2);
- }
- Rect region = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
- bitmap = decoder.decodeRegion(region, options);
- decoder.recycle();
- } catch (IOException | NullPointerException e) {
- Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
- }
- if (bitmap == null) {
- drawable = wm.getDrawable();
- }
- }
-
- if (drawable != null) {
- // Calculate how big the bitmap needs to be.
- // This avoids unnecessary processing and allocation inside Palette.
- final int requestedArea = drawable.getIntrinsicWidth() *
- drawable.getIntrinsicHeight();
- double scale = 1;
- if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
- scale = Math.sqrt(MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea);
- }
- bitmap = Bitmap.createBitmap((int) (drawable.getIntrinsicWidth() * scale),
- (int) (drawable.getIntrinsicHeight() * scale), Bitmap.Config.ARGB_8888);
- final Canvas bmpCanvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
- drawable.draw(bmpCanvas);
- }
-
- String value = VERSION_PREFIX + wallpaperId;
-
- if (bitmap != null) {
- int color = mColorExtractor.findDominantColorByHue(bitmap,
- MAX_WALLPAPER_EXTRACTION_AREA);
- value += "," + color;
- }
-
- // Send the result
- sendBroadcast(new Intent(ACTION_EXTRACTION_COMPLETE)
- .setPackage(getPackageName())
- .putExtra(KEY_COLORS, value));
- }
- }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVOMR1.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVOMR1.java
deleted file mode 100644
index f34497d..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVOMR1.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2017 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.launcher3.uioverrides.dynamicui;
-
-import android.annotation.TargetApi;
-import android.app.WallpaperColors;
-import android.app.WallpaperManager;
-import android.app.WallpaperManager.OnColorsChangedListener;
-import android.content.Context;
-import android.graphics.Color;
-import android.util.Log;
-
-import java.lang.reflect.Method;
-
-import androidx.annotation.Nullable;
-
-@TargetApi(27)
-public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat {
-
- private static final String TAG = "WMCompatVOMR1";
-
- private final WallpaperManager mWm;
- private Method mWCColorHintsMethod;
-
- WallpaperManagerCompatVOMR1(Context context) throws Throwable {
- mWm = context.getSystemService(WallpaperManager.class);
- String className = WallpaperColors.class.getName();
- try {
- mWCColorHintsMethod = WallpaperColors.class.getDeclaredMethod("getColorHints");
- } catch (Exception exc) {
- Log.e(TAG, "getColorHints not available", exc);
- }
- }
-
- @Nullable
- @Override
- public WallpaperColorsCompat getWallpaperColors(int which) {
- return convertColorsObject(mWm.getWallpaperColors(which));
- }
-
- @Override
- public void addOnColorsChangedListener(final OnColorsChangedListenerCompat listener) {
- OnColorsChangedListener onChangeListener = new OnColorsChangedListener() {
- @Override
- public void onColorsChanged(WallpaperColors colors, int which) {
- listener.onColorsChanged(convertColorsObject(colors), which);
- }
- };
- mWm.addOnColorsChangedListener(onChangeListener, null);
- }
-
- private WallpaperColorsCompat convertColorsObject(WallpaperColors colors) {
- if (colors == null) {
- return null;
- }
- Color primary = colors.getPrimaryColor();
- Color secondary = colors.getSecondaryColor();
- Color tertiary = colors.getTertiaryColor();
- int primaryVal = primary != null ? primary.toArgb() : 0;
- int secondaryVal = secondary != null ? secondary.toArgb() : 0;
- int tertiaryVal = tertiary != null ? tertiary.toArgb() : 0;
- int colorHints = 0;
- try {
- if (mWCColorHintsMethod != null) {
- colorHints = (Integer) mWCColorHintsMethod.invoke(colors);
- }
- } catch (Exception exc) {
- Log.e(TAG, "error calling color hints", exc);
- }
- return new WallpaperColorsCompat(primaryVal, secondaryVal, tertiaryVal, colorHints);
- }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 53748b7..978c321 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -23,6 +23,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
/**
* Definition for AllApps state
@@ -76,7 +77,7 @@
}
@Override
- public float getWorkspaceScrimAlpha(Launcher launcher) {
- return 1;
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
}
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
index e85e505..d154317 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -19,7 +19,10 @@
import android.content.Context;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
/**
* Definition for overview state
@@ -56,4 +59,9 @@
public static OverviewState newSplitSelectState(int id) {
return new OverviewState(id);
}
+
+ @Override
+ public int getWorkspaceScrimColor(Launcher launcher) {
+ return Themes.getAttrColor(launcher, R.attr.overviewScrimColor);
+ }
}
diff --git a/tests/dummy_app/Android.mk b/tests/dummy_app/Android.mk
index f4ab582..3472079 100644
--- a/tests/dummy_app/Android.mk
+++ b/tests/dummy_app/Android.mk
@@ -7,6 +7,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := Aardwolf
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
LOCAL_SDK_VERSION := current
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index e7e245f..2a0f7bb 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -115,7 +115,6 @@
if (TestHelpers.isInLauncherProcess()) {
StrictMode.VmPolicy.Builder builder =
new StrictMode.VmPolicy.Builder()
- .detectActivityLeaks()
.penaltyLog()
.penaltyListener(Runnable::run, violation -> {
if (sStrictmodeDetectedActivityLeak == null) {
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 266f0ae..6c68daa 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -4,6 +4,7 @@
import android.view.Surface;
import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.testing.TestProtocol;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -54,19 +55,23 @@
}
private void evaluateInPortrait() throws Throwable {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "evaluateInPortrait");
mTest.mDevice.setOrientationNatural();
mTest.mLauncher.setExpectedRotation(Surface.ROTATION_0);
AbstractLauncherUiTest.checkDetectedLeaks(mTest.mLauncher);
base.evaluate();
mTest.getDevice().pressHome();
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "evaluateInPortrait finished");
}
private void evaluateInLandscape() throws Throwable {
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "evaluateInLandscape");
mTest.mDevice.setOrientationLeft();
mTest.mLauncher.setExpectedRotation(Surface.ROTATION_90);
AbstractLauncherUiTest.checkDetectedLeaks(mTest.mLauncher);
base.evaluate();
mTest.getDevice().pressHome();
+ Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "evaluateInLandscape finished");
}
};
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index cf935f3..ebad154 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -636,6 +636,7 @@
}
SystemClock.sleep(100);
}
+ checkForAnomaly();
fail("Launcher didn't initialize");
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index a3f9ade..51e331d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -169,12 +169,16 @@
"widgets_table");
boolean hasHeaderExpanded = false;
+ int scrollDistance = 0;
for (int i = 0; i < SCROLL_ATTEMPTS; i++) {
UiObject2 fullWidgetsPicker = verifyActiveContainer();
UiObject2 header = mLauncher.waitForObjectInContainer(fullWidgetsPicker,
headerSelector);
- int headerHeight = header.getVisibleBounds().height();
+ // If a header is barely visible in the bottom edge of the screen, its height could be
+ // too small for a scroll gesture. Since all header should have roughly the same height,
+ // let's pick the max height we have seen so far.
+ scrollDistance = Math.max(scrollDistance, header.getVisibleBounds().height());
// Look for a header that has the test app name.
UiObject2 headerTitle = mLauncher.findObjectInContainer(fullWidgetsPicker,
@@ -196,7 +200,8 @@
return widgetsContainer;
}
}
- mLauncher.scrollDownByDistance(fullWidgetsPicker, headerHeight);
+ log("Finding test widget package - scroll with distance: " + scrollDistance);
+ mLauncher.scrollDownByDistance(fullWidgetsPicker, scrollDistance);
}
return null;