Merge "Do not clear the changed view when there is an update to RemoteViews" into udc-dev
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index 43439c6..2887518 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -205,15 +205,16 @@
android:id="@+id/checkmark_animation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginBottom="44dp"
android:gravity="center"
android:scaleType="centerCrop"
app:lottie_loop="false"
android:visibility="gone"
- app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle" />
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
+ app:layout_constraintBottom_toBottomOf="parent" />
<Button
android:id="@+id/gesture_tutorial_fragment_action_button"
@@ -224,6 +225,7 @@
android:stateListAnimator="@null"
android:text="@string/gesture_tutorial_action_button_label"
android:visibility="invisible"
+ android:layout_marginBottom="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/quickstep/res/layout/taskbar_edu.xml b/quickstep/res/layout/taskbar_edu.xml
deleted file mode 100644
index f3856ba..0000000
--- a/quickstep/res/layout/taskbar_edu.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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.launcher3.taskbar.TaskbarEduView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:gravity="bottom"
- android:orientation="vertical"
- android:layout_marginHorizontal="108dp">
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/edu_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/bg_rounded_corner_bottom_sheet"
- android:gravity="center_horizontal"
- android:paddingHorizontal="36dp"
- android:paddingTop="64dp">
-
- <com.android.launcher3.taskbar.TaskbarEduPagedView
- android:id="@+id/content"
- android:clipToPadding="false"
- android:layout_width="match_parent"
- android:layout_height="378dp"
- app:layout_constraintTop_toTopOf="parent"
- launcher:pageIndicator="@+id/content_page_indicator" />
-
- <Button
- android:id="@+id/edu_start_button"
- android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginBottom="18dp"
- android:layout_marginTop="32dp"
- app:layout_constraintTop_toBottomOf="@id/content"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- android:text="@string/taskbar_edu_close"
- style="@style/TaskbarEdu.Button.Close"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
- android:id="@+id/content_page_indicator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:layout_constraintTop_toTopOf="@id/edu_start_button"
- app:layout_constraintBottom_toBottomOf="@id/edu_start_button"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:indicatorDotColor="@color/folder_pagination_color"
- android:elevation="1dp" />
-
- <Button
- android:id="@+id/edu_end_button"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- app:layout_constraintTop_toTopOf="@id/edu_start_button"
- app:layout_constraintBottom_toBottomOf="@id/edu_start_button"
- app:layout_constraintEnd_toEndOf="parent"
- android:text="@string/taskbar_edu_next"
- style="@style/TaskbarEdu.Button.Next"
- android:textColor="?androidprv:attr/textColorOnAccent"/>
- </androidx.constraintlayout.widget.ConstraintLayout>
-</com.android.launcher3.taskbar.TaskbarEduView>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_features.xml b/quickstep/res/layout/taskbar_edu_features.xml
index 4137df7..5cd7aaf 100644
--- a/quickstep/res/layout/taskbar_edu_features.xml
+++ b/quickstep/res/layout/taskbar_edu_features.xml
@@ -106,7 +106,7 @@
<Button
android:id="@+id/done_button"
- style="@style/TaskbarEdu.Button.Next"
+ style="@style/TaskbarEdu.Button.Done"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginTop="32dp"
diff --git a/quickstep/res/layout/taskbar_edu_pages_persistent.xml b/quickstep/res/layout/taskbar_edu_pages_persistent.xml
deleted file mode 100644
index 77ce31a..0000000
--- a/quickstep/res/layout/taskbar_edu_pages_persistent.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2022 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.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.TaskbarEdu.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_splitscreen" />
-
- <com.airbnb.lottie.LottieAnimationView
- android:id="@+id/animation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- app:lottie_rawRes="@raw/taskbar_edu_splitscreen_persistent" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.TaskbarEdu.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_suggestions" />
-
- <com.airbnb.lottie.LottieAnimationView
- android:id="@id/animation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- app:lottie_rawRes="@raw/taskbar_edu_suggestions_persistent" />
- </LinearLayout>
-</merge>
diff --git a/quickstep/res/layout/taskbar_edu_pages_transient.xml b/quickstep/res/layout/taskbar_edu_pages_transient.xml
deleted file mode 100644
index b68e723..0000000
--- a/quickstep/res/layout/taskbar_edu_pages_transient.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2022 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.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.TaskbarEdu.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_stashing" />
-
- <com.airbnb.lottie.LottieAnimationView
- android:id="@+id/animation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- app:lottie_rawRes="@raw/taskbar_edu_stashing_transient" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.TaskbarEdu.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_splitscreen" />
-
- <com.airbnb.lottie.LottieAnimationView
- android:id="@id/animation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- app:lottie_rawRes="@raw/taskbar_edu_splitscreen_transient" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical">
-
- <TextView
- style="@style/TextAppearance.TaskbarEdu.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_suggestions" />
-
- <com.airbnb.lottie.LottieAnimationView
- android:id="@id/animation"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- app:lottie_rawRes="@raw/taskbar_edu_suggestions_transient" />
- </LinearLayout>
-</merge>
\ No newline at end of file
diff --git a/quickstep/res/raw/taskbar_edu_stashing_transient.json b/quickstep/res/raw/taskbar_edu_stashing_transient.json
deleted file mode 100644
index 847a607..0000000
--- a/quickstep/res/raw/taskbar_edu_stashing_transient.json
+++ /dev/null
@@ -1 +0,0 @@
-{"v":"5.9.0","fr":60,"ip":0,"op":94,"w":412,"h":300,"nm":"Taskbar_Transient_Step_1_LT","ddd":0,"assets":[{"id":"comp_0","nm":"Taskbar_Transient_LT","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"press 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":381,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":391,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":416,"s":[100]},{"t":426,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[259.25,134,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":406,"s":[50,50,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":416,"s":[40,40,100]},{"t":426,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.186},"t":381,"s":[-37,67],"to":[15,-7],"ti":[7,20]},{"t":406,"s":[0,0],"h":1}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Touch","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":381,"op":437,"st":176,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"press","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":301,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":311,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":336,"s":[100]},{"t":346,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[248,134,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":326,"s":[50,50,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":336,"s":[40,40,100]},{"t":346,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.186},"t":301,"s":[-37,67],"to":[15,-7],"ti":[7,20]},{"t":326,"s":[0,0],"h":1}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Touch","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":301,"op":357,"st":96,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,194,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"ip":15,"op":73,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"swipe up","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[100]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":15,"s":[-48.3,37.417,0],"to":[5.5,9,0],"ti":[-12,-36,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":40,"s":[-15.3,91.417,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.45,"y":0},"t":50,"s":[-15.3,91.417,0],"to":[0,0,0],"ti":[0,0,0]},{"t":70,"s":[-15.3,-62.583,0],"h":1}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":40,"s":[100,100,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":50,"s":[80,80,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":60,"s":[80,80,100]},{"t":70,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":52,"s":[56,56]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":62,"s":[56,98]},{"t":72,"s":[56,56]}],"ix":2},"p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":52,"s":[0,0],"to":[0,0],"ti":[0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":62,"s":[0,14],"to":[0,0],"ti":[0,0]},{"t":72,"s":[0,0]}],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":15,"op":73,"st":-10,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"screen_matte","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[287,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"Pre-comp_TaskBar_Transient_LT","tt":1,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.7,"y":0},"t":50,"s":[204.5,244.501,0],"to":[0,-2.5,0],"ti":[0,2.5,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":94,"s":[204.5,229.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":356,"s":[204.5,229.501,0],"to":[0,1.333,0],"ti":[0,-1.333,0]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":386,"s":[204.5,237.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":436,"s":[204.5,237.501,0],"to":[0,-1.333,0],"ti":[0,1.333,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.3,"y":0.3},"t":466,"s":[204.5,229.501,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":474,"s":[204.5,229.501,0],"to":[-42.083,-12.917,0],"ti":[42.083,12.917,0]},{"t":554,"s":[-48,152.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[206,227.625,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":50,"s":[70,70,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":94,"s":[100,100,100]},{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":474,"s":[100,100,100]},{"t":554,"s":[370,370,100]}],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.9,"y":0},"t":46,"s":[205.5,241.5,0],"to":[0,-1.667,0],"ti":[0,1.667,0]},{"t":76,"s":[205.5,231.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.381,0],[0,0],[0,-1.381],[0,0],[1.381,0],[0,0],[0,1.381],[0,0]],"o":[[0,0],[1.381,0],[0,0],[0,1.381],[0,0],[-1.381,0],[0,0],[0,-1.381]],"v":[[-42,-2.5],[42,-2.5],[44.5,0],[44.5,0],[42,2.5],[-42,2.5],[-44.5,0],[-44.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":65,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"Pre-comp_Toggle_LT","refId":"comp_2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":256,"s":[0]},{"i":{"x":[0.316],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":286,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":474,"s":[100]},{"t":554,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":235,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".blue100","cl":"blue100","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":249,"s":[0]},{"t":269,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[287,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":356,"s":[320,204.01]},{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":386,"s":[320,173.01]},{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":436,"s":[320,173.01]},{"t":466,"s":[320,204.01]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":12,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.549019607843,0.713725490196,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":356,"s":[-81,0],"to":[0,-2.542],"ti":[0,2.542]},{"i":{"x":0.1,"y":0.1},"o":{"x":0.167,"y":0.167},"t":386,"s":[-81,-15.25],"to":[0,0],"ti":[0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":436,"s":[-81,-15.25],"to":[0,2.542],"ti":[0,-2.542]},{"t":466,"s":[-81,0]}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":286,"op":11635,"st":235,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue100","cl":"blue100","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[132.562,150,0],"ix":2,"l":2},"a":{"a":0,"k":[-154.438,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":137,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":187,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":249,"s":[95,95,100]},{"t":269,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":187,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":249,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[0,-89.005],[0,89.005],[-13,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[-13,-102.005]],"c":true}]},{"t":269,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[13.125,-89.005],[13.125,89.005],[0.125,102.005],[-147,102.005],[-160,89.005],[-160,-89.005],[-147,-102.005],[0.125,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.549019607843,0.713725490196,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".blue100","cl":"blue100","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":137,"s":[100]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.8],"y":[0]},"t":187,"s":[0]},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":249,"s":[0]},{"t":259,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[279.438,150,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":137,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":187,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":249,"s":[95,95,100]},{"t":269,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":187,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":249,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"t":269,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.549019607843,0.713725490196,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".yellow100","cl":"yellow100","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[279.438,150,0],"ix":2,"l":2},"a":{"a":0,"k":[-7.562,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":137,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.8,0.8,0.167],"y":[0,0,0]},"t":187,"s":[95,95,100]},{"i":{"x":[0.1,0.1,0.833],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.167],"y":[0,0,0]},"t":249,"s":[95,95,100]},{"t":269,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.8,"y":0},"t":187,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"i":{"x":0.1,"y":1},"o":{"x":0.3,"y":0},"t":249,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[13,102.005],[0,89.005],[0,-89.005],[13,-102.005],[147,-102.005]],"c":true}]},{"t":269,"s":[{"i":[[0,-7.18],[0,0],[7.18,0],[0,0],[0,7.18],[0,0],[-7.18,0],[0,0]],"o":[[0,0],[0,7.18],[0,0],[-7.18,0],[0,0],[0,-7.18],[0,0],[7.18,0]],"v":[[160,-89.005],[160,89.005],[147,102.005],[-0.125,102.005],[-13.125,89.005],[-13.125,-89.005],[-0.125,-102.005],[147,-102.005]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.98431372549,0.78431372549,0.274509803922,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":286,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[287,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[320,204.01],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-81,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":100,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[15.3,0],[0,0],[0,15.7],[0,0],[-15.3,0],[0,0],[0,-15.7],[0,0]],"o":[[0,0],[-15.3,0],[0,0],[0,-15.7],[0,0],[15.2,0],[0,0],[0,15.5]],"v":[[178.2,150],[-178.2,150],[-206,121.5],[-206,-121.5],[-178.2,-150],[178.3,-150],[206,-121.5],[206,121.7]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0}]},{"id":"comp_1","nm":"Pre-comp_TaskBar_Transient_LT","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[237.75,183,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"ip":102,"op":255,"st":90,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"swipe up 2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":100,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":110,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"t":177,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":100,"s":[-45.3,33.917,0],"to":[5.5,9,0],"ti":[-12,-36,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.333,"y":0.333},"t":127,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[-12.3,87.917,0],"to":[0,0,0],"ti":[-99.967,45.186,0]},{"t":187,"s":[89.5,-76.7,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.667],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.333],"y":[0,0,0]},"t":127,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"t":137,"s":[80,80,100]},{"i":{"x":[0.5,0.5,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"t":167,"s":[80,80,100]},{"t":179,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":63.75,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":8,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":30,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]},{"ty":25,"nm":"Drop Shadow 2","np":8,"mn":"ADBE Drop Shadow","ix":2,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":10.2,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":40,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":240,"s":[56,56]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":262,"s":[56,98]},{"t":288,"s":[56,56]}],"ix":2},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[0,0],"to":[0,0],"ti":[0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.8,"y":0},"t":187,"s":[0,14],"to":[0,0],"ti":[0,0]},{"t":189,"s":[0,0]}],"ix":3},"r":{"a":0,"k":67,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":50,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":102,"op":234,"st":77,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey300","cl":"grey300","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-83.044,0.454,0],"ix":2,"l":2},"a":{"a":0,"k":[121.456,227.454,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 18","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 17","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[125.547,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 16","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 15","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 14","np":1,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[121.453,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 13","np":1,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,231.545],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 12","np":1,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,227.455],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 11","np":1,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.753,0],[0,-0.753],[0.753,0],[0,0.753]],"o":[[0.753,0],[0,0.753],[-0.753,0],[0,-0.753]],"v":[[0,-1.364],[1.364,0],[0,1.364],[-1.364,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901960784,0.470588235294,0.486274509804,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[117.364,223.364],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 10","np":1,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"green circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":550,"s":[84.522,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":580,"s":[84.522,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"green circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.807843148708,0.917647063732,0.839215695858,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.807843137255,0.917647058824,0.839215686275,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".green400","cl":"green400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":553,"s":[84.522,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":583,"s":[84.522,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".green100","cl":"green100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84.409,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"blue circle matte 2","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":544,"s":[55.772,0.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":574,"s":[55.772,-19.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"blue circle matte","parent":20,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.541175991881,0.705881993911,0.972549019608,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":547,"s":[55.772,20.001,0],"to":[0,-3.333,0],"ti":[0,3.333,0]},{"t":577,"s":[55.772,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue100","cl":"blue100","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.772,0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.443,0],[0,-4.443],[4.443,0],[0,4.443]],"o":[[4.443,0],[0,4.443],[-4.443,0],[0,-4.443]],"v":[[0,-8.045],[8.045,0],[0,8.045],[-8.045,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":177,"s":[0]},{"t":187,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":947,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":957,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":967,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.596078431373,0.145098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":177,"op":11577,"st":177,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".yellow400","cl":"yellow400","parent":20,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"t":177,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":137,"s":[27.135,0.001,0],"to":[0.728,-9.542,0],"ti":[-45.478,19.292,0]},{"t":187,"s":[78,-76.749,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.941176470588,0.596078431373,0.145098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey400","cl":"grey400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":944,"s":[27.135,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":954,"s":[27.135,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":964,"s":[27.135,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":137,"op":252,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".green400","cl":"green400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":941,"s":[-1.498,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":951,"s":[-1.498,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":961,"s":[-1.498,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".red400","cl":"red400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":938,"s":[-30.134,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":948,"s":[-30.134,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":958,"s":[-30.134,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.403921574354,0.360784322023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".blue400","cl":"blue400","parent":20,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":935,"s":[-58.771,0.001,0],"to":[0,-0.625,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":945,"s":[-58.771,-3.749,0],"to":[0,0,0],"ti":[0,-0.625,0]},{"t":955,"s":[-58.771,0.001,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.272,0],[0,-5.272],[5.272,0],[0,5.272]],"o":[[5.272,0],[0,5.272],[-5.272,0],[0,-5.272]],"v":[[0,-9.545],[9.545,0],[0,9.545],[-9.545,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204.5,227.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0.001,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,0],[0,-8.284],[0,0],[8.284,0],[0,0],[0,8.284],[0,0]],"o":[[0,0],[8.284,0],[0,0],[0,8.284],[0,0],[-8.284,0],[0,0],[0,-8.284]],"v":[[-86.5,-15],[86.5,-15],[101.5,0],[101.5,0],[86.5,15],[-86.5,15],[-101.5,0],[-101.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":65,"op":11400,"st":0,"bm":0}]},{"id":"comp_2","nm":"Pre-comp_Toggle_LT","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".blue900","cl":"blue900","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":336,"s":[-12.5,0,0],"to":[3.75,0,0],"ti":[-3.75,0,0]},{"i":{"x":0.2,"y":0.2},"o":{"x":0.7,"y":0.7},"t":356,"s":[10,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":416,"s":[10,0,0],"to":[-3.75,0,0],"ti":[3.75,0,0]},{"t":436,"s":[-12.5,0,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.8,"y":0},"t":336,"s":[{"i":[[-6.627,0],[0,0],[0,-6.627],[0,0],[6.627,0],[0,0],[0,6.627],[0,0]],"o":[[0,0],[6.627,0],[0,0],[0,6.627],[0,0],[-6.627,0],[0,0],[0,-6.627]],"v":[[0,-12],[0,-12],[12,0],[12,0],[0,12],[0,12],[-12,0],[-12,0]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.8,"y":0},"t":356,"s":[{"i":[[-7.732,0],[0,0],[0,-7.732],[0,0],[7.732,0],[0,0],[0,7.732],[0,0]],"o":[[0,0],[7.732,0],[0,0],[0,7.732],[0,0],[-7.732,0],[0,0],[0,-7.732]],"v":[[0,-14],[0,-14],[14,0],[14,0],[0,14],[0,14],[-14,0],[-14,0]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0},"t":416,"s":[{"i":[[-7.732,0],[0,0],[0,-7.732],[0,0],[7.732,0],[0,0],[0,7.732],[0,0]],"o":[[0,0],[7.732,0],[0,0],[0,7.732],[0,0],[-7.732,0],[0,0],[0,-7.732]],"v":[[0,-14],[0,-14],[14,0],[14,0],[0,14],[0,14],[-14,0],[-14,0]],"c":true}]},{"t":436,"s":[{"i":[[-6.627,0],[0,0],[0,-6.627],[0,0],[6.627,0],[0,0],[0,6.627],[0,0]],"o":[[0,0],[6.627,0],[0,0],[0,6.627],[0,0],[-6.627,0],[0,0],[0,-6.627]],"v":[[0,-12],[0,-12],[12,0],[12,0],[0,12],[0,12],[-12,0],[-12,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.090196078431,0.305882352941,0.650980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".blue200","cl":"blue200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[254.5,133.75,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.837,0],[0,0],[0,-8.837],[0,0],[8.837,0],[0,0],[0,8.837],[0,0]],"o":[[0,0],[8.837,0],[0,0],[0,8.837],[0,0],[-8.837,0],[0,0],[0,-8.837]],"v":[[-10,-16],[10,-16],[26,0],[26,0],[10,16],[-10,16],[-26,0],[-26,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682352941176,0.796078431373,0.980392156863,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".blue100_T","cl":"blue100_T","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.784,0],[0,1.783],[1.783,0],[0,-1.783]],"o":[[1.783,0],[0,-1.783],[-1.784,0],[0,1.783]],"v":[[-43.755,-12.577],[-40.526,-15.806],[-43.755,-19.035],[-46.984,-15.806]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.053]],"o":[[0,0.053],[0,0]],"v":[[-44.937,-23.822],[-44.937,-23.822]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0.054]],"o":[[0,0.054],[0,0]],"v":[[-49.458,-21.078],[-49.458,-21.078]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[-0.431,0.269],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0.215],[0,0.215],[0,0],[0,0],[0,0],[0,0],[0,0],[0.431,0.161],[0,0],[0,0],[0,0],[0,0],[0,0],[0.431,-0.269],[0,0],[0,0],[0,0],[0,0],[0,0],[0,-0.216],[-0.054,-0.215],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.431,-0.162],[0,0]],"o":[[0,0],[0,0],[0,0],[0.431,-0.162],[0,0],[0,0],[0,0],[0,0],[0,0],[0.054,-0.215],[0,-0.269],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.377,-0.269],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.431,0.161],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0.215],[0,0.215],[0,0],[0,0],[0,0],[0,0],[0,0],[0.377,0.323],[0,0],[0,0]],"v":[[-45.045,-8.215],[-42.515,-8.215],[-42.138,-10.529],[-41.654,-10.744],[-40.416,-11.444],[-39.986,-11.767],[-37.779,-10.906],[-36.487,-13.112],[-38.371,-14.565],[-38.317,-15.104],[-38.263,-15.803],[-38.317,-16.503],[-38.371,-17.041],[-36.487,-18.494],[-37.779,-20.701],[-39.986,-19.84],[-40.416,-20.163],[-41.654,-20.862],[-42.138,-21.078],[-42.461,-23.392],[-44.991,-23.392],[-45.314,-21.078],[-45.798,-20.862],[-47.036,-20.163],[-47.467,-19.84],[-49.673,-20.701],[-50.965,-18.494],[-49.081,-17.041],[-49.135,-16.503],[-49.189,-15.803],[-49.135,-15.104],[-49.081,-14.565],[-50.965,-13.112],[-49.673,-10.906],[-47.467,-11.767],[-47.036,-11.444],[-45.798,-10.744],[-45.368,-10.529]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0.054,0]],"o":[[0.054,0],[0,0]],"v":[[-44.991,-7.784],[-44.991,-7.784]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0.7,0],[0,0],[0.108,0.7],[0,0],[0.215,0.162],[0,0],[0.323,0.592],[0,0],[-0.484,0.376],[0,0],[0,0.161],[0,0.162],[0,0],[-0.376,0.593],[0,0],[-0.592,-0.215],[0,0],[-0.215,0.162],[0,0],[-0.7,0],[0,0],[-0.107,-0.7],[0,0],[-0.269,-0.162],[0,0],[-0.323,-0.592],[0,0],[0.484,-0.377],[0,0],[0,-0.162],[0,-0.161],[0,0],[0.323,-0.592],[0,0],[0.646,0.215],[0,0],[0.216,-0.162],[0,0]],"o":[[0,0],[-0.7,0],[0,0],[-0.269,-0.108],[0,0],[-0.646,0.215],[0,0],[-0.323,-0.592],[0,0],[0,-0.161],[0,-0.162],[0,0],[-0.538,-0.431],[0,0],[0.323,-0.592],[0,0],[0.215,-0.162],[0,0],[0.053,-0.646],[0,0],[0.699,0],[0,0],[0.269,0.108],[0,0],[0.646,-0.215],[0,0],[0.323,0.592],[0,0],[0,0.161],[0,0.161],[0,0],[0.538,0.431],[0,0],[-0.323,0.592],[0,0],[-0.215,0.161],[0,0],[0,0.538]],"v":[[-42.085,-6.385],[-45.475,-6.385],[-46.821,-7.569],[-47.09,-9.291],[-47.789,-9.722],[-49.458,-9.076],[-51.126,-9.668],[-52.795,-12.574],[-52.472,-14.296],[-51.072,-15.373],[-51.072,-15.803],[-51.072,-16.234],[-52.472,-17.31],[-52.795,-19.033],[-51.126,-21.939],[-49.512,-22.531],[-47.843,-21.831],[-47.144,-22.262],[-46.874,-24.038],[-45.529,-25.168],[-42.138,-25.168],[-40.793,-23.984],[-40.524,-22.262],[-39.77,-21.831],[-38.102,-22.477],[-36.433,-21.885],[-34.765,-18.979],[-35.088,-17.256],[-36.487,-16.18],[-36.487,-15.749],[-36.487,-15.319],[-35.088,-14.243],[-34.765,-12.52],[-36.487,-9.56],[-38.156,-8.968],[-39.824,-9.614],[-40.524,-9.183],[-40.793,-7.407]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":6,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-43.792,-15.776],"ix":2},"a":{"a":0,"k":[-43.792,-15.776],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".blue400","cl":"blue400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,0],[0,-8.284],[0,0],[8.284,0],[0,0],[0,8.284],[0,0]],"o":[[0,0],[8.284,0],[0,0],[0,8.284],[0,0],[-8.284,0],[0,0],[0,-8.284]],"v":[[-54,-33],[60,-33],[75,-18],[75,-13],[60,2],[-54,2],[-69,-13],[-69,-18]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.137254901961,0.462745098039,0.898039215686,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":11400,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Taskbar_Transient_LT","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":11400,"st":0,"bm":0}],"markers":[{"tm":94,"cm":"","dr":0},{"tm":249,"cm":"","dr":0},{"tm":474,"cm":"","dr":0}]}
\ No newline at end of file
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 09ea534..2c17ce8 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -241,10 +241,6 @@
<!-- ******* Taskbar Edu ******* -->
<!-- Accessibility title for the Taskbar education window. [CHAR_LIMIT=NONE] -->
<string name="taskbar_edu_a11y_title">Taskbar education</string>
- <!-- Accessibility text spoken when the Taskbar education panel appears [CHAR_LIMIT=NONE] -->
- <string name="taskbar_edu_opened">Taskbar education appeared</string>
- <!-- Accessibility text spoken when the Taskbar education panel disappears [CHAR_LIMIT=NONE] -->
- <string name="taskbar_edu_closed">Taskbar education closed</string>
<!-- Text in dialog that lets a user know how they can use the Taskbar to use multiple apps at once on their device. [CHAR_LIMIT=60] -->
<string name="taskbar_edu_splitscreen">Drag an app to the side to use 2 apps at once</string>
<!-- Text in dialog that lets a user know how they can show the Taskbar on their device. [CHAR_LIMIT=60] -->
@@ -255,10 +251,6 @@
<string name="taskbar_edu_settings_persistent">Turn on gesture navigation in Settings to auto-hide the Taskbar</string>
<!-- Title in dialog that shows a user what they can do with the Taskbar. [CHAR_LIMIT=60] -->
<string name="taskbar_edu_features">Do more with the Taskbar</string>
- <!-- Text on button to go to the next screen of a tutorial [CHAR_LIMIT=16] -->
- <string name="taskbar_edu_next">Next</string>
- <!-- Text on button to go to the previous screen of a tutorial [CHAR_LIMIT=16] -->
- <string name="taskbar_edu_previous">Back</string>
<!-- Text on button to exit a tutorial [CHAR_LIMIT=16] -->
<string name="taskbar_edu_close">Close</string>
<!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 8eea37f..f9f2175 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -195,30 +195,13 @@
<item name="iconDisplay">taskbar</item>
</style>
- <style name="TaskbarEdu.Button.Close" parent="@android:style/Widget.Material.Button">
- <item name="android:background">@drawable/button_taskbar_edu_bordered</item>
- <item name="android:stateListAnimator">@null</item>
- <item name="android:textSize">16sp</item>
- <item name="android:padding">4dp</item>
- </style>
-
- <style name="TaskbarEdu.Button.Next" parent="@android:style/Widget.Material.Button">
+ <style name="TaskbarEdu.Button.Done" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/button_taskbar_edu_colored</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:textSize">16sp</item>
<item name="android:padding">4dp</item>
</style>
- <style name="TextAppearance.TaskbarEdu.Title"
- parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" >
- <item name="android:layout_marginHorizontal">16dp</item>
- <item name="android:gravity">center_horizontal</item>
- <item name="android:fontFamily">google-sans</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textSize">24sp</item>
- <item name="android:lines">2</item>
- </style>
-
<style name="TextAppearance.TaskbarEduTooltip.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
<item name="android:gravity">center_horizontal</item>
<item name="android:fontFamily">google-sans</item>
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 2e1318b..bc97df1 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -48,11 +48,15 @@
import android.util.Log;
import android.util.StatsEvent;
+import androidx.annotation.AnyThread;
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -62,6 +66,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.PersistedItemArray;
import com.android.quickstep.logging.SettingsChangeLogger;
@@ -111,45 +116,80 @@
mStatsManager = context.getSystemService(StatsManager.class);
}
+ @CallSuper
@Override
- public void loadHotseatItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
- // TODO: Implement caching and preloading
- super.loadHotseatItems(ums, pinnedShortcuts);
-
- WorkspaceItemFactory hotseatFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
- mIDP.numDatabaseHotseatIcons, mHotseatState.containerId);
- FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
- mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
- mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
+ public void loadAndBindWorkspaceItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ loadAndBindItems(ums, pinnedShortcuts, callbacks, mIDP.numDatabaseHotseatIcons,
+ mHotseatState);
}
+ @CallSuper
@Override
- public void loadAllAppsItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
- // TODO: Implement caching and preloading
- super.loadAllAppsItems(ums, pinnedShortcuts);
-
- WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
- mIDP.numDatabaseAllAppsColumns, mAllAppsState.containerId);
- FixedContainerItems allAppsPredictionItems = new FixedContainerItems(
- mAllAppsState.containerId, mAllAppsState.storage.read(mApp.getContext(),
- allAppsFactory, ums.allUsers::get));
- mDataModel.extraItems.put(mAllAppsState.containerId, allAppsPredictionItems);
+ public void loadAndBindAllAppsItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
+ loadAndBindItems(ums, pinnedShortcuts, callbacks, mIDP.numDatabaseAllAppsColumns,
+ mAllAppsState);
}
- @Override
- public void loadWidgetsRecommendationItems() {
+ @WorkerThread
+ private void loadAndBindItems(@NonNull UserManagerState ums,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ int numColumns, @NonNull PredictorState state) {
// TODO: Implement caching and preloading
- super.loadWidgetsRecommendationItems();
+
+ WorkspaceItemFactory factory =
+ new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, numColumns, state.containerId);
+ FixedContainerItems fci = new FixedContainerItems(state.containerId,
+ state.storage.read(mApp.getContext(), factory, ums.allUsers::get));
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ bindPredictionItems(callbacks, fci);
+ }
+ mDataModel.extraItems.put(state.containerId, fci);
+ }
+
+ @CallSuper
+ @Override
+ public void loadAndBindOtherItems(@NonNull BgDataModel.Callbacks[] callbacks) {
+ FixedContainerItems widgetPredictionFCI = new FixedContainerItems(
+ mWidgetsRecommendationState.containerId, new ArrayList<>());
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
- mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
- new FixedContainerItems(mWidgetsRecommendationState.containerId,
- new ArrayList<>()));
+ mDataModel.extraItems.put(mWidgetsRecommendationState.containerId, widgetPredictionFCI);
+
+ bindPredictionItems(callbacks, widgetPredictionFCI);
+ loadStringCache(mDataModel.stringCache);
+ }
+
+ @AnyThread
+ private void bindPredictionItems(@NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull FixedContainerItems fci) {
+ Executors.MAIN_EXECUTOR.execute(() -> {
+ for (BgDataModel.Callbacks c : callbacks) {
+ c.bindExtraContainerItems(fci);
+ }
+ });
}
@Override
+ @WorkerThread
+ public void bindAllModelExtras(@NonNull BgDataModel.Callbacks[] callbacks) {
+ Iterable<FixedContainerItems> containerItems;
+ synchronized (mDataModel.extraItems) {
+ containerItems = mDataModel.extraItems.clone();
+ }
+ Executors.MAIN_EXECUTOR.execute(() -> {
+ for (BgDataModel.Callbacks c : callbacks) {
+ for (FixedContainerItems fci : containerItems) {
+ c.bindExtraContainerItems(fci);
+ }
+ }
+ });
+ }
+
public void markActive() {
super.markActive();
mActive = true;
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index d8fd51a..003c2fc 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -47,11 +47,7 @@
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.RemoteActionShortcut;
import com.android.launcher3.popup.SystemShortcut;
@@ -73,21 +69,14 @@
private static final int[] RETRY_TIMES_MS = {5000, 15000, 30000};
private static final boolean DEBUG = false;
- private static final int UNKNOWN_MINIMAL_DEVICE_STATE = 0;
- private static final int IN_MINIMAL_DEVICE = 2;
-
// Welbeing contract
private static final String PATH_ACTIONS = "actions";
- private static final String PATH_MINIMAL_DEVICE = "minimal_device";
- private static final String METHOD_GET_MINIMAL_DEVICE_CONFIG = "get_minimal_device_config";
private static final String METHOD_GET_ACTIONS = "get_actions";
private static final String EXTRA_ACTIONS = "actions";
private static final String EXTRA_ACTION = "action";
private static final String EXTRA_MAX_NUM_ACTIONS_SHOWN = "max_num_actions_shown";
private static final String EXTRA_PACKAGES = "packages";
private static final String EXTRA_SUCCESS = "success";
- private static final String EXTRA_MINIMAL_DEVICE_STATE = "minimal_device_state";
- private static final String DB_NAME_MINIMAL_DEVICE = "minimal.db";
public static final MainThreadInitializedObject<WellbeingModel> INSTANCE =
new MainThreadInitializedObject<>(WellbeingModel::new);
@@ -137,36 +126,7 @@
@WorkerThread
private void onWellbeingUriChanged(Uri uri) {
Preconditions.assertNonUiThread();
- if (DEBUG || mIsInTest) {
- Log.d(TAG, "ContentObserver.onChange() called with: uri = [" + uri + "]");
- }
- if (uri.getPath().contains(PATH_ACTIONS)) {
- // Wellbeing reports that app actions have changed.
- updateAllPackages();
- } else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) {
- // Wellbeing reports that minimal device state or config is changed.
- if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
- return;
- }
-
- // Temporary bug fix for b/169771796. Wellbeing provides the layout configuration when
- // minimal device is enabled. We always want to reload the configuration from Wellbeing
- // since the layout configuration might have changed.
- mContext.deleteDatabase(DB_NAME_MINIMAL_DEVICE);
-
- final Bundle extras = new Bundle();
- String dbFile;
- if (isInMinimalDeviceMode()) {
- dbFile = DB_NAME_MINIMAL_DEVICE;
- extras.putString(LauncherProvider.KEY_LAYOUT_PROVIDER_AUTHORITY,
- mWellbeingProviderPkg + ".api");
- } else {
- dbFile = InvariantDeviceProfile.INSTANCE.get(mContext).dbFile;
- }
- LauncherSettings.Settings.call(mContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_SWITCH_DATABASE,
- dbFile, extras);
- }
+ updateAllPackages();
}
public void setInTest(boolean inTest) {
@@ -178,12 +138,9 @@
final ContentResolver resolver = mContext.getContentResolver();
resolver.unregisterContentObserver(mContentObserver);
Uri actionsUri = apiBuilder().path(PATH_ACTIONS).build();
- Uri minimalDeviceUri = apiBuilder().path(PATH_MINIMAL_DEVICE).build();
try {
resolver.registerContentObserver(
actionsUri, true /* notifyForDescendants */, mContentObserver);
- resolver.registerContentObserver(
- minimalDeviceUri, true /* notifyForDescendants */, mContentObserver);
} catch (Exception e) {
Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e);
if (mIsInTest) throw new RuntimeException(e);
@@ -228,32 +185,6 @@
}
@WorkerThread
- private boolean isInMinimalDeviceMode() {
- if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
- return false;
- }
- if (DEBUG || mIsInTest) {
- Log.d(TAG, "isInMinimalDeviceMode() called");
- }
- Preconditions.assertNonUiThread();
-
- final Uri contentUri = apiBuilder().build();
- try (ContentProviderClient client = mContext.getContentResolver()
- .acquireUnstableContentProviderClient(contentUri)) {
- final Bundle remoteBundle = client == null ? null : client.call(
- METHOD_GET_MINIMAL_DEVICE_CONFIG, null /* args */, null /* extras */);
- return remoteBundle != null
- && remoteBundle.getInt(EXTRA_MINIMAL_DEVICE_STATE,
- UNKNOWN_MINIMAL_DEVICE_STATE) == IN_MINIMAL_DEVICE;
- } catch (Exception e) {
- Log.e(TAG, "Failed to retrieve data from " + contentUri + ": " + e);
- if (mIsInTest) throw new RuntimeException(e);
- }
- if (DEBUG || mIsInTest) Log.i(TAG, "isInMinimalDeviceMode(): finished");
- return false;
- }
-
- @WorkerThread
private boolean updateActions(String[] packageNames) {
if (packageNames.length == 0) {
return true;
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 3a985c4..b74964c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
@@ -252,13 +251,6 @@
return;
}
- // Transient and persistent bottom sheet.
- if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
- mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
- mControllers.taskbarEduController.showEdu();
- return;
- }
-
// Persistent features EDU tooltip.
if (!DisplayController.isTransientTaskbar(mLauncher)) {
mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
@@ -277,11 +269,6 @@
return false;
}
- // Transient and persistent bottom sheet.
- if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
- return !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
- }
-
// Persistent features EDU tooltip.
if (!DisplayController.isTransientTaskbar(mLauncher)) {
return !mLauncher.getOnboardingPrefs().hasReachedMaxCount(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index b61e9fc..5c53b5f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -224,7 +224,6 @@
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
- new TaskbarEduController(this),
new TaskbarAutohideSuspendController(this),
new TaskbarPopupController(this),
new TaskbarForceVisibleImmersiveController(this),
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index a71e5db..8efb9b0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -48,7 +48,6 @@
public final TaskbarKeyguardController taskbarKeyguardController;
public final StashedHandleViewController stashedHandleViewController;
public final TaskbarStashController taskbarStashController;
- public final TaskbarEduController taskbarEduController;
public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
public final TaskbarPopupController taskbarPopupController;
public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
@@ -95,7 +94,6 @@
TaskbarKeyguardController taskbarKeyguardController,
StashedHandleViewController stashedHandleViewController,
TaskbarStashController taskbarStashController,
- TaskbarEduController taskbarEduController,
TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
TaskbarPopupController taskbarPopupController,
TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
@@ -120,7 +118,6 @@
this.taskbarKeyguardController = taskbarKeyguardController;
this.stashedHandleViewController = stashedHandleViewController;
this.taskbarStashController = taskbarStashController;
- this.taskbarEduController = taskbarEduController;
this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
this.taskbarPopupController = taskbarPopupController;
this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
@@ -155,7 +152,6 @@
taskbarSpringOnStashController.init(this);
stashedHandleViewController.init(this);
taskbarStashController.init(this, sharedState.setupUIVisible, mSharedState);
- taskbarEduController.init(this);
taskbarPopupController.init(this);
taskbarForceVisibleImmersiveController.init(this);
taskbarOverlayController.init(this);
@@ -172,7 +168,7 @@
taskbarDragController, navButtonController, navbarButtonsViewController,
taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
taskbarUnfoldAnimationController, taskbarKeyguardController,
- stashedHandleViewController, taskbarStashController, taskbarEduController,
+ stashedHandleViewController, taskbarStashController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
voiceInteractionWindowController, taskbarTranslationController,
taskbarEduTooltipController, keyboardQuickSwitchController
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 66a903b..41093bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -55,7 +55,6 @@
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragDriver;
import com.android.launcher3.dragndrop.DragOptions;
@@ -188,12 +187,10 @@
DragOptions dragOptions = new DragOptions();
dragOptions.preDragCondition = null;
- if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
- PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
- mControllers.taskbarPopupController.showForIcon(btv);
- if (popupContainer != null) {
- dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
- }
+ PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
+ mControllers.taskbarPopupController.showForIcon(btv);
+ if (popupContainer != null) {
+ dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
}
if (dragOptions.preDragCondition == null) {
dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
@@ -208,8 +205,7 @@
public void onPreDragStart(DropTarget.DragObject dragObject) {
mDragView = dragObject.dragView;
- if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()
- && !shouldStartDrag(0)) {
+ if (!shouldStartDrag(0)) {
mDragView.setOnAnimationEndCallback(() -> {
// Drag might be cancelled during the DragView animation, so check
// mIsPreDrag again.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
deleted file mode 100644
index d1b8644..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ /dev/null
@@ -1,131 +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.taskbar;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
-import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
-import com.android.launcher3.util.DisplayController;
-
-import com.airbnb.lottie.LottieAnimationView;
-
-import java.io.PrintWriter;
-
-/** Handles the Taskbar Education flow. */
-public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarController {
-
- private final TaskbarActivityContext mActivity;
-
- // Initialized in init.
- TaskbarControllers mControllers;
-
- private TaskbarEduView mTaskbarEduView;
- private TaskbarEduPagedView mPagedView;
-
- public TaskbarEduController(TaskbarActivityContext activity) {
- mActivity = activity;
- }
-
- public void init(TaskbarControllers controllers) {
- mControllers = controllers;
- }
-
- void showEdu() {
- TaskbarOverlayController overlayController = mControllers.taskbarOverlayController;
- TaskbarOverlayContext overlayContext = overlayController.requestWindow();
- LayoutInflater layoutInflater = overlayContext.getLayoutInflater();
-
- mTaskbarEduView = (TaskbarEduView) layoutInflater.inflate(
- R.layout.taskbar_edu, overlayContext.getDragLayer(), false);
- mPagedView = mTaskbarEduView.findViewById(R.id.content);
- layoutInflater.inflate(
- DisplayController.isTransientTaskbar(overlayContext)
- ? R.layout.taskbar_edu_pages_transient
- : R.layout.taskbar_edu_pages_persistent,
- mPagedView,
- true);
-
- // Provide enough room for taskbar.
- View startButton = mTaskbarEduView.findViewById(R.id.edu_start_button);
- ViewGroup.MarginLayoutParams layoutParams =
- (ViewGroup.MarginLayoutParams) startButton.getLayoutParams();
- DeviceProfile dp = overlayContext.getDeviceProfile();
- layoutParams.bottomMargin += dp.taskbarHeight + dp.taskbarBottomMargin;
-
- mTaskbarEduView.init(new TaskbarEduCallbacks());
-
- mControllers.navbarButtonsViewController.setSlideInViewVisible(true);
- mTaskbarEduView.setOnCloseBeginListener(
- () -> mControllers.navbarButtonsViewController.setSlideInViewVisible(false));
- mTaskbarEduView.addOnCloseListener(() -> mTaskbarEduView = null);
- mTaskbarEduView.show();
- }
-
- @Override
- public void dumpLogs(String prefix, PrintWriter pw) {
- pw.println(prefix + "TaskbarEduController:");
- pw.println(prefix + "\tisShowingEdu=" + (mTaskbarEduView != null));
- }
-
- /**
- * Callbacks for {@link TaskbarEduView} to interact with its controller.
- */
- class TaskbarEduCallbacks {
- void onPageChanged(int prevPage, int currentPage, int pageCount) {
- // Reset previous pages' animation.
- LottieAnimationView prevAnimation = mPagedView.getChildAt(prevPage)
- .findViewById(R.id.animation);
- prevAnimation.cancelAnimation();
- prevAnimation.setFrame(0);
-
- mPagedView.getChildAt(currentPage)
- .<LottieAnimationView>findViewById(R.id.animation)
- .playAnimation();
-
- if (currentPage == 0) {
- mTaskbarEduView.updateStartButton(R.string.taskbar_edu_close,
- v -> mTaskbarEduView.close(true /* animate */));
- } else {
- mTaskbarEduView.updateStartButton(R.string.taskbar_edu_previous,
- v -> mTaskbarEduView.snapToPage(currentPage - 1));
- }
- if (currentPage == pageCount - 1) {
- mTaskbarEduView.updateEndButton(R.string.taskbar_edu_done,
- v -> mTaskbarEduView.close(true /* animate */));
- } else {
- mTaskbarEduView.updateEndButton(R.string.taskbar_edu_next,
- v -> mTaskbarEduView.snapToPage(currentPage + 1));
- }
- }
-
- int getIconLayoutBoundsWidth() {
- return mControllers.taskbarViewController.getIconLayoutWidth();
- }
-
- int getOpenDuration() {
- return mControllers.taskbarOverlayController.getOpenDuration();
- }
-
- int getCloseDuration() {
- return mControllers.taskbarOverlayController.getCloseDuration();
- }
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
deleted file mode 100644
index d0e6386..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
+++ /dev/null
@@ -1,79 +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.taskbar;
-
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_EDUCATION_DIALOG;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.PagedView;
-import com.android.launcher3.R;
-import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
-import com.android.launcher3.taskbar.TaskbarEduController.TaskbarEduCallbacks;
-import com.android.launcher3.views.ActivityContext;
-
-/** Horizontal carousel of tutorial screens for Taskbar Edu. */
-public class TaskbarEduPagedView extends PagedView<LauncherDotsPageIndicator> {
-
- private TaskbarEduView mTaskbarEduView;
- private TaskbarEduCallbacks mControllerCallbacks;
-
- public TaskbarEduPagedView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- void setTaskbarEduView(TaskbarEduView taskbarEduView) {
- mTaskbarEduView = taskbarEduView;
- mPageIndicator = taskbarEduView.findViewById(R.id.content_page_indicator);
- initParentViews(taskbarEduView);
- }
-
- void setControllerCallbacks(TaskbarEduCallbacks controllerCallbacks) {
- mControllerCallbacks = controllerCallbacks;
- mControllerCallbacks.onPageChanged(getCurrentPage(), getCurrentPage(), getPageCount());
- }
-
- @Override
- protected int getChildGap(int fromIndex, int toIndex) {
- return mTaskbarEduView.getPaddingLeft() + mTaskbarEduView.getPaddingRight();
- }
-
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- if (mMaxScroll > 0) {
- mPageIndicator.setScroll(l, mMaxScroll);
- }
- }
-
- @Override
- protected void notifyPageSwitchListener(int prevPage) {
- super.notifyPageSwitchListener(prevPage);
- mControllerCallbacks.onPageChanged(prevPage, getCurrentPage(), getPageCount());
- }
-
- @Override
- protected boolean canScroll(float absVScroll, float absHScroll) {
- return AbstractFloatingView.getTopOpenViewWithType(
- ActivityContext.lookupContext(getContext()),
- TYPE_ALL & ~TYPE_TASKBAR_EDUCATION_DIALOG) == null;
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 22ed284..4373a88 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -31,7 +31,6 @@
import com.airbnb.lottie.model.KeyPath
import com.android.launcher3.R
import com.android.launcher3.Utilities
-import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
@@ -59,7 +58,7 @@
LoggableTaskbarController {
private val isTooltipEnabled: Boolean
- get() = !Utilities.isRunningInTestHarness() && ENABLE_TASKBAR_EDU_TOOLTIP.get()
+ get() = !Utilities.isRunningInTestHarness()
private val isOpen: Boolean
get() = tooltip?.isOpen ?: false
val isBeforeTooltipFeaturesStep: Boolean
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
deleted file mode 100644
index 5702b6b..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
+++ /dev/null
@@ -1,183 +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.taskbar;
-
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-
-import android.animation.PropertyValuesHolder;
-import android.content.Context;
-import android.graphics.Rect;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.View;
-import android.view.animation.Interpolator;
-import android.widget.Button;
-
-import com.android.launcher3.Insettable;
-import com.android.launcher3.R;
-import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
-import com.android.launcher3.views.AbstractSlideInView;
-
-/** Education view about the Taskbar. */
-public class TaskbarEduView extends AbstractSlideInView<TaskbarOverlayContext>
- implements Insettable {
-
- private final Rect mInsets = new Rect();
-
- // Initialized in init.
- private TaskbarEduController.TaskbarEduCallbacks mTaskbarEduCallbacks;
-
- private Button mStartButton;
- private Button mEndButton;
- private TaskbarEduPagedView mPagedView;
-
- public TaskbarEduView(Context context, AttributeSet attr) {
- this(context, attr, 0);
- }
-
- public TaskbarEduView(Context context, AttributeSet attrs,
- int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- protected void init(TaskbarEduController.TaskbarEduCallbacks callbacks) {
- if (mPagedView != null) {
- mPagedView.setControllerCallbacks(callbacks);
- }
- mTaskbarEduCallbacks = callbacks;
- }
-
- @Override
- protected void handleClose(boolean animate) {
- handleClose(animate, mTaskbarEduCallbacks.getCloseDuration());
- }
-
- @Override
- protected Interpolator getIdleInterpolator() {
- return EMPHASIZED;
- }
-
- @Override
- protected boolean isOfType(int type) {
- return (type & TYPE_TASKBAR_EDUCATION_DIALOG) != 0;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mContent = findViewById(R.id.edu_view);
- mStartButton = findViewById(R.id.edu_start_button);
- mEndButton = findViewById(R.id.edu_end_button);
- mPagedView = findViewById(R.id.content);
- mPagedView.setTaskbarEduView(this);
- }
-
- @Override
- public void setInsets(Rect insets) {
- mInsets.set(insets);
- mContent.setPadding(mContent.getPaddingStart(),
- mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom);
- }
-
- @Override
- protected void attachToContainer() {
- if (mColorScrim != null) {
- getPopupContainer().addView(mColorScrim, 0);
- }
- getPopupContainer().addView(this, 1);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int contentWidth = Math.min(getContentAreaWidth(), getMeasuredWidth());
- contentWidth = Math.max(contentWidth, mTaskbarEduCallbacks.getIconLayoutBoundsWidth());
- int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY);
-
- mContent.measure(contentAreaWidthSpec, MeasureSpec.UNSPECIFIED);
- }
-
- private int getContentAreaWidth() {
- return mTaskbarEduCallbacks.getIconLayoutBoundsWidth()
- + getResources().getDimensionPixelSize(R.dimen.taskbar_edu_horizontal_margin) * 2;
- }
-
- /** Show the Education flow. */
- public void show() {
- attachToContainer();
- animateOpen();
- }
-
- @Override
- protected Pair<View, String> getAccessibilityTarget() {
- return Pair.create(mContent, mIsOpen ? getContext().getString(R.string.taskbar_edu_opened)
- : getContext().getString(R.string.taskbar_edu_closed));
- }
-
- @Override
- protected int getScrimColor(Context context) {
- return context.getResources().getColor(R.color.widgets_picker_scrim);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int width = r - l;
- int height = b - t;
-
- // Lay out the content as center bottom aligned.
- int contentWidth = mContent.getMeasuredWidth();
- int contentLeft = (width - contentWidth - mInsets.left - mInsets.right) / 2 + mInsets.left;
- mContent.layout(contentLeft, height - mContent.getMeasuredHeight(),
- contentLeft + contentWidth, height);
-
- setTranslationShift(mTranslationShift);
- }
-
- private void animateOpen() {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
- return;
- }
- mIsOpen = true;
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(EMPHASIZED);
- mOpenCloseAnimator.setDuration(mTaskbarEduCallbacks.getOpenDuration()).start();
- }
-
- void snapToPage(int page) {
- mPagedView.snapToPage(page);
- }
-
- void updateStartButton(int textResId, OnClickListener onClickListener) {
- mStartButton.setText(textResId);
- mStartButton.setOnClickListener(onClickListener);
- }
-
- void updateEndButton(int textResId, OnClickListener onClickListener) {
- mEndButton.setText(textResId);
- mEndButton.setOnClickListener(onClickListener);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 5fedb3d..fcb2042 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -98,7 +98,8 @@
windowLayoutParams.providedInsets =
arrayOf(
InsetsFrameProvider(insetsOwner, 0, navigationBars()),
- InsetsFrameProvider(insetsOwner, 0, tappableElement())
+ InsetsFrameProvider(insetsOwner, 0, tappableElement()),
+ InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures())
)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 5bb958a..610efeb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
@@ -265,6 +266,7 @@
}
private void navigateHome() {
+ TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
index c10b57a..054689b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
@@ -32,7 +32,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -75,7 +74,7 @@
@Override
protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
- if (ShortcutUtil.supportsShortcuts(item) && FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
+ if (ShortcutUtil.supportsShortcuts(item)) {
out.add(mActions.get(NotificationListener.getInstanceIfConnected() != null
? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 5f11740..69ea9fd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -36,6 +36,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -43,6 +44,7 @@
import android.app.RemoteAction;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
+import android.os.SystemClock;
import android.util.Log;
import android.view.InsetsController;
import android.view.View;
@@ -187,6 +189,10 @@
// Auto stashes when user has not interacted with the Taskbar after X ms.
private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000;
+ // Duration for which an unlock event is considered "current", as other events are received
+ // asynchronously.
+ private static final long UNLOCK_TRANSITION_MEMOIZATION_MS = 200;
+
/**
* The default stash animation, morphing the taskbar into the navbar.
*/
@@ -743,56 +749,77 @@
private void createTransientAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
@StashAnimation int animationType) {
- Interpolator skipInterpolator = null;
+ // Target values of the properties this is going to set
+ final float backgroundOffsetTarget = isStashed ? 1 : 0;
+ final float iconAlphaTarget = isStashed ? 0 : 1;
+ final float stashedHandleAlphaTarget = isStashed ? 1 : 0;
+
+ // Timing for the alpha values depend on the animation played
+ long iconAlphaStartDelay = 0, iconAlphaDuration = 0, stashedHandleAlphaDelay = 0,
+ stashedHandleAlphaDuration = 0;
+ if (duration > 0) {
+ if (animationType == TRANSITION_HANDLE_FADE) {
+ // When fading, the handle fades in/out at the beginning of the transition with
+ // TASKBAR_STASH_ALPHA_DURATION.
+ stashedHandleAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+ // The iconAlphaDuration must be set to duration for the skippable interpolators
+ // below to work.
+ iconAlphaDuration = duration;
+ } else {
+ iconAlphaStartDelay = TASKBAR_STASH_ALPHA_START_DELAY;
+ iconAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+ stashedHandleAlphaDuration = TASKBAR_STASH_ALPHA_DURATION;
+
+ if (isStashed) {
+ if (animationType == TRANSITION_HOME_TO_APP) {
+ iconAlphaStartDelay = TASKBAR_STASH_ICON_ALPHA_HOME_TO_APP_START_DELAY;
+ }
+ stashedHandleAlphaDelay = iconAlphaStartDelay;
+ stashedHandleAlphaDuration = Math.max(0, duration - iconAlphaStartDelay);
+ }
+
+ }
+ }
+
+ play(as, mTaskbarStashedHandleAlpha.animateToValue(stashedHandleAlphaTarget),
+ stashedHandleAlphaDelay,
+ stashedHandleAlphaDuration, LINEAR);
+
+ // The rest of the animations might be "skipped" in TRANSITION_HANDLE_FADE transitions.
+ AnimatorSet skippable = as;
+ if (animationType == TRANSITION_HANDLE_FADE) {
+ skippable = new AnimatorSet();
+ as.play(skippable);
+ skippable.setInterpolator(isStashed ? INSTANT : FINAL_FRAME);
+ }
+
+ final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
+ if (animateBg) {
+ play(skippable, mTaskbarBackgroundOffset.animateToValue(backgroundOffsetTarget), 0,
+ duration, EMPHASIZED);
+ } else {
+ skippable.addListener(AnimatorListeners.forEndCallback(
+ () -> mTaskbarBackgroundOffset.updateValue(backgroundOffsetTarget)));
+ }
+
+ play(skippable, mIconAlphaForStash.animateToValue(iconAlphaTarget), iconAlphaStartDelay,
+ iconAlphaDuration,
+ LINEAR);
if (isStashed) {
- play(as, mTaskbarBackgroundOffset.animateToValue(1), 0, duration, EMPHASIZED);
-
- long alphaStartDelay = duration == 0 ? 0 : animationType == TRANSITION_HOME_TO_APP
- ? TASKBAR_STASH_ICON_ALPHA_HOME_TO_APP_START_DELAY
- : TASKBAR_STASH_ALPHA_START_DELAY;
- long alphaDuration = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_DURATION;
- play(as, mIconAlphaForStash.animateToValue(0), alphaStartDelay, alphaDuration, LINEAR);
- play(as, mTaskbarStashedHandleAlpha.animateToValue(1), alphaStartDelay,
- Math.max(0, duration - alphaStartDelay), LINEAR);
-
- play(as, mControllers.taskbarSpringOnStashController.createSpringToStash(), 0, duration,
- LINEAR);
-
- if (animationType == TRANSITION_HANDLE_FADE) {
- skipInterpolator = INSTANT;
- }
- } else {
- final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
- if (animateBg) {
- play(as, mTaskbarBackgroundOffset.animateToValue(0), 0, duration, EMPHASIZED);
- } else {
- as.addListener(AnimatorListeners.forEndCallback(
- () -> mTaskbarBackgroundOffset.updateValue(0)));
- }
-
- long alphaStartDelay = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_START_DELAY;
- long alphaDuration = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_DURATION;
- play(as, mIconAlphaForStash.animateToValue(1), alphaStartDelay, alphaDuration, LINEAR);
- play(as, mTaskbarStashedHandleAlpha.animateToValue(0), 0, alphaDuration, LINEAR);
-
- if (animationType == TRANSITION_HANDLE_FADE) {
- skipInterpolator = FINAL_FRAME;
- }
+ play(skippable, mControllers.taskbarSpringOnStashController.createSpringToStash(),
+ 0, duration, LINEAR);
}
- mControllers.taskbarViewController.addRevealAnimToIsStashed(as, isStashed, duration,
+
+ mControllers.taskbarViewController.addRevealAnimToIsStashed(skippable, isStashed, duration,
EMPHASIZED);
- if (skipInterpolator != null) {
- as.setInterpolator(skipInterpolator);
- }
-
- play(as, mControllers.stashedHandleViewController
+ play(skippable, mControllers.stashedHandleViewController
.createRevealAnimToIsStashed(isStashed), 0, duration, EMPHASIZED);
// Return the stashed handle to its default scale in case it was changed as part of the
// feedforward hint. Note that the reveal animation above also visually scales it.
- as.play(mTaskbarStashedHandleHintScale.animateToValue(1f)
+ skippable.play(mTaskbarStashedHandleHintScale.animateToValue(1f)
.setDuration(isStashed ? duration / 2 : duration));
}
@@ -951,7 +978,8 @@
updateStateForFlag(FLAG_STASHED_SYSUI,
hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
- boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
+ boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
+ && !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
// Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
@@ -1169,6 +1197,8 @@
private @StashAnimation int mLastStartedTransitionType = TRANSITION_DEFAULT;
private int mPrevFlags;
+ private long mLastUnlockTransitionTimeout = 0;
+
StatePropertyHolder(IntPredicate stashCondition) {
mStashCondition = stashCondition;
}
@@ -1186,7 +1216,7 @@
if (DEBUG) {
String stateString = formatFlagChange(flags, mPrevFlags,
- TaskbarStashController::getStateString);
+ TaskbarStashController::getStateString);
Log.d(TAG, "createSetStateAnimator: flags: " + stateString
+ ", duration: " + duration
+ ", isStashed: " + isStashed
@@ -1199,6 +1229,17 @@
mPrevFlags = flags;
}
+ boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
+ && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
+ if (isUnlockTransition) {
+ // the launcher might not be resumed at the time the device is considered
+ // unlocked (when the keyguard goes away), but possibly shortly afterwards.
+ // To play the unlock transition at the time the unstash animation actually happens,
+ // this memoizes the state transition for UNLOCK_TRANSITION_MEMOIZATION_MS.
+ mLastUnlockTransitionTimeout =
+ SystemClock.elapsedRealtime() + UNLOCK_TRANSITION_MEMOIZATION_MS;
+ }
+
@StashAnimation int animationType = computeTransitionType(changedFlags);
// Allow re-starting animation if upgrading from default animation type, otherwise
@@ -1229,6 +1270,7 @@
}
private @StashAnimation int computeTransitionType(int changedFlags) {
+
boolean hotseatHiddenDuringAppLaunch =
!mControllers.uiController.isHotseatIconOnTopWhenAligned()
&& hasAnyFlag(changedFlags, FLAG_IN_APP);
@@ -1240,8 +1282,8 @@
return TRANSITION_HANDLE_FADE;
}
- boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
- && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
+ boolean isUnlockTransition =
+ SystemClock.elapsedRealtime() < mLastUnlockTransitionTimeout;
if (isUnlockTransition) {
// When transitioning to unlocked device, the hotseat will already be visible on
// the homescreen, thus do not play an un-stash animation.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index b9242b2..1435cb0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -244,7 +244,8 @@
taskAttributes.getIconView().getDrawable(),
taskAttributes.getThumbnailView(),
taskAttributes.getThumbnailView().getThumbnail(),
- null /* intent */);
+ null /* intent */,
+ null /* user */);
return;
}
}
@@ -256,7 +257,8 @@
new BitmapDrawable(info.bitmap.icon),
startingView,
null /* thumbnail */,
- intent);
+ intent,
+ info.user);
}
);
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 88a27b8..edd8823 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -135,6 +135,7 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.wm.shell.common.TransactionPool;
@@ -1345,7 +1346,10 @@
}
StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
.withSrcState(LAUNCHER_STATE_BACKGROUND)
- .withDstState(endTarget.containerType);
+ .withDstState(endTarget.containerType)
+ .withInputType(mGestureState.isTrackpadGesture()
+ ? SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TRACKPAD
+ : SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TOUCH);
if (targetTask != null) {
logger.withItemInfo(targetTask.getItemInfo());
}
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index a68bea2..df42efc 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -86,9 +86,7 @@
Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding "
+ convertToFlagNames(stateFlag) + " to " + convertToFlagNames(mState));
}
- if (FeatureFlags.ENABLE_GESTURE_ERROR_DETECTION.get()) {
- trackGestureEvents(stateFlag);
- }
+ trackGestureEvents(stateFlag);
final int oldState = mState;
mState = mState | stateFlag;
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index fad4563..93363a0 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -18,6 +18,7 @@
import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
@@ -29,6 +30,7 @@
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_MOVE;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_UP;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
@@ -674,20 +676,24 @@
if (mUncheckedConsumer != InputConsumer.NO_OP) {
switch (event.getActionMasked()) {
- case ACTION_DOWN:
- case ACTION_UP:
+ case ACTION_DOWN, ACTION_UP ->
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "onMotionEvent(" + (int) event.getRawX() + ", "
+ (int) event.getRawY() + "): "
- + MotionEvent.actionToString(event.getActionMasked()),
+ + MotionEvent.actionToString(event.getActionMasked()) + ", "
+ + MotionEvent.classificationToString(event.getClassification()),
/* gestureEvent= */ event.getActionMasked() == ACTION_DOWN
? MOTION_DOWN
: MOTION_UP);
- break;
- default:
+ case ACTION_MOVE ->
ActiveGestureLog.INSTANCE.addLog("onMotionEvent: "
- + MotionEvent.actionToString(event.getActionMasked()));
- break;
+ + MotionEvent.actionToString(event.getActionMasked()) + ","
+ + MotionEvent.classificationToString(event.getClassification())
+ + ", pointerCount: " + event.getPointerCount(), MOTION_MOVE);
+ default ->
+ ActiveGestureLog.INSTANCE.addLog("onMotionEvent: "
+ + MotionEvent.actionToString(event.getActionMasked()) + ","
+ + MotionEvent.classificationToString(event.getClassification()));
}
}
@@ -910,10 +916,6 @@
private void logInputConsumerSelectionReason(
InputConsumer consumer, CompoundString reasonString) {
- if (!FeatureFlags.ENABLE_INPUT_CONSUMER_REASON_LOGGING.get()) {
- ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + consumer.getName());
- return;
- }
ActiveGestureLog.INSTANCE.addLog(new CompoundString("setInputConsumer: ")
.append(consumer.getName())
.append(". reason(s):")
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 4690d94..298d49a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -227,6 +227,7 @@
private SliceItem mSliceItem;
private LauncherAtom.Slice mSlice;
private Optional<Integer> mCardinality = Optional.empty();
+ private int mInputType = SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__UNKNOWN;
StatsCompatLogger(Context context, ActivityContext activityContext) {
mContext = context;
@@ -320,6 +321,12 @@
}
@Override
+ public StatsLogger withInputType(int inputType) {
+ this.mInputType = inputType;
+ return this;
+ }
+
+ @Override
public void log(EventEnum event) {
if (!Utilities.ATLEAST_R) {
return;
@@ -413,6 +420,7 @@
InstanceId instanceId = mInstanceId;
int srcState = mSrcState;
int dstState = mDstState;
+ int inputType = mInputType;
if (IS_VERBOSE) {
String name = (event instanceof Enum) ? ((Enum) event).name() :
event.getId() + "";
@@ -470,7 +478,8 @@
cardinality /* cardinality */,
getFeatures(atomInfo) /* features */,
getSearchAttributes(atomInfo) /* searchAttributes */,
- getAttributes(atomInfo) /* attributes */
+ getAttributes(atomInfo) /* attributes */,
+ inputType /* input_type */
);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 2964868..6eadd2b 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -32,11 +32,11 @@
* Enums associated to gesture navigation events.
*/
public enum GestureEvent {
- MOTION_DOWN, MOTION_UP, SET_END_TARGET, SET_END_TARGET_HOME, SET_END_TARGET_NEW_TASK,
- ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION,
- CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION,
- CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
- FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
+ MOTION_DOWN, MOTION_UP, MOTION_MOVE, SET_END_TARGET, SET_END_TARGET_HOME,
+ SET_END_TARGET_NEW_TASK, ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION,
+ FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK,
+ CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED,
+ EXPECTING_TASK_APPEARED, FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
/**
* These GestureEvents are specifically associated to state flags that get set in
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index e05d85c..409bf9c 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -155,15 +155,13 @@
}
public void dump(String prefix, PrintWriter writer) {
- if (FeatureFlags.ENABLE_GESTURE_ERROR_DETECTION.get()) {
- writer.println(prefix + "ActiveGestureErrorDetector:");
- for (int i = 0; i < logs.length; i++) {
- EventLog eventLog = logs[(nextIndex + i) % logs.length];
- if (eventLog == null) {
- continue;
- }
- ActiveGestureErrorDetector.analyseAndDump(prefix + '\t', writer, eventLog);
+ writer.println(prefix + "ActiveGestureErrorDetector:");
+ for (int i = 0; i < logs.length; i++) {
+ EventLog eventLog = logs[(nextIndex + i) % logs.length];
+ if (eventLog == null) {
+ continue;
}
+ ActiveGestureErrorDetector.analyseAndDump(prefix + '\t', writer, eventLog);
}
writer.println(prefix + "ActiveGestureLog history:");
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index c537ef8..11e1fbd 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -89,11 +89,17 @@
private final StateManager mStateManager;
@Nullable
private DepthController mDepthController;
- private @StagePosition int mStagePosition;
+ private @StagePosition int mInitialStagePosition;
private ItemInfo mItemInfo;
+ /** {@link #mInitialTaskIntent} and {@link #mInitialUser} (the user of the Intent) are set
+ * together when split is initiated from an Intent. */
private Intent mInitialTaskIntent;
+ private UserHandle mInitialUser;
private int mInitialTaskId = INVALID_TASK_ID;
+ /** {@link #mSecondTaskIntent} and {@link #mSecondUser} (the user of the Intent) are set
+ * together when split is confirmed with an Intent. */
private Intent mSecondTaskIntent;
+ private UserHandle mSecondUser;
private int mSecondTaskId = INVALID_TASK_ID;
private boolean mRecentsAnimationRunning;
/** If {@code true}, animates the existing task view split placeholder view */
@@ -103,8 +109,6 @@
* split pair task view without wanting to animate current task dismissal overall
*/
private boolean mDismissingFromSplitPair;
- @Nullable
- private UserHandle mUser;
/** If not null, this is the TaskView we want to launch from */
@Nullable
private GroupedTaskView mLaunchingTaskView;
@@ -138,7 +142,7 @@
mInitialTaskId = alreadyRunningTask;
} else {
mInitialTaskIntent = intent;
- mUser = itemInfo.user;
+ mInitialUser = itemInfo.user;
}
setInitialData(stagePosition, splitEvent, itemInfo);
@@ -158,7 +162,7 @@
private void setInitialData(@StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
mItemInfo = itemInfo;
- mStagePosition = stagePosition;
+ mInitialStagePosition = stagePosition;
mSplitEvent = splitEvent;
}
@@ -215,7 +219,7 @@
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
launchTasks(mInitialTaskId, mInitialTaskIntent, mSecondTaskId, mSecondTaskIntent,
- mStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
+ mInitialStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
instanceIds.first);
mStatsLogManager.logger()
@@ -232,8 +236,14 @@
mSecondTaskId = task.key.id;
}
- public void setSecondTask(Intent intent) {
+ /**
+ * To be called as soon as user selects the second app (even if animations aren't complete)
+ * @param intent The second intent that will be launched.
+ * @param user The user of that intent.
+ */
+ public void setSecondTask(Intent intent, UserHandle user) {
mSecondTaskIntent = intent;
+ mSecondUser = user;
}
/**
@@ -291,16 +301,17 @@
null /* options2 */, stagePosition, splitRatio, remoteTransition,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcut(intent1, options1, taskId2, stagePosition, splitRatio,
- remoteTransition, shellInstanceId);
+ launchIntentOrShortcut(intent1, mInitialUser, options1, taskId2, stagePosition,
+ splitRatio, remoteTransition, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcut(intent2, options1, taskId1,
+ launchIntentOrShortcut(intent2, mSecondUser, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
shellInstanceId);
} else {
- mSystemUiProxy.startIntents(getPendingIntent(intent1), options1.toBundle(),
- getPendingIntent(intent2), null /* options2 */, stagePosition,
- splitRatio, remoteTransition, shellInstanceId);
+ mSystemUiProxy.startIntents(getPendingIntent(intent1, mInitialUser),
+ options1.toBundle(), getPendingIntent(intent2, mSecondUser),
+ null /* options2 */, stagePosition, splitRatio, remoteTransition,
+ shellInstanceId);
}
} else {
final RemoteSplitLaunchAnimationRunner animationRunner =
@@ -314,61 +325,64 @@
taskId2, null /* options2 */, stagePosition, splitRatio, adapter,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcutLegacy(intent1, options1, taskId2, stagePosition, splitRatio,
- adapter, shellInstanceId);
+ launchIntentOrShortcutLegacy(intent1, mInitialUser, options1, taskId2,
+ stagePosition, splitRatio, adapter, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcutLegacy(intent2, options1, taskId1,
+ launchIntentOrShortcutLegacy(intent2, mSecondUser, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, adapter,
shellInstanceId);
} else {
mSystemUiProxy.startIntentsWithLegacyTransition(
- getPendingIntent(intent1), getShortcutInfo(intent1), options1.toBundle(),
- getPendingIntent(intent2), getShortcutInfo(intent2), null /* options2 */,
- stagePosition, splitRatio, adapter, shellInstanceId);
+ getPendingIntent(intent1, mInitialUser),
+ getShortcutInfo(intent1, mInitialUser), options1.toBundle(),
+ getPendingIntent(intent2, mSecondUser),
+ getShortcutInfo(intent2, mSecondUser), null /* options2 */, stagePosition,
+ splitRatio, adapter, shellInstanceId);
}
}
}
- private void launchIntentOrShortcut(Intent intent, ActivityOptions options1, int taskId,
- @StagePosition int stagePosition, float splitRatio, RemoteTransition remoteTransition,
- @Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+ private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
+ int taskId, @StagePosition int stagePosition, float splitRatio,
+ RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
+ final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
if (shortcutInfo != null) {
mSystemUiProxy.startShortcutAndTask(shortcutInfo,
options1.toBundle(), taskId, null /* options2 */, stagePosition,
splitRatio, remoteTransition, shellInstanceId);
} else {
- mSystemUiProxy.startIntentAndTask(getPendingIntent(intent), options1.toBundle(), taskId,
- null /* options2 */, stagePosition, splitRatio, remoteTransition,
- shellInstanceId);
+ mSystemUiProxy.startIntentAndTask(getPendingIntent(intent, user),
+ options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
+ remoteTransition, shellInstanceId);
}
}
- private void launchIntentOrShortcutLegacy(Intent intent, ActivityOptions options1, int taskId,
- @StagePosition int stagePosition, float splitRatio, RemoteAnimationAdapter adapter,
+ private void launchIntentOrShortcutLegacy(Intent intent, UserHandle user,
+ ActivityOptions options1, int taskId, @StagePosition int stagePosition,
+ float splitRatio, RemoteAnimationAdapter adapter,
@Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent);
+ final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
if (shortcutInfo != null) {
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
options1.toBundle(), taskId, null /* options2 */, stagePosition,
splitRatio, adapter, shellInstanceId);
} else {
- mSystemUiProxy.startIntentAndTaskWithLegacyTransition(getPendingIntent(intent),
- options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
- adapter, shellInstanceId);
+ mSystemUiProxy.startIntentAndTaskWithLegacyTransition(
+ getPendingIntent(intent, user), options1.toBundle(), taskId,
+ null /* options2 */, stagePosition, splitRatio, adapter, shellInstanceId);
}
}
- private PendingIntent getPendingIntent(Intent intent) {
- return intent == null ? null : (mUser != null
+ private PendingIntent getPendingIntent(Intent intent, UserHandle user) {
+ return intent == null ? null : (user != null
? PendingIntent.getActivityAsUser(mContext, 0, intent,
- FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, null /* options */, mUser)
+ FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, null /* options */, user)
: PendingIntent.getActivity(mContext, 0, intent,
FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT));
}
public @StagePosition int getActiveSplitStagePosition() {
- return mStagePosition;
+ return mInitialStagePosition;
}
public StatsLogManager.EventEnum getSplitEvent() {
@@ -380,7 +394,7 @@
}
@Nullable
- private ShortcutInfo getShortcutInfo(Intent intent) {
+ private ShortcutInfo getShortcutInfo(Intent intent, UserHandle user) {
if (intent == null || intent.getPackage() == null) {
return null;
}
@@ -392,7 +406,7 @@
try {
final Context context = mContext.createPackageContextAsUser(
- intent.getPackage(), 0 /* flags */, mUser);
+ intent.getPackage(), 0 /* flags */, user);
return new ShortcutInfo.Builder(context, shortcutId).build();
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage());
@@ -522,7 +536,9 @@
mInitialTaskIntent = null;
mSecondTaskId = INVALID_TASK_ID;
mSecondTaskIntent = null;
- mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
+ mInitialUser = null;
+ mSecondUser = null;
+ mInitialStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
mItemInfo = null;
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e5c74dc..dd10c2d 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -24,6 +24,7 @@
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.UserHandle;
import android.view.View;
import com.android.launcher3.DeviceProfile;
@@ -66,21 +67,24 @@
}
Object tag = view.getTag();
Intent intent;
+ UserHandle user;
BitmapInfo bitmapInfo;
if (tag instanceof WorkspaceItemInfo) {
final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
intent = workspaceItemInfo.intent;
+ user = workspaceItemInfo.user;
bitmapInfo = workspaceItemInfo.bitmap;
} else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
final com.android.launcher3.model.data.AppInfo appInfo =
(com.android.launcher3.model.data.AppInfo) tag;
intent = appInfo.intent;
+ user = appInfo.user;
bitmapInfo = appInfo.bitmap;
} else {
return false;
}
- mController.setSecondTask(intent);
+ mController.setSecondTask(intent, user);
boolean isTablet = mLauncher.getDeviceProfile().isTablet;
SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7989bb0..cf6ee2d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4589,11 +4589,13 @@
* is (either the ThumbnailView or the tapped icon).
* @param intent If we are launching a fresh instance of the app, this is the Intent for it. If
* the second app is already running in Recents, this will be null.
+ * @param user If we are launching a fresh instance of the app, this is the UserHandle for it.
+ * If the second app is already running in Recents, this will be null.
* @return true if waiting for confirmation of second app or if split animations are running,
* false otherwise
*/
public boolean confirmSplitSelect(TaskView containerTaskView, Task task, Drawable drawable,
- View secondView, @Nullable Bitmap thumbnail, Intent intent) {
+ View secondView, @Nullable Bitmap thumbnail, Intent intent, UserHandle user) {
if (canLaunchFullscreenTask()) {
return false;
}
@@ -4609,7 +4611,7 @@
}
mSplitSelectStateController.setSecondTask(task);
} else {
- mSplitSelectStateController.setSecondTask(intent);
+ mSplitSelectStateController.setSecondTask(intent, user);
}
RectF secondTaskStartingBounds = new RectF();
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index df90583..42589ce 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -761,7 +761,8 @@
if (container != null) {
return getRecentsView().confirmSplitSelect(this, container.getTask(),
container.getIconView().getDrawable(), container.getThumbnailView(),
- container.getThumbnailView().getThumbnail(), /* intent */ null);
+ container.getThumbnailView().getThumbnail(), /* intent */ null,
+ /* user */ null);
}
return false;
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 172cb46..3bf4ad3 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -40,7 +40,6 @@
@Mock lateinit var taskbarKeyguardController: TaskbarKeyguardController
@Mock lateinit var stashedHandleViewController: StashedHandleViewController
@Mock lateinit var taskbarStashController: TaskbarStashController
- @Mock lateinit var taskbarEduController: TaskbarEduController
@Mock lateinit var taskbarAutohideSuspendController: TaskbarAutohideSuspendController
@Mock lateinit var taskbarPopupController: TaskbarPopupController
@Mock
@@ -81,7 +80,6 @@
taskbarKeyguardController,
stashedHandleViewController,
taskbarStashController,
- taskbarEduController,
taskbarAutohideSuspendController,
taskbarPopupController,
taskbarForceVisibleImmersiveController,
diff --git a/res/drawable/page_indicator.xml b/res/drawable/page_indicator.xml
new file mode 100644
index 0000000..c0ccc49
--- /dev/null
+++ b/res/drawable/page_indicator.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?attr/folderPaginationColor"/>
+ <size android:width="@dimen/page_indicator_size" android:height="@dimen/page_indicator_size"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/page_indicator_dots.xml b/res/layout/page_indicator_dots.xml
index 41844b7..d5fe51e 100644
--- a/res/layout/page_indicator_dots.xml
+++ b/res/layout/page_indicator_dots.xml
@@ -14,13 +14,9 @@
limitations under the License.
-->
-<com.android.launcher3.pageindicators.LauncherDotsPageIndicator
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
+<com.android.launcher3.pageindicators.PageIndicatorDots xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/page_indicator"
android:layout_width="match_parent"
android:layout_height="@dimen/workspace_page_indicator_height"
android:layout_gravity="bottom | center_horizontal"
- android:theme="@style/HomeScreenElementTheme"
- launcher:indicatorDotColor="?attr/workspaceTextColor"
- />
\ No newline at end of file
+ android:theme="@style/HomeScreenElementTheme" />
\ No newline at end of file
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index ddcef09..3008339 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -22,15 +22,12 @@
android:id="@+id/bubble_text"
android:background="?android:attr/selectableItemBackground"
android:gravity="start|center_vertical"
- android:paddingTop="@dimen/bg_popup_item_vertical_padding"
- android:paddingBottom="@dimen/bg_popup_item_vertical_padding"
android:minHeight="@dimen/bg_popup_item_height"
android:textAlignment="viewStart"
android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
android:paddingEnd="@dimen/popup_padding_end"
android:textSize="14sp"
- android:minLines="1"
- android:maxLines="2"
+ android:lines="1"
android:ellipsize="end"
android:hyphenationFrequency="full"
android:textColor="@color/system_shortcut_text"
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 35ccc5a..5518dc8 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -53,13 +53,12 @@
android:textColorHighlight="?android:attr/colorControlHighlight"
android:textColorHint="?attr/folderHintColor"/>
- <com.android.launcher3.pageindicators.LauncherDotsPageIndicator
+ <com.android.launcher3.pageindicators.PageIndicatorDots
android:id="@+id/folder_page_indicator"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="1dp"
- launcher:indicatorDotColor="@color/folder_pagination_color"
/>
</LinearLayout>
diff --git a/res/layout/widgets_two_pane_sheet_paged_view.xml b/res/layout/widgets_two_pane_sheet_paged_view.xml
index 5cc2406..d3a8584 100644
--- a/res/layout/widgets_two_pane_sheet_paged_view.xml
+++ b/res/layout/widgets_two_pane_sheet_paged_view.xml
@@ -74,7 +74,9 @@
android:id="@+id/suggestions_header"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:background="?android:attr/colorBackground"
+ launcher:layout_sticky="true">
</LinearLayout>
<com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip
diff --git a/res/layout/widgets_two_pane_sheet_recyclerview.xml b/res/layout/widgets_two_pane_sheet_recyclerview.xml
index 09cef88..8f2a25e 100644
--- a/res/layout/widgets_two_pane_sheet_recyclerview.xml
+++ b/res/layout/widgets_two_pane_sheet_recyclerview.xml
@@ -59,7 +59,10 @@
android:id="@+id/suggestions_header"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
- android:orientation="horizontal">
+ android:paddingBottom="16dp"
+ android:orientation="horizontal"
+ android:background="?android:attr/colorBackground"
+ launcher:layout_sticky="true">
</LinearLayout>
</com.android.launcher3.views.StickyHeaderLayout>
</FrameLayout>
diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml
index 3b85b88..f331361 100644
--- a/res/values-night-v31/colors.xml
+++ b/res/values-night-v31/colors.xml
@@ -26,6 +26,4 @@
<color name="home_settings_track_off_color">@android:color/system_neutral1_700</color>
<color name="all_apps_button_color">@android:color/system_neutral2_200</color>
-
- <color name="folder_pagination_color">@android:color/system_accent2_100</color>
</resources>
\ No newline at end of file
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index ee27d99..17fe419 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -18,6 +18,4 @@
<resources>
<color name="all_apps_button_color">#BFC8CC</color>
- <color name="folder_pagination_color">#ffbfebe3</color>
-
</resources>
\ No newline at end of file
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index 0c87ff4..054fe47 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -41,7 +41,8 @@
<color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
<color name="folder_dot_color">@android:color/system_accent3_100</color>
- <color name="folder_pagination_color">@android:color/system_accent1_600</color>
+ <color name="folder_pagination_color_light">@android:color/system_accent1_600</color>
+ <color name="folder_pagination_color_dark">@android:color/system_accent2_100</color>
<color name="home_settings_header_accent">@android:color/system_accent1_600</color>
<color name="home_settings_header_collapsed">@android:color/system_neutral1_100</color>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 82bab56..417ae61 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -42,6 +42,7 @@
<attr name="popupNotificationDotColor" format="color" />
<attr name="folderDotColor" format="color" />
+ <attr name="folderPaginationColor" format="color" />
<attr name="folderPreviewColor" format="color" />
<attr name="folderBackgroundColor" format="color" />
<attr name="folderIconRadius" format="float" />
@@ -500,10 +501,4 @@
<!-- The icon drawable of a widget category. -->
<attr name="sectionDrawable" format="reference" />
</declare-styleable>
-
- <!-- Attributes for PagedIndicator -->
- <declare-styleable name="PagedIndicator">
- <!-- Color used to draw dots -->
- <attr name="indicatorDotColor" format="color" />
- </declare-styleable>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 1ef918d..8788557 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -67,7 +67,8 @@
<color name="folder_preview_dark">#464746</color>
<color name="folder_dot_color">?attr/colorPrimary</color>
- <color name="folder_pagination_color">#ff006c5f</color>
+ <color name="folder_pagination_color_light">#ff006c5f</color>
+ <color name="folder_pagination_color_dark">#ffbfebe3</color>
<color name="text_color_primary_dark">#FFFFFFFF</color>
<color name="text_color_secondary_dark">#FFFFFFFF</color>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 517bb87..5dc4f0a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,6 +50,7 @@
<item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderDotColor">@color/folder_dot_color</item>
+ <item name="folderPaginationColor">@color/folder_pagination_color_light</item>
<item name="folderPreviewColor">@color/folder_preview_light</item>
<item name="folderBackgroundColor">@color/folder_background_light</item>
<item name="folderIconBorderColor">?android:attr/colorPrimary</item>
@@ -103,6 +104,7 @@
<item name="popupShadeThird">@color/popup_shade_third_dark</item>
<item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
<item name="folderDotColor">@color/folder_dot_color</item>
+ <item name="folderPaginationColor">@color/folder_pagination_color_dark</item>
<item name="folderPreviewColor">@color/folder_preview_dark</item>
<item name="folderBackgroundColor">@color/folder_background_dark</item>
<item name="folderIconBorderColor">?android:attr/colorPrimary</item>
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 2083726..5367d80 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -38,6 +38,7 @@
import android.util.Xml;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -531,6 +532,7 @@
protected class SearchWidgetParser extends PendingWidgetParser {
@Override
@Nullable
+ @WorkerThread
public ComponentName getComponentName(XmlPullParser parser) {
return QsbContainerView.getSearchComponentName(mContext);
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 53d9281..961c254 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -872,7 +872,9 @@
if (mIcon instanceof PreloadIconDrawable) {
preloadIconDrawable = (PreloadIconDrawable) mIcon;
preloadIconDrawable.setLevel(progressLevel);
- preloadIconDrawable.setIsDisabled(!info.isAppStartable());
+ preloadIconDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
+ ? info.getProgressLevel() == 0
+ : !info.isAppStartable());
} else {
preloadIconDrawable = makePreloadIcon();
setIcon(preloadIconDrawable);
@@ -897,8 +899,9 @@
final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);
preloadDrawable.setLevel(progressLevel);
- preloadDrawable.setIsDisabled(!info.isAppStartable());
-
+ preloadDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
+ ? info.getProgressLevel() == 0
+ : !info.isAppStartable());
return preloadDrawable;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8fcc08d..4f7380a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -85,6 +85,7 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
@@ -1355,6 +1356,10 @@
if (SHOW_DOT_PAGINATION.get()) {
mWorkspace.getPageIndicator().setShouldAutoHide(true);
+ mWorkspace.getPageIndicator().setPaintColor(
+ Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)
+ ? Color.BLACK
+ : Color.WHITE);
}
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ad95f7e..06ac44a 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -421,6 +421,9 @@
launcherBinder.bindAllApps();
launcherBinder.bindDeepShortcuts();
launcherBinder.bindWidgets();
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.bindAllModelExtras(callbacksList);
+ }
return true;
} else {
stopLoader();
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index e688709..f4892b2 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -18,11 +18,9 @@
import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
-import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import android.annotation.TargetApi;
-import android.app.backup.BackupManager;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -31,91 +29,59 @@
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
-import android.database.sqlite.SQLiteStatement;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
-import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.BaseColumns;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.logging.FileLog;
-import com.android.launcher3.model.DbDowngradeHelper;
-import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.IntSet;
-import com.android.launcher3.util.NoLocaleSQLiteHelper;
-import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Partner;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.LauncherWidgetHolder;
import org.xmlpull.v1.XmlPullParser;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
-import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "LauncherProvider";
- private static final boolean LOGD = false;
-
- private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
- private static final long RESTORE_BACKUP_TABLE_DELAY = TimeUnit.SECONDS.toMillis(30);
-
- /**
- * Represents the schema of the database. Changes in scheme need not be backwards compatible.
- * When increasing the scheme version, ensure that downgrade_schema.json is updated
- */
- public static final int SCHEMA_VERSION = 31;
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
- public static final String KEY_LAYOUT_PROVIDER_AUTHORITY = "KEY_LAYOUT_PROVIDER_AUTHORITY";
private static final int TEST_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test_workspace;
private static final int TEST2_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test2_workspace;
private static final int TAPL_WORKSPACE_LAYOUT_RES_XML = R.xml.default_tapl_test_workspace;
- static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
+ public static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
protected DatabaseHelper mOpenHelper;
protected String mProviderAuthority;
- private long mLastRestoreTimestamp = 0L;
-
private int mDefaultWorkspaceLayoutOverride = 0;
/**
@@ -198,18 +164,6 @@
return result;
}
- @Thunk static int dbInsertAndCheck(DatabaseHelper helper,
- SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
- if (values == null) {
- throw new RuntimeException("Error: attempting to insert null values");
- }
- if (!values.containsKey(LauncherSettings.Favorites._ID)) {
- throw new RuntimeException("Error: attempting to add item without specifying an id");
- }
- helper.checkId(values);
- return (int) db.insert(table, nullColumnHack, values);
- }
-
private void reloadLauncherIfExternal() {
if (Binder.getCallingPid() != Process.myPid()) {
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
@@ -233,7 +187,7 @@
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
addModifiedTime(initialValues);
- final int rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
+ final int rowId = mOpenHelper.dbInsertAndCheck(db, args.table, initialValues);
if (rowId < 0) return null;
onAddOrDeleteOp(db);
@@ -292,7 +246,7 @@
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
addModifiedTime(values[i]);
- if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) {
+ if (mOpenHelper.dbInsertAndCheck(db, args.table, values[i]) < 0) {
return 0;
}
}
@@ -374,13 +328,6 @@
clearFlagEmptyDbCreated();
return null;
}
- case LauncherSettings.Settings.METHOD_WAS_EMPTY_DB_CREATED : {
- Bundle result = new Bundle();
- result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- LauncherPrefs.getPrefs(getContext()).getBoolean(
- mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false));
- return result;
- }
case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: {
Bundle result = new Bundle();
result.putIntArray(LauncherSettings.Settings.EXTRA_VALUE, deleteEmptyFolders()
@@ -438,25 +385,11 @@
new SQLiteTransaction(mOpenHelper.getWritableDatabase()));
return result;
}
- case LauncherSettings.Settings.METHOD_REFRESH_BACKUP_TABLE: {
- mOpenHelper.mBackupTableExists = tableExists(mOpenHelper.getReadableDatabase(),
- Favorites.BACKUP_TABLE_NAME);
- return null;
- }
case LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE: {
mOpenHelper.mHotseatRestoreTableExists = tableExists(
mOpenHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
return null;
}
- case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
- final long ts = System.currentTimeMillis();
- if (ts - mLastRestoreTimestamp > RESTORE_BACKUP_TABLE_DELAY) {
- mLastRestoreTimestamp = ts;
- RestoreDbTask.restoreIfPossible(
- getContext(), mOpenHelper, new BackupManager(getContext()));
- }
- return null;
- }
case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
@@ -479,22 +412,6 @@
() -> mOpenHelper));
return result;
}
- case LauncherSettings.Settings.METHOD_SWITCH_DATABASE: {
- if (TextUtils.equals(arg, mOpenHelper.getDatabaseName())) return null;
- final DatabaseHelper helper = mOpenHelper;
- if (extras == null || !extras.containsKey(KEY_LAYOUT_PROVIDER_AUTHORITY)) {
- mProviderAuthority = null;
- } else {
- mProviderAuthority = extras.getString(KEY_LAYOUT_PROVIDER_AUTHORITY);
- }
- mOpenHelper = DatabaseHelper.createDatabaseHelper(
- getContext(), arg, false /* forMigration */);
- helper.close();
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app == null) return null;
- app.getModel().forceReload();
- return null;
- }
}
return null;
}
@@ -658,504 +575,6 @@
mOpenHelper, getContext().getResources(), defaultLayout);
}
- /**
- * The class is subclassed in tests to create an in-memory db.
- */
- public static class DatabaseHelper extends NoLocaleSQLiteHelper implements
- LayoutParserCallback {
- private final Context mContext;
- private final boolean mForMigration;
- private int mMaxItemId = -1;
- private boolean mBackupTableExists;
- private boolean mHotseatRestoreTableExists;
-
- static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
- return createDatabaseHelper(context, null, forMigration);
- }
-
- static DatabaseHelper createDatabaseHelper(Context context, String dbName,
- boolean forMigration) {
- if (dbName == null) {
- dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile;
- }
- DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration);
- // Table creation sometimes fails silently, which leads to a crash loop.
- // This way, we will try to create a table every time after crash, so the device
- // would eventually be able to recover.
- if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
- Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
- // This operation is a no-op if the table already exists.
- databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true);
- }
- databaseHelper.mHotseatRestoreTableExists = tableExists(
- databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
-
- databaseHelper.initIds();
- return databaseHelper;
- }
-
- /**
- * Constructor used in tests and for restore.
- */
- public DatabaseHelper(Context context, String dbName, boolean forMigration) {
- super(context, dbName, SCHEMA_VERSION);
- mContext = context;
- mForMigration = forMigration;
- }
-
- protected void initIds() {
- // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
- // the DB here
- if (mMaxItemId == -1) {
- mMaxItemId = initializeMaxItemId(getWritableDatabase());
- }
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- if (LOGD) Log.d(TAG, "creating new launcher database");
-
- mMaxItemId = 1;
-
- addFavoritesTable(db, false);
-
- // Fresh and clean launcher DB.
- mMaxItemId = initializeMaxItemId(db);
- if (!mForMigration) {
- onEmptyDbCreated();
- }
- }
-
- protected void onAddOrDeleteOp(SQLiteDatabase db) {
- if (mBackupTableExists) {
- dropTable(db, Favorites.BACKUP_TABLE_NAME);
- mBackupTableExists = false;
- }
- if (mHotseatRestoreTableExists) {
- dropTable(db, Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
- mHotseatRestoreTableExists = false;
- }
- }
-
- /**
- * Re-composite given key in respect to database. If the current db is
- * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
- * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
- * string will be "EMPTY_DATABASE_CREATED@minimal.db".
- */
- String getKey(final String key) {
- if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
- return key;
- }
- return key + "@" + getDatabaseName();
- }
-
- /**
- * Overriden in tests.
- */
- protected void onEmptyDbCreated() {
- // Set the flag for empty DB
- LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
- .commit();
- }
-
- public long getSerialNumberForUser(UserHandle user) {
- return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
- }
-
- public long getDefaultUserSerial() {
- return getSerialNumberForUser(Process.myUserHandle());
- }
-
- private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
- Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
- }
-
- @Override
- public void onOpen(SQLiteDatabase db) {
- super.onOpen(db);
-
- File schemaFile = mContext.getFileStreamPath(DOWNGRADE_SCHEMA_FILE);
- if (!schemaFile.exists()) {
- handleOneTimeDataUpgrade(db);
- }
- DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext);
- }
-
- /**
- * One-time data updated before support of onDowngrade was added. This update is backwards
- * compatible and can safely be run multiple times.
- * Note: No new logic should be added here after release, as the new logic might not get
- * executed on an existing device.
- * TODO: Move this to db upgrade path, once the downgrade path is released.
- */
- protected void handleOneTimeDataUpgrade(SQLiteDatabase db) {
- // Remove "profile extra"
- UserCache um = UserCache.INSTANCE.get(mContext);
- for (UserHandle user : um.getUserProfiles()) {
- long serial = um.getSerialNumberForUser(user);
- String sql = "update favorites set intent = replace(intent, "
- + "';l.profile=" + serial + ";', ';') where itemType = 0;";
- db.execSQL(sql);
- }
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (LOGD) Log.d(TAG, "onUpgrade triggered: " + oldVersion);
- switch (oldVersion) {
- // The version cannot be lower that 12, as Launcher3 never supported a lower
- // version of the DB.
- case 12:
- // No-op
- case 13: {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- // Insert new column for holding widget provider name
- db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN appWidgetProvider TEXT;");
- t.commit();
- } catch (SQLException ex) {
- Log.e(TAG, ex.getMessage(), ex);
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 14: {
- if (!addIntegerColumn(db, Favorites.MODIFIED, 0)) {
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 15: {
- if (!addIntegerColumn(db, Favorites.RESTORED, 0)) {
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 16:
- // No-op
- case 17:
- // No-op
- case 18:
- // No-op
- case 19: {
- // Add userId column
- if (!addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial())) {
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 20:
- if (!updateFolderItemsRank(db, true)) {
- break;
- }
- case 21:
- // No-op
- case 22: {
- if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) {
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 23:
- // No-op
- case 24:
- // No-op
- case 25:
- convertShortcutsToLauncherActivities(db);
- case 26:
- // QSB was moved to the grid. Ignore overlapping items
- case 27: {
- // Update the favorites table so that the screen ids are ordered based on
- // workspace page rank.
- IntArray finalScreens = LauncherDbUtils.queryIntArray(false, db,
- "workspaceScreens", BaseColumns._ID, null, null, "screenRank");
- int[] original = finalScreens.toArray();
- Arrays.sort(original);
- String updatemap = "";
- for (int i = 0; i < original.length; i++) {
- if (finalScreens.get(i) != original[i]) {
- updatemap += String.format(Locale.ENGLISH, " WHEN %1$s=%2$d THEN %3$d",
- Favorites.SCREEN, finalScreens.get(i), original[i]);
- }
- }
- if (!TextUtils.isEmpty(updatemap)) {
- String query = String.format(Locale.ENGLISH,
- "UPDATE %1$s SET %2$s=CASE %3$s ELSE %2$s END WHERE %4$s = %5$d",
- Favorites.TABLE_NAME, Favorites.SCREEN, updatemap,
- Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP);
- db.execSQL(query);
- }
- dropTable(db, "workspaceScreens");
- }
- case 28: {
- boolean columnAdded = addIntegerColumn(
- db, Favorites.APPWIDGET_SOURCE, Favorites.CONTAINER_UNKNOWN);
- if (!columnAdded) {
- // Old version remains, which means we wipe old data
- break;
- }
- }
- case 29: {
- // Remove widget panel related leftover workspace items
- db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
- Favorites.SCREEN, IntArray.wrap(-777, -778)), null);
- }
- case 30: {
- if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
- // Clean up first row in screen 0 as it might contain junk data.
- Log.d(TAG, "Cleaning up first row");
- db.delete(Favorites.TABLE_NAME,
- String.format(Locale.ENGLISH,
- "%1$s = %2$d AND %3$s = %4$d AND %5$s = %6$d",
- Favorites.SCREEN, 0,
- Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP,
- Favorites.CELLY, 0), null);
- }
- return;
- }
- case 31: {
- // DB Upgraded successfully
- return;
- }
- }
-
- // DB was not upgraded
- Log.w(TAG, "Destroying all old data.");
- createEmptyDB(db);
- }
-
- @Override
- public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- try {
- DbDowngradeHelper.parse(mContext.getFileStreamPath(DOWNGRADE_SCHEMA_FILE))
- .onDowngrade(db, oldVersion, newVersion);
- } catch (Exception e) {
- Log.d(TAG, "Unable to downgrade from: " + oldVersion + " to " + newVersion +
- ". Wiping databse.", e);
- createEmptyDB(db);
- }
- }
-
- /**
- * Clears all the data for a fresh start.
- */
- public void createEmptyDB(SQLiteDatabase db) {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- dropTable(db, Favorites.TABLE_NAME);
- dropTable(db, "workspaceScreens");
- onCreate(db);
- t.commit();
- }
- }
-
- /**
- * Removes widgets which are registered to the Launcher's host, but are not present
- * in our model.
- */
- public void removeGhostWidgets(SQLiteDatabase db) {
- // Get all existing widget ids.
- final LauncherWidgetHolder holder = newLauncherWidgetHolder();
- try {
- final int[] allWidgets;
- try {
- // Although the method was defined in O, it has existed since the beginning of
- // time, so it might work on older platforms as well.
- allWidgets = holder.getAppWidgetIds();
- } catch (IncompatibleClassChangeError e) {
- Log.e(TAG, "getAppWidgetIds not supported", e);
- return;
- }
- final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(false, db,
- Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
- "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
- boolean isAnyWidgetRemoved = false;
- for (int widgetId : allWidgets) {
- if (!validWidgets.contains(widgetId)) {
- try {
- FileLog.d(TAG, "Deleting invalid widget " + widgetId);
- holder.deleteAppWidgetId(widgetId);
- isAnyWidgetRemoved = true;
- } catch (RuntimeException e) {
- // Ignore
- }
- }
- }
- if (isAnyWidgetRemoved) {
- final String allWidgetsIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
- .collect(Collectors.joining(",", "[", "]"));
- final String validWidgetsIds = Arrays.stream(
- validWidgets.getArray().toArray()).mapToObj(String::valueOf)
- .collect(Collectors.joining(",", "[", "]"));
- FileLog.d(TAG, "One or more widgets was removed. db_path=" + db.getPath()
- + " allWidgetsIds=" + allWidgetsIds
- + ", validWidgetsIds=" + validWidgetsIds);
- }
- } finally {
- holder.destroy();
- }
- }
-
- /**
- * Replaces all shortcuts of type {@link Favorites#ITEM_TYPE_SHORTCUT} which have a valid
- * launcher activity target with {@link Favorites#ITEM_TYPE_APPLICATION}.
- */
- @Thunk void convertShortcutsToLauncherActivities(SQLiteDatabase db) {
- try (SQLiteTransaction t = new SQLiteTransaction(db);
- // Only consider the primary user as other users can't have a shortcut.
- Cursor c = db.query(Favorites.TABLE_NAME,
- new String[] { Favorites._ID, Favorites.INTENT},
- "itemType=" + Favorites.ITEM_TYPE_SHORTCUT +
- " AND profileId=" + getDefaultUserSerial(),
- null, null, null, null);
- SQLiteStatement updateStmt = db.compileStatement("UPDATE favorites SET itemType="
- + Favorites.ITEM_TYPE_APPLICATION + " WHERE _id=?")
- ) {
- final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
- final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT);
-
- while (c.moveToNext()) {
- String intentDescription = c.getString(intentIndex);
- Intent intent;
- try {
- intent = Intent.parseUri(intentDescription, 0);
- } catch (URISyntaxException e) {
- Log.e(TAG, "Unable to parse intent", e);
- continue;
- }
-
- if (!PackageManagerHelper.isLauncherAppTarget(intent)) {
- continue;
- }
-
- int id = c.getInt(idIndex);
- updateStmt.bindLong(1, id);
- updateStmt.executeUpdateDelete();
- }
- t.commit();
- } catch (SQLException ex) {
- Log.w(TAG, "Error deduping shortcuts", ex);
- }
- }
-
- @Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- if (addRankColumn) {
- // Insert new column for holding rank
- db.execSQL("ALTER TABLE favorites ADD COLUMN rank INTEGER NOT NULL DEFAULT 0;");
- }
-
- // Get a map for folder ID to folder width
- Cursor c = db.rawQuery("SELECT container, MAX(cellX) FROM favorites"
- + " WHERE container IN (SELECT _id FROM favorites WHERE itemType = ?)"
- + " GROUP BY container;",
- new String[] {Integer.toString(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)});
-
- while (c.moveToNext()) {
- db.execSQL("UPDATE favorites SET rank=cellX+(cellY*?) WHERE "
- + "container=? AND cellX IS NOT NULL AND cellY IS NOT NULL;",
- new Object[] {c.getLong(1) + 1, c.getLong(0)});
- }
-
- c.close();
- t.commit();
- } catch (SQLException ex) {
- // Old version remains, which means we wipe old data
- Log.e(TAG, ex.getMessage(), ex);
- return false;
- }
- return true;
- }
-
- private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) {
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- db.execSQL("ALTER TABLE favorites ADD COLUMN "
- + columnName + " INTEGER NOT NULL DEFAULT " + defaultValue + ";");
- t.commit();
- } catch (SQLException ex) {
- Log.e(TAG, ex.getMessage(), ex);
- return false;
- }
- return true;
- }
-
- // Generates a new ID to use for an object in your database. This method should be only
- // called from the main UI thread. As an exception, we do call it when we call the
- // constructor from the worker thread; however, this doesn't extend until after the
- // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
- // after that point
- @Override
- public int generateNewItemId() {
- if (mMaxItemId < 0) {
- throw new RuntimeException("Error: max item id was not initialized");
- }
- mMaxItemId += 1;
- return mMaxItemId;
- }
-
- /**
- * @return A new {@link LauncherWidgetHolder} based on the current context
- */
- @NonNull
- public LauncherWidgetHolder newLauncherWidgetHolder() {
- return LauncherWidgetHolder.newInstance(mContext);
- }
-
- @Override
- public int insertAndCheck(SQLiteDatabase db, ContentValues values) {
- return dbInsertAndCheck(this, db, Favorites.TABLE_NAME, null, values);
- }
-
- public void checkId(ContentValues values) {
- int id = values.getAsInteger(Favorites._ID);
- mMaxItemId = Math.max(id, mMaxItemId);
- }
-
- private int initializeMaxItemId(SQLiteDatabase db) {
- return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s", Favorites._ID, Favorites.TABLE_NAME);
- }
-
- // Returns a new ID to use for an workspace screen in your database that is greater than all
- // existing screen IDs.
- private int getNewScreenId() {
- return getMaxId(getWritableDatabase(),
- "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d AND %1$s >= 0",
- Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER,
- Favorites.CONTAINER_DESKTOP) + 1;
- }
-
- @Thunk int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
- // TODO: Use multiple loaders with fall-back and transaction.
- int count = loader.loadLayout(db, new IntArray());
-
- // Ensure that the max ids are initialized
- mMaxItemId = initializeMaxItemId(db);
- return count;
- }
- }
-
- /**
- * @return the max _id in the provided table.
- */
- @Thunk static int getMaxId(SQLiteDatabase db, String query, Object... args) {
- int max = 0;
- try (SQLiteStatement prog = db.compileStatement(
- String.format(Locale.ENGLISH, query, args))) {
- max = (int) DatabaseUtils.longForQuery(prog, null);
- if (max < 0) {
- throw new RuntimeException("Error: could not query max id");
- }
- } catch (IllegalArgumentException exception) {
- String message = exception.getMessage();
- if (message.contains("re-open") && message.contains("already-closed")) {
- // Don't crash trying to end a transaction an an already closed DB. See b/173162852.
- } else {
- throw exception;
- }
- }
- return max;
- }
-
static class SqlArguments {
public final String table;
public final String where;
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 6e3e96c..1cd2a30 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -380,7 +380,6 @@
LauncherProvider.AUTHORITY + "/settings");
public static final String METHOD_CLEAR_EMPTY_DB_FLAG = "clear_empty_db_flag";
- public static final String METHOD_WAS_EMPTY_DB_CREATED = "get_empty_db_flag";
public static final String METHOD_DELETE_EMPTY_FOLDERS = "delete_empty_folders";
@@ -404,18 +403,12 @@
public static final String METHOD_NEW_TRANSACTION = "new_db_transaction";
- public static final String METHOD_REFRESH_BACKUP_TABLE = "refresh_backup_table";
-
public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
- public static final String METHOD_RESTORE_BACKUP_TABLE = "restore_backup_table";
-
public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper";
public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
- public static final String METHOD_SWITCH_DATABASE = "switch_database";
-
public static final String EXTRA_VALUE = "value";
public static final String EXTRA_DB_NAME = "db_name";
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 50ad2be..32c8968 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -71,7 +71,6 @@
}
InstallSessionHelper packageInstallerCompat = InstallSessionHelper.INSTANCE.get(context);
- packageInstallerCompat.restoreDbIfApplicable(info);
if (TextUtils.isEmpty(info.getAppPackageName())
|| info.getInstallReason() != PackageManager.INSTALL_REASON_USER
|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 26ad4b5..62e7ef3 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -153,8 +153,8 @@
Interpolator workspaceFadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
- mLauncher.getWorkspace().getPageIndicator().setAlpha(
- propertySetter, workspacePageIndicatorAlpha, workspaceFadeInterpolator);
+ propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
+ workspacePageIndicatorAlpha, workspaceFadeInterpolator);
Interpolator hotseatFadeInterpolator = config.getInterpolator(ANIM_HOTSEAT_FADE,
workspaceFadeInterpolator);
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 66417d3..b485780 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -184,7 +184,7 @@
this, mActivityContext.getStatsLogManager());
mAH = Arrays.asList(null, null, null);
mNavBarScrimPaint = new Paint();
- mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+ mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
AllAppsStore.OnUpdateListener onAppsUpdated = this::onAppsUpdated;
if (TestProtocol.sDebugTracing) {
@@ -831,6 +831,12 @@
}
}
updateBackground(dp);
+
+ int navBarScrimColor = Themes.getNavBarScrimColor(mActivityContext);
+ if (mNavBarScrimPaint.getColor() != navBarScrimColor) {
+ mNavBarScrimPaint.setColor(navBarScrimColor);
+ invalidate();
+ }
}
protected void updateBackground(DeviceProfile deviceProfile) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 6f1dfe9..0b34bef 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -69,21 +69,13 @@
/**
* Feature flag to handle define config changes dynamically instead of killing the process.
- *
+ * <p>
*
* To add a new flag that can be toggled through the flags UI:
- *
+ * <p>
* Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"),
* and set a default value for the flag. This will be the default value on Debug builds.
*/
- public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(270390028,
- "ENABLE_INPUT_CONSUMER_REASON_LOGGING", ENABLED,
- "Log the reason why an Input Consumer was selected for a gesture.");
-
- public static final BooleanFlag ENABLE_GESTURE_ERROR_DETECTION = getDebugFlag(270389990,
- "ENABLE_GESTURE_ERROR_DETECTION", ENABLED,
- "Analyze gesture events and log detected errors");
-
// When enabled the promise icon is visible in all apps while installation an app.
public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012,
"PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps");
@@ -139,21 +131,6 @@
"ASSISTANT_GIVES_LAUNCHER_FOCUS", DISABLED,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
- public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(270392203,
- "ENABLE_BULK_WORKSPACE_ICON_LOADING", ENABLED,
- "Enable loading workspace icons in bulk.");
-
- public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(270392465,
- "ENABLE_BULK_ALL_APPS_ICON_LOADING", ENABLED, "Enable loading all apps icons in bulk.");
-
- public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(270392706,
- "ENABLE_DATABASE_RESTORE", DISABLED,
- "Enable database restore when new restore session is created");
-
- public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(270391664,
- "ENABLE_SMARTSPACE_DISMISS", ENABLED,
- "Adds a menu option to dismiss the current Enhanced Smartspace card.");
-
public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629,
"ENABLE_OVERLAY_CONNECTION_OPTIM", DISABLED,
"Enable optimizing overlay service connection");
@@ -173,14 +150,6 @@
"SEPARATE_RECENTS_ACTIVITY", DISABLED,
"Uses a separate recents activity instead of using the integrated recents+Launcher UI");
- public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(270392984,
- "ENABLE_MINIMAL_DEVICE", DISABLED,
- "Allow user to toggle minimal device mode in launcher.");
-
- public static final BooleanFlag ENABLE_TASKBAR_POPUP_MENU = getDebugFlag(270392477,
- "ENABLE_TASKBAR_POPUP_MENU", ENABLED,
- "Enables long pressing taskbar icons to show the popup menu.");
-
public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643,
"ENABLE_TWO_PANEL_HOME", ENABLED,
"Uses two panel on home screen. Only applicable on large screen devices.");
@@ -228,7 +197,7 @@
"Enable initiating split screen from workspace.");
public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS =
- getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", ENABLED,
+ getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", DISABLED,
"Enable splitting from fullscreen app with keyboard shortcuts");
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
@@ -362,10 +331,6 @@
"ENABLE_FORCED_MONO_ICON", DISABLED,
"Enable the ability to generate monochromatic icons, if it is not provided by the app");
- public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(270396268,
- "ENABLE_TASKBAR_EDU_TOOLTIP", ENABLED,
- "Enable the tooltip version of the Taskbar education flow.");
-
public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680,
"ENABLE_MULTI_INSTANCE", DISABLED,
"Enables creation and filtering of multiple task instances in overview");
@@ -380,6 +345,11 @@
"load the current workspace screen visible to the user before the rest rather than "
+ "loading all of them at once.");
+ public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424,
+ "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED,
+ "changes the timing of the loading and binding of delegate items during "
+ + "data preparation for loading the home screen");
+
public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
"ENABLE_GRID_ONLY_OVERVIEW", DISABLED,
"Enable a grid-only overview without a focused task.");
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 9fe3c0b..d43731b 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -45,7 +45,7 @@
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pageindicators.LauncherDotsPageIndicator;
+import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Thunk;
@@ -60,7 +60,7 @@
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
-public class FolderPagedView extends PagedView<LauncherDotsPageIndicator> implements ClipPathView {
+public class FolderPagedView extends PagedView<PageIndicatorDots> implements ClipPathView {
private static final String TAG = "FolderPagedView";
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 5a50569..0fe79e7 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -27,16 +27,11 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
-import android.os.SystemClock;
import android.util.Property;
import com.android.launcher3.R;
@@ -47,10 +42,6 @@
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.util.Themes;
-import com.android.launcher3.util.window.RefreshRateTracker;
-
-import java.util.WeakHashMap;
-import java.util.function.Function;
/**
* Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
@@ -91,14 +82,6 @@
private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
- private static final int ALPHA_DURATION_MILLIS = 3000;
- private static final int OVERLAY_ALPHA_RANGE = 191;
- private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
- private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
- new WeakHashMap<>();
- public static final Function<Integer, PorterDuffColorFilter> FILTER_FACTORY =
- currArgb -> new PorterDuffColorFilter(currArgb, PorterDuff.Mode.SRC_ATOP);
-
private final Matrix mTmpMatrix = new Matrix();
private final PathMeasure mPathMeasure = new PathMeasure();
@@ -119,7 +102,6 @@
private float mTrackLength;
private boolean mRanFinishAnimation;
- private final int mRefreshRateMillis;
// Progress of the internal state. [0, 1] indicates the fraction of completed progress,
// [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
@@ -138,7 +120,6 @@
IconPalette.getPreloadProgressColor(context, info.bitmap.color),
getPreloadColors(context),
Utilities.isDarkTheme(context),
- getRefreshRateMillis(context),
GraphicsUtils.getShapePath(context, DEFAULT_PATH_SIZE));
}
@@ -147,7 +128,6 @@
int indicatorColor,
int[] preloadColors,
boolean isDarkMode,
- int refreshRateMillis,
Path shapePath) {
super(info.bitmap);
mItem = info;
@@ -162,13 +142,14 @@
mSystemAccentColor = preloadColors[PRELOAD_ACCENT_COLOR_INDEX];
mSystemBackgroundColor = preloadColors[PRELOAD_BACKGROUND_COLOR_INDEX];
mIsDarkMode = isDarkMode;
- mRefreshRateMillis = refreshRateMillis;
// If it's a pending app we will animate scale and alpha when it's no longer pending.
mIconScaleMultiplier.updateValue(info.getProgressLevel() == 0 ? 0 : 1);
setLevel(info.getProgressLevel());
- setIsStartable(info.isAppStartable());
+ if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+ setIsStartable(info.isAppStartable());
+ }
}
@Override
@@ -223,20 +204,16 @@
: SMALL_SCALE;
canvas.scale(scale, scale, bounds.exactCenterX(), bounds.exactCenterY());
- ColorFilter filter = getOverlayFilter();
- mPaint.setColorFilter(filter);
super.drawInternal(canvas, bounds);
canvas.restoreToCount(saveCount);
-
- if (ENABLE_DOWNLOAD_APP_UX_V2.get() && filter != null) {
- reschedule();
- }
}
@Override
protected void updateFilter() {
if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
setAlpha(mIsDisabled ? DISABLED_ICON_ALPHA : MAX_PAINT_ALPHA);
+ } else {
+ super.updateFilter();
}
}
@@ -317,7 +294,7 @@
/**
* Sets the internal progress and updates the UI accordingly
* for progress <= 0:
- * - icon with pending motion
+ * - icon is pending
* - progress track is not visible
* - progress bar is not visible
* for progress < 1:
@@ -367,11 +344,6 @@
return preloadColors;
}
-
- private static int getRefreshRateMillis(Context context) {
- return RefreshRateTracker.getSingleFrameMs(context);
- }
-
/**
* Returns a FastBitmapDrawable with the icon.
*/
@@ -388,55 +360,9 @@
mIndicatorColor,
new int[] {mSystemAccentColor, mSystemBackgroundColor},
mIsDarkMode,
- mRefreshRateMillis,
mShapePath);
}
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- if (!visible) {
- unscheduleSelf(mInvalidateRunnable);
- }
- return super.setVisible(visible, restart);
- }
-
- private void reschedule() {
- unscheduleSelf(mInvalidateRunnable);
- if (!isVisible()) {
- return;
- }
- final long upTime = SystemClock.uptimeMillis();
- scheduleSelf(mInvalidateRunnable,
- upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
- }
-
- /**
- * Returns a color filter to be used as an overlay on the pending icon with cascading motion
- * based on its position.
- */
- private ColorFilter getOverlayFilter() {
- if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
- // If the download has started, we do no need to animate
- return null;
- }
- long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
- + (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
- long time = SystemClock.uptimeMillis();
- int alpha = (int) Utilities.mapBoundToRange(
- (int) ((time + waveMotionDelay) % ALPHA_DURATION_MILLIS),
- 0,
- ALPHA_DURATION_MILLIS,
- 0,
- OVERLAY_ALPHA_RANGE * 2,
- LINEAR);
- if (alpha > OVERLAY_ALPHA_RANGE) {
- alpha = (OVERLAY_ALPHA_RANGE - (alpha % OVERLAY_ALPHA_RANGE));
- }
- int overlayColor = mIsDarkMode ? 0 : 255;
- int currArgb = Color.argb(alpha, overlayColor, overlayColor, overlayColor);
- return COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY);
- }
-
protected static class PreloadIconConstantState extends FastBitmapConstantState {
protected final ItemInfoWithIcon mInfo;
@@ -444,7 +370,6 @@
protected final int[] mPreloadColors;
protected final boolean mIsDarkMode;
protected final int mLevel;
- protected final int mRefreshRateMillis;
private final Path mShapePath;
public PreloadIconConstantState(
@@ -454,7 +379,6 @@
int indicatorColor,
int[] preloadColors,
boolean isDarkMode,
- int refreshRateMillis,
Path shapePath) {
super(bitmap, iconColor);
mInfo = info;
@@ -462,7 +386,6 @@
mPreloadColors = preloadColors;
mIsDarkMode = isDarkMode;
mLevel = info.getProgressLevel();
- mRefreshRateMillis = refreshRateMillis;
mShapePath = shapePath;
}
@@ -473,7 +396,6 @@
mIndicatorColor,
mPreloadColors,
mIsDarkMode,
- mRefreshRateMillis,
mShapePath);
}
}
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 0767e69..372e9bf 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -229,8 +229,8 @@
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
+ Workspace.SECOND_SCREEN_ID;
}
- loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
- query);
+ loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(),
+ LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query);
final SparseArray<Size> spanInfo =
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index cf710da..7f46324 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -770,6 +770,13 @@
}
/**
+ * Sets the input type of the log message.
+ */
+ default StatsLogger withInputType(int inputType) {
+ return this;
+ }
+
+ /**
* Builds the final message and logs it as {@link EventEnum}.
*/
default void log(EventEnum event) {
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 91ace27..358992e 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -63,7 +63,7 @@
protected final BgDataModel mBgDataModel;
private final AllAppsList mBgAllAppsList;
- private final Callbacks[] mCallbacksList;
+ final Callbacks[] mCallbacksList;
private int mMyBindingId;
@@ -293,8 +293,10 @@
// Load items on the current page.
bindWorkspaceItems(currentWorkspaceItems, mUiExecutor);
bindAppWidgets(currentAppWidgets, mUiExecutor);
- mExtraItems.forEach(item ->
- executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mExtraItems.forEach(item ->
+ executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ }
RunnableList pendingTasks = new RunnableList();
Executor pendingExecutor = pendingTasks::add;
@@ -382,14 +384,22 @@
// Save a copy of all the bg-thread collections
ArrayList<ItemInfo> workspaceItems;
ArrayList<LauncherAppWidgetInfo> appWidgets;
+ ArrayList<FixedContainerItems> fciList = new ArrayList<>();
synchronized (mBgDataModel) {
workspaceItems = new ArrayList<>(mBgDataModel.workspaceItems);
appWidgets = new ArrayList<>(mBgDataModel.appWidgets);
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mBgDataModel.extraItems.forEach(fciList::add);
+ }
}
workspaceItems.forEach(it -> mBoundItemIds.add(it.id));
appWidgets.forEach(it -> mBoundItemIds.add(it.id));
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ fciList.forEach(item ->
+ executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
+ }
sortWorkspaceItemsSpatially(mApp.getInvariantDeviceProfile(), workspaceItems);
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
new file mode 100644
index 0000000..3578b67
--- /dev/null
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2023 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.model;
+
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteStatement;
+import android.os.Process;
+import android.os.UserHandle;
+import android.provider.BaseColumns;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.AutoInstallsLayout;
+import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.provider.LauncherDbUtils;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.NoLocaleSQLiteHelper;
+import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.LauncherWidgetHolder;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+/**
+ * SqLite database for launcher home-screen model
+ * The class is subclassed in tests to create an in-memory db.
+ */
+public class DatabaseHelper extends NoLocaleSQLiteHelper implements
+ LayoutParserCallback {
+
+ /**
+ * Represents the schema of the database. Changes in scheme need not be backwards compatible.
+ * When increasing the scheme version, ensure that downgrade_schema.json is updated
+ */
+ public static final int SCHEMA_VERSION = 31;
+ private static final String TAG = "DatabaseHelper";
+ private static final boolean LOGD = false;
+
+ private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
+
+ private final Context mContext;
+ private final boolean mForMigration;
+ private int mMaxItemId = -1;
+ public boolean mHotseatRestoreTableExists;
+
+ public static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
+ return createDatabaseHelper(context, null, forMigration);
+ }
+
+ public static DatabaseHelper createDatabaseHelper(Context context, String dbName,
+ boolean forMigration) {
+ if (dbName == null) {
+ dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile;
+ }
+ DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration);
+ // Table creation sometimes fails silently, which leads to a crash loop.
+ // This way, we will try to create a table every time after crash, so the device
+ // would eventually be able to recover.
+ if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
+ Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
+ // This operation is a no-op if the table already exists.
+ databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true);
+ }
+ databaseHelper.mHotseatRestoreTableExists = tableExists(
+ databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+
+ databaseHelper.initIds();
+ return databaseHelper;
+ }
+
+ /**
+ * Constructor used in tests and for restore.
+ */
+ public DatabaseHelper(Context context, String dbName, boolean forMigration) {
+ super(context, dbName, SCHEMA_VERSION);
+ mContext = context;
+ mForMigration = forMigration;
+ }
+
+ protected void initIds() {
+ // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
+ // the DB here
+ if (mMaxItemId == -1) {
+ mMaxItemId = initializeMaxItemId(getWritableDatabase());
+ }
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ if (LOGD) Log.d(TAG, "creating new launcher database");
+
+ mMaxItemId = 1;
+
+ addFavoritesTable(db, false);
+
+ // Fresh and clean launcher DB.
+ mMaxItemId = initializeMaxItemId(db);
+ if (!mForMigration) {
+ onEmptyDbCreated();
+ }
+ }
+
+ public void onAddOrDeleteOp(SQLiteDatabase db) {
+ if (mHotseatRestoreTableExists) {
+ dropTable(db, Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+ mHotseatRestoreTableExists = false;
+ }
+ }
+
+ /**
+ * Re-composite given key in respect to database. If the current db is
+ * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
+ * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
+ * string will be "EMPTY_DATABASE_CREATED@minimal.db".
+ */
+ public String getKey(final String key) {
+ if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
+ return key;
+ }
+ return key + "@" + getDatabaseName();
+ }
+
+ /**
+ * Overridden in tests.
+ */
+ protected void onEmptyDbCreated() {
+ // Set the flag for empty DB
+ LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(
+ LauncherProvider.EMPTY_DATABASE_CREATED), true)
+ .commit();
+ }
+
+ public long getSerialNumberForUser(UserHandle user) {
+ return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
+ }
+
+ public long getDefaultUserSerial() {
+ return getSerialNumberForUser(Process.myUserHandle());
+ }
+
+ private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
+ Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
+ }
+
+ @Override
+ public void onOpen(SQLiteDatabase db) {
+ super.onOpen(db);
+
+ File schemaFile = mContext.getFileStreamPath(DOWNGRADE_SCHEMA_FILE);
+ if (!schemaFile.exists()) {
+ handleOneTimeDataUpgrade(db);
+ }
+ DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext);
+ }
+
+ /**
+ * One-time data updated before support of onDowngrade was added. This update is backwards
+ * compatible and can safely be run multiple times.
+ * Note: No new logic should be added here after release, as the new logic might not get
+ * executed on an existing device.
+ * TODO: Move this to db upgrade path, once the downgrade path is released.
+ */
+ protected void handleOneTimeDataUpgrade(SQLiteDatabase db) {
+ // Remove "profile extra"
+ UserCache um = UserCache.INSTANCE.get(mContext);
+ for (UserHandle user : um.getUserProfiles()) {
+ long serial = um.getSerialNumberForUser(user);
+ String sql = "update favorites set intent = replace(intent, "
+ + "';l.profile=" + serial + ";', ';') where itemType = 0;";
+ db.execSQL(sql);
+ }
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (LOGD) {
+ Log.d(TAG, "onUpgrade triggered: " + oldVersion);
+ }
+ switch (oldVersion) {
+ // The version cannot be lower that 12, as Launcher3 never supported a lower
+ // version of the DB.
+ case 12:
+ // No-op
+ case 13: {
+ try (SQLiteTransaction t = new SQLiteTransaction(db)) {
+ // Insert new column for holding widget provider name
+ db.execSQL("ALTER TABLE favorites ADD COLUMN appWidgetProvider TEXT;");
+ t.commit();
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 14: {
+ if (!addIntegerColumn(db, Favorites.MODIFIED, 0)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 15: {
+ if (!addIntegerColumn(db, Favorites.RESTORED, 0)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 16:
+ // No-op
+ case 17:
+ // No-op
+ case 18:
+ // No-op
+ case 19: {
+ // Add userId column
+ if (!addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial())) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 20:
+ if (!updateFolderItemsRank(db, true)) {
+ break;
+ }
+ case 21:
+ // No-op
+ case 22: {
+ if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 23:
+ // No-op
+ case 24:
+ // No-op
+ case 25:
+ convertShortcutsToLauncherActivities(db);
+ case 26:
+ // QSB was moved to the grid. Ignore overlapping items
+ case 27: {
+ // Update the favorites table so that the screen ids are ordered based on
+ // workspace page rank.
+ IntArray finalScreens = LauncherDbUtils.queryIntArray(false, db,
+ "workspaceScreens", BaseColumns._ID, null, null, "screenRank");
+ int[] original = finalScreens.toArray();
+ Arrays.sort(original);
+ String updatemap = "";
+ for (int i = 0; i < original.length; i++) {
+ if (finalScreens.get(i) != original[i]) {
+ updatemap += String.format(Locale.ENGLISH, " WHEN %1$s=%2$d THEN %3$d",
+ Favorites.SCREEN, finalScreens.get(i), original[i]);
+ }
+ }
+ if (!TextUtils.isEmpty(updatemap)) {
+ String query = String.format(Locale.ENGLISH,
+ "UPDATE %1$s SET %2$s=CASE %3$s ELSE %2$s END WHERE %4$s = %5$d",
+ Favorites.TABLE_NAME, Favorites.SCREEN, updatemap,
+ Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP);
+ db.execSQL(query);
+ }
+ dropTable(db, "workspaceScreens");
+ }
+ case 28: {
+ boolean columnAdded = addIntegerColumn(
+ db, Favorites.APPWIDGET_SOURCE, Favorites.CONTAINER_UNKNOWN);
+ if (!columnAdded) {
+ // Old version remains, which means we wipe old data
+ break;
+ }
+ }
+ case 29: {
+ // Remove widget panel related leftover workspace items
+ db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
+ Favorites.SCREEN, IntArray.wrap(-777, -778)), null);
+ }
+ case 30: {
+ if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
+ // Clean up first row in screen 0 as it might contain junk data.
+ Log.d(TAG, "Cleaning up first row");
+ db.delete(Favorites.TABLE_NAME,
+ String.format(Locale.ENGLISH,
+ "%1$s = %2$d AND %3$s = %4$d AND %5$s = %6$d",
+ Favorites.SCREEN, 0,
+ Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP,
+ Favorites.CELLY, 0), null);
+ }
+ return;
+ }
+ case 31: {
+ // DB Upgraded successfully
+ return;
+ }
+ }
+
+ // DB was not upgraded
+ Log.w(TAG, "Destroying all old data.");
+ createEmptyDB(db);
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ try {
+ DbDowngradeHelper.parse(mContext.getFileStreamPath(DOWNGRADE_SCHEMA_FILE))
+ .onDowngrade(db, oldVersion, newVersion);
+ } catch (Exception e) {
+ Log.d(TAG, "Unable to downgrade from: " + oldVersion + " to " + newVersion
+ + ". Wiping database.", e);
+ createEmptyDB(db);
+ }
+ }
+
+ /**
+ * Clears all the data for a fresh start.
+ */
+ public void createEmptyDB(SQLiteDatabase db) {
+ try (SQLiteTransaction t = new SQLiteTransaction(db)) {
+ dropTable(db, Favorites.TABLE_NAME);
+ dropTable(db, "workspaceScreens");
+ onCreate(db);
+ t.commit();
+ }
+ }
+
+ /**
+ * Removes widgets which are registered to the Launcher's host, but are not present
+ * in our model.
+ */
+ public void removeGhostWidgets(SQLiteDatabase db) {
+ // Get all existing widget ids.
+ final LauncherWidgetHolder holder = newLauncherWidgetHolder();
+ try {
+ final int[] allWidgets;
+ try {
+ // Although the method was defined in O, it has existed since the beginning of
+ // time, so it might work on older platforms as well.
+ allWidgets = holder.getAppWidgetIds();
+ } catch (IncompatibleClassChangeError e) {
+ Log.e(TAG, "getAppWidgetIds not supported", e);
+ return;
+ }
+ final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(false, db,
+ Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
+ "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
+ boolean isAnyWidgetRemoved = false;
+ for (int widgetId : allWidgets) {
+ if (!validWidgets.contains(widgetId)) {
+ try {
+ FileLog.d(TAG, "Deleting invalid widget " + widgetId);
+ holder.deleteAppWidgetId(widgetId);
+ isAnyWidgetRemoved = true;
+ } catch (RuntimeException e) {
+ // Ignore
+ }
+ }
+ }
+ if (isAnyWidgetRemoved) {
+ final String allWidgetsIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
+ .collect(Collectors.joining(",", "[", "]"));
+ final String validWidgetsIds = Arrays.stream(
+ validWidgets.getArray().toArray()).mapToObj(String::valueOf)
+ .collect(Collectors.joining(",", "[", "]"));
+ FileLog.d(TAG,
+ "One or more widgets was removed. db_path=" + db.getPath()
+ + " allWidgetsIds=" + allWidgetsIds
+ + ", validWidgetsIds=" + validWidgetsIds);
+ }
+ } finally {
+ holder.destroy();
+ }
+ }
+
+ /**
+ * Replaces all shortcuts of type {@link Favorites#ITEM_TYPE_SHORTCUT} which have a valid
+ * launcher activity target with {@link Favorites#ITEM_TYPE_APPLICATION}.
+ */
+ @Thunk
+ void convertShortcutsToLauncherActivities(SQLiteDatabase db) {
+ try (SQLiteTransaction t = new SQLiteTransaction(db);
+ // Only consider the primary user as other users can't have a shortcut.
+ Cursor c = db.query(Favorites.TABLE_NAME,
+ new String[]{Favorites._ID, Favorites.INTENT},
+ "itemType=" + Favorites.ITEM_TYPE_SHORTCUT
+ + " AND profileId=" + getDefaultUserSerial(),
+ null, null, null, null);
+ SQLiteStatement updateStmt = db.compileStatement("UPDATE favorites SET itemType="
+ + Favorites.ITEM_TYPE_APPLICATION + " WHERE _id=?")
+ ) {
+ final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
+ final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT);
+
+ while (c.moveToNext()) {
+ String intentDescription = c.getString(intentIndex);
+ Intent intent;
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Unable to parse intent", e);
+ continue;
+ }
+
+ if (!PackageManagerHelper.isLauncherAppTarget(intent)) {
+ continue;
+ }
+
+ int id = c.getInt(idIndex);
+ updateStmt.bindLong(1, id);
+ updateStmt.executeUpdateDelete();
+ }
+ t.commit();
+ } catch (SQLException ex) {
+ Log.w(TAG, "Error deduping shortcuts", ex);
+ }
+ }
+
+ @Thunk
+ boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) {
+ try (SQLiteTransaction t = new SQLiteTransaction(db)) {
+ if (addRankColumn) {
+ // Insert new column for holding rank
+ db.execSQL("ALTER TABLE favorites ADD COLUMN rank INTEGER NOT NULL DEFAULT 0;");
+ }
+
+ // Get a map for folder ID to folder width
+ Cursor c = db.rawQuery("SELECT container, MAX(cellX) FROM favorites"
+ + " WHERE container IN (SELECT _id FROM favorites WHERE itemType = ?)"
+ + " GROUP BY container;",
+ new String[]{Integer.toString(Favorites.ITEM_TYPE_FOLDER)});
+
+ while (c.moveToNext()) {
+ db.execSQL("UPDATE favorites SET rank=cellX+(cellY*?) WHERE "
+ + "container=? AND cellX IS NOT NULL AND cellY IS NOT NULL;",
+ new Object[]{c.getLong(1) + 1, c.getLong(0)});
+ }
+
+ c.close();
+ t.commit();
+ } catch (SQLException ex) {
+ // Old version remains, which means we wipe old data
+ Log.e(TAG, ex.getMessage(), ex);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) {
+ try (SQLiteTransaction t = new SQLiteTransaction(db)) {
+ db.execSQL("ALTER TABLE favorites ADD COLUMN "
+ + columnName + " INTEGER NOT NULL DEFAULT " + defaultValue + ";");
+ t.commit();
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ return false;
+ }
+ return true;
+ }
+
+ // Generates a new ID to use for an object in your database. This method should be only
+ // called from the main UI thread. As an exception, we do call it when we call the
+ // constructor from the worker thread; however, this doesn't extend until after the
+ // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
+ // after that point
+ @Override
+ public int generateNewItemId() {
+ if (mMaxItemId < 0) {
+ throw new RuntimeException("Error: max item id was not initialized");
+ }
+ mMaxItemId += 1;
+ return mMaxItemId;
+ }
+
+ /**
+ * @return A new {@link LauncherWidgetHolder} based on the current context
+ */
+ @NonNull
+ public LauncherWidgetHolder newLauncherWidgetHolder() {
+ return LauncherWidgetHolder.newInstance(mContext);
+ }
+
+ @Override
+ public int insertAndCheck(SQLiteDatabase db, ContentValues values) {
+ return dbInsertAndCheck(db, Favorites.TABLE_NAME, values);
+ }
+
+ public int dbInsertAndCheck(SQLiteDatabase db, String table, ContentValues values) {
+ if (values == null) {
+ throw new RuntimeException("Error: attempting to insert null values");
+ }
+ if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+ throw new RuntimeException("Error: attempting to add item without specifying an id");
+ }
+ checkId(values);
+ return (int) db.insert(table, null, values);
+ }
+
+ public void checkId(ContentValues values) {
+ int id = values.getAsInteger(Favorites._ID);
+ mMaxItemId = Math.max(id, mMaxItemId);
+ }
+
+ private int initializeMaxItemId(SQLiteDatabase db) {
+ return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s", Favorites._ID,
+ Favorites.TABLE_NAME);
+ }
+
+ /**
+ * Returns a new ID to use for a workspace screen in your database that is greater than all
+ * existing screen IDs
+ */
+ public int getNewScreenId() {
+ return getMaxId(getWritableDatabase(),
+ "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d AND %1$s >= 0",
+ Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER,
+ Favorites.CONTAINER_DESKTOP) + 1;
+ }
+
+ public int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
+ // TODO: Use multiple loaders with fall-back and transaction.
+ int count = loader.loadLayout(db, new IntArray());
+
+ // Ensure that the max ids are initialized
+ mMaxItemId = initializeMaxItemId(db);
+ return count;
+ }
+
+ /**
+ * @return the max _id in the provided table.
+ */
+ private static int getMaxId(SQLiteDatabase db, String query, Object... args) {
+ int max = 0;
+ try (SQLiteStatement prog = db.compileStatement(
+ String.format(Locale.ENGLISH, query, args))) {
+ max = (int) DatabaseUtils.longForQuery(prog, null);
+ if (max < 0) {
+ throw new RuntimeException("Error: could not query max id");
+ }
+ } catch (IllegalArgumentException exception) {
+ String message = exception.getMessage();
+ if (message.contains("re-open") && message.contains("already-closed")) {
+ // Don't crash trying to end a transaction an an already closed DB. See b/173162852.
+ } else {
+ throw exception;
+ }
+ }
+ return max;
+ }
+}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index da9be49..481cc6e 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -138,6 +138,7 @@
private final UserManagerState mUserManagerState = new UserManagerState();
protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();
+ private Map<ShortcutKey, ShortcutInfo> mShortcutKeyToPinnedShortcuts;
private boolean mStopped;
@@ -211,6 +212,14 @@
}
logASplit(timingLogger, "loadWorkspace");
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ verifyNotStopped();
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.markActive();
+ logASplit(timingLogger, "workspaceDelegateItems");
+ }
+
// 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
// from the main db as defined in the invariant device profile.
@@ -246,6 +255,11 @@
}
logASplit(timingLogger, "loadAllApps");
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ logASplit(timingLogger, "allAppsDelegateItems");
+ }
verifyNotStopped();
mLauncherBinder.bindAllApps();
logASplit(timingLogger, "bindAllApps");
@@ -296,6 +310,12 @@
logASplit(timingLogger, "bindWidgets");
verifyNotStopped();
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
+ logASplit(timingLogger, "otherDelegateItems");
+ verifyNotStopped();
+ }
+
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
@@ -334,9 +354,14 @@
null /* selection */, memoryLogger);
}
- protected void loadWorkspace(
+ protected void loadWorkspaceForPreviewSurfaceRenderer(
List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
loadWorkspace(allDeepShortcuts, contentUri, selection, null);
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.markActive();
+ }
}
protected void loadWorkspace(
@@ -376,7 +401,7 @@
final PackageUserKey tempPackageKey = new PackageUserKey(null, null);
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
- Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts = new HashMap<>();
+ mShortcutKeyToPinnedShortcuts = new HashMap<>();
final LoaderCursor c = new LoaderCursor(
contentResolver.query(contentUri, null, selection, null, null), contentUri,
mApp, mUserManagerState);
@@ -397,7 +422,7 @@
.query(ShortcutRequest.PINNED);
if (pinnedShortcuts.wasSuccess()) {
for (ShortcutInfo shortcut : pinnedShortcuts) {
- shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),
+ mShortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),
shortcut);
}
} else {
@@ -414,22 +439,22 @@
while (!mStopped && c.moveToNext()) {
processWorkspaceItem(c, memoryLogger, installingPkgs, isSdCardReady,
- tempPackageKey, widgetHelper, pmHelper, shortcutKeyToPinnedShortcuts,
+ tempPackageKey, widgetHelper, pmHelper,
iconRequestInfos, unlockedUsers, isSafeMode, allDeepShortcuts);
}
- maybeLoadWorkspaceIconsInBulk(iconRequestInfos);
+ tryLoadWorkspaceIconsInBulk(iconRequestInfos);
} finally {
IOUtils.closeSilently(c);
}
- // Load delegate items
- mModelDelegate.loadHotseatItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
- mModelDelegate.loadAllAppsItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
- mModelDelegate.loadWidgetsRecommendationItems();
- mModelDelegate.markActive();
-
- // Load string cache
- mModelDelegate.loadStringCache(mBgDataModel.stringCache);
+ if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
+ mModelDelegate.markActive();
+ }
// Break early if we've stopped loading
if (mStopped) {
@@ -474,7 +499,6 @@
PackageUserKey tempPackageKey,
WidgetManagerHelper widgetHelper,
PackageManagerHelper pmHelper,
- Map<ShortcutKey, ShortcutInfo> shortcutKeyToPinnedShortcuts,
List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos,
LongSparseArray<Boolean> unlockedUsers,
boolean isSafeMode,
@@ -598,12 +622,12 @@
// Already verified above that user is same as default user
info = c.getRestoredItemInfo(intent);
} else if (c.itemType == Favorites.ITEM_TYPE_APPLICATION) {
- info = c.getAppShortcutInfo(intent, allowMissingTarget, useLowResIcon,
- !FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get());
+ info = c.getAppShortcutInfo(
+ intent, allowMissingTarget, useLowResIcon, false);
} else if (c.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
ShortcutKey key = ShortcutKey.fromIntent(intent, c.user);
if (unlockedUsers.get(c.serialNumber)) {
- ShortcutInfo pinnedShortcut = shortcutKeyToPinnedShortcuts.get(key);
+ ShortcutInfo pinnedShortcut = mShortcutKeyToPinnedShortcuts.get(key);
if (pinnedShortcut == null) {
// The shortcut is no longer valid.
c.markDeleted("Pinned shortcut not found");
@@ -861,21 +885,19 @@
}
}
- private void maybeLoadWorkspaceIconsInBulk(
+ private void tryLoadWorkspaceIconsInBulk(
List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos) {
- if (FeatureFlags.ENABLE_BULK_WORKSPACE_ICON_LOADING.get()) {
- Trace.beginSection("LoadWorkspaceIconsInBulk");
- try {
- mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
- for (IconRequestInfo<WorkspaceItemInfo> iconRequestInfo : iconRequestInfos) {
- WorkspaceItemInfo wai = iconRequestInfo.itemInfo;
- if (mIconCache.isDefaultIcon(wai.bitmap, wai.user)) {
- iconRequestInfo.loadWorkspaceIcon(mApp.getContext());
- }
+ Trace.beginSection("LoadWorkspaceIconsInBulk");
+ try {
+ mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
+ for (IconRequestInfo<WorkspaceItemInfo> iconRequestInfo : iconRequestInfos) {
+ WorkspaceItemInfo wai = iconRequestInfo.itemInfo;
+ if (mIconCache.isDefaultIcon(wai.bitmap, wai.user)) {
+ iconRequestInfo.loadWorkspaceIcon(mApp.getContext());
}
- } finally {
- Trace.endSection();
}
+ } finally {
+ Trace.endSection();
}
}
@@ -960,7 +982,7 @@
iconRequestInfos.add(new IconRequestInfo<>(
appInfo, app, /* useLowResIcon= */ false));
mBgAllAppsList.add(
- appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
+ appInfo, app, false);
}
allActivityList.addAll(apps);
}
@@ -973,7 +995,7 @@
AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp(
mApp.getContext(),
PackageInstallInfo.fromInstallingState(info),
- !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
+ false);
if (promiseAppInfo != null) {
iconRequestInfos.add(new IconRequestInfo<>(
@@ -984,15 +1006,13 @@
}
}
- if (FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()) {
- Trace.beginSection("LoadAllAppsIconsInBulk");
- try {
- mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
- iconRequestInfos.forEach(iconRequestInfo ->
- mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
- } finally {
- Trace.endSection();
- }
+ Trace.beginSection("LoadAllAppsIconsInBulk");
+ try {
+ mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
+ iconRequestInfos.forEach(iconRequestInfo ->
+ mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
+ } finally {
+ Trace.endSection();
}
mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED,
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 0639a6c..7e7bfb3 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.ShortcutInfo;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
@@ -68,9 +69,7 @@
this.mContext = context;
}
- /**
- * Called periodically to validate and update any data
- */
+ /** Called periodically to validate and update any data */
@WorkerThread
public void validateData() {
if (hasShortcutsPermission(mApp.getContext())
@@ -79,36 +78,32 @@
}
}
- /**
- * Load hot seat items if any in the data model
- */
+ /** Load workspace items (for example, those in the hot seat) if any in the data model */
@WorkerThread
- public void loadHotseatItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+ public void loadAndBindWorkspaceItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
- /**
- * Load all apps items if any in the data model
- */
+ /** Load all apps items if any in the data model */
@WorkerThread
- public void loadAllAppsItems(UserManagerState ums,
- Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
+ public void loadAndBindAllAppsItems(@NonNull UserManagerState ums,
+ @NonNull BgDataModel.Callbacks[] callbacks,
+ @NonNull Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
- /**
- * Load widget recommendation items if any in the data model
- */
+ /** Load other items like widget recommendations if any in the data model */
@WorkerThread
- public void loadWidgetsRecommendationItems() { }
+ public void loadAndBindOtherItems(@NonNull BgDataModel.Callbacks[] callbacks) { }
- /**
- * Marks the ModelDelegate as active
- */
+ /** binds everything not bound by launcherBinder */
+ @WorkerThread
+ public void bindAllModelExtras(@NonNull BgDataModel.Callbacks[] callbacks) { }
+
+ /** Marks the ModelDelegate as active */
public void markActive() { }
- /**
- * Load String cache
- */
+ /** Load String cache */
@WorkerThread
- public void loadStringCache(StringCache cache) {
+ public void loadStringCache(@NonNull StringCache cache) {
cache.loadStrings(mContext);
}
diff --git a/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java b/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
deleted file mode 100644
index 8a21d13..0000000
--- a/src/com/android/launcher3/pageindicators/LauncherDotsPageIndicator.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2023 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.pageindicators;
-
-import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
-
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.ViewConfiguration;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Alarm;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.util.MultiValueAlpha;
-
-/**
- * Extension of {@link PageIndicatorDots} with Launcher specific page-indicator functionality
- */
-public class LauncherDotsPageIndicator extends PageIndicatorDots
- implements Insettable, PageIndicator {
-
- private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
- private static final int PAGINATION_FADE_IN_DURATION = 83;
- private static final int PAGINATION_FADE_OUT_DURATION = 167;
-
- private static final int INDEX_VIEW_ALPHA = 0;
- private static final int INDEX_AUTO_HIDE = 1;
- private static final int ALPHA_CHANNEL_COUNT = 2;
-
- private final Alarm mAutoHideAlarm;
- private final MultiValueAlpha mMultiValueAlpha;
-
- private @Nullable ObjectAnimator mAlphaAnimator;
- private boolean mShouldAutoHide;
- private float mTargetAutoHideAlpha;
-
- private boolean mIsSettled = true;
- private int mTotalScroll;
-
- public LauncherDotsPageIndicator(Context context) {
- this(context, null);
- }
-
- public LauncherDotsPageIndicator(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public LauncherDotsPageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT);
- mMultiValueAlpha.setUpdateVisibility(true);
-
- mTargetAutoHideAlpha = mMultiValueAlpha.get(INDEX_AUTO_HIDE).getValue();
-
- mAutoHideAlarm = new Alarm();
- mAutoHideAlarm.setOnAlarmListener(a -> animatePaginationToAlpha(0));
- }
-
- @Override
- public void setScroll(int currentScroll, int totalScroll) {
- mTotalScroll = totalScroll;
- super.setScroll(currentScroll, totalScroll);
- }
-
- @Override
- public void setShouldAutoHide(boolean shouldAutoHide) {
- mShouldAutoHide = shouldAutoHide;
- mAutoHideAlarm.cancelAlarm();
- if (!mIsSettled || !mShouldAutoHide) {
- animatePaginationToAlpha(1);
- } else {
- mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (mShouldAutoHide && mTotalScroll == 0) {
- return;
- }
- super.onDraw(canvas);
- }
-
- @Override
- public void setActiveMarker(int activePage) {
- super.setActiveMarker(activePage);
- }
-
- @Override
- public void setMarkersCount(int numMarkers) {
- super.setMarkersCount(numMarkers);
- }
-
- @Override
- public void pauseAnimations() {
- if (mAlphaAnimator != null) {
- mAlphaAnimator.pause();
- }
- }
-
- @Override
- public void skipAnimationsToEnd() {
- if (mAlphaAnimator != null) {
- mAlphaAnimator.end();
- }
- }
-
- @Override
- protected void onAnimationStateChanged(boolean isSettled) {
- mIsSettled = isSettled;
- if (!mShouldAutoHide) {
- return;
- }
- mAutoHideAlarm.cancelAlarm();
- if (isSettled) {
- mAutoHideAlarm.setAlarm(PAGINATION_FADE_DELAY);
- } else {
- animatePaginationToAlpha(1f);
- }
- }
-
- private void animatePaginationToAlpha(float targetAlpha) {
- if (mTargetAutoHideAlpha == targetAlpha) {
- // Ignore the new animation if it is going to the same alpha as the current animation.
- return;
- }
-
- if (mAlphaAnimator != null) {
- mAlphaAnimator.cancel();
- }
- mAlphaAnimator = ObjectAnimator.ofFloat(mMultiValueAlpha.get(INDEX_AUTO_HIDE),
- MULTI_PROPERTY_VALUE, targetAlpha);
- // If we are animating to decrease the alpha, then it's a fade out animation
- // whereas if we are animating to increase the alpha, it's a fade in animation.
- mAlphaAnimator.setDuration(targetAlpha == 0
- ? PAGINATION_FADE_OUT_DURATION
- : PAGINATION_FADE_IN_DURATION);
- mAlphaAnimator.addListener(forEndCallback(() -> mAlphaAnimator = null));
- mAlphaAnimator.start();
- mTargetAutoHideAlpha = targetAlpha;
- }
-
-
- @Override
- public void stopAllAnimations() {
- super.stopAllAnimations();
- }
-
- @Override
- public void prepareEntryAnimation() {
- super.prepareEntryAnimation();
- }
-
- @Override
- public void playEntryAnimation() {
- super.playEntryAnimation();
- }
-
- /**
- * We need to override setInsets to prevent InsettableFrameLayout from applying different
- * margins on the pagination.
- */
- @Override
- public void setInsets(Rect insets) {
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- @Override
- public void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
- setter.setFloat(mMultiValueAlpha.get(INDEX_VIEW_ALPHA),
- MULTI_PROPERTY_VALUE, alpha, interpolator);
- }
-}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 193f50d..570d6ff 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -15,11 +15,6 @@
*/
package com.android.launcher3.pageindicators;
-import android.animation.TimeInterpolator;
-import android.view.View;
-
-import com.android.launcher3.anim.PropertySetter;
-
/**
* Base class for a page indicator.
*/
@@ -53,9 +48,9 @@
}
/**
- * Sets the provided alpha on the pageIndicator
+ * Sets the paint color.
*/
- default void setAlpha(PropertySetter setter, float alpha, TimeInterpolator interpolator) {
- setter.setViewAlpha((View) this, alpha, interpolator);
+ default void setPaintColor(int color) {
+ // No-op by default
}
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 95452b9..b2c64b3 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -25,30 +25,42 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
-import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.Handler;
+import android.os.Looper;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.util.IntProperty;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewOutlineProvider;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Themes;
/**
* {@link PageIndicator} which shows dots per page. The active page is shown with the current
* accent color.
*/
-public class PageIndicatorDots extends View {
+public class PageIndicatorDots extends View implements Insettable, PageIndicator {
private static final float SHIFT_PER_ANIMATION = 0.5f;
private static final float SHIFT_THRESHOLD = 0.1f;
private static final long ANIMATION_DURATION = 150;
+ private static final int PAGINATION_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
+ private static final int PAGINATION_FADE_IN_DURATION = 83;
+ private static final int PAGINATION_FADE_OUT_DURATION = 167;
private static final int ENTER_ANIMATION_START_DELAY = 300;
private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
@@ -58,6 +70,9 @@
private static final int DOT_ALPHA = 128;
private static final float DOT_ALPHA_FRACTION = 0.5f;
private static final int DOT_GAP_FACTOR = SHOW_DOT_PAGINATION.get() ? 4 : 3;
+ private static final int VISIBLE_ALPHA = 255;
+ private static final int INVISIBLE_ALPHA = 0;
+ private Paint mPaginationPaint;
// This value approximately overshoots to 1.5 times the original size.
private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f;
@@ -79,14 +94,30 @@
}
};
+ private static final IntProperty<PageIndicatorDots> PAGINATION_ALPHA =
+ new IntProperty<PageIndicatorDots>("pagination_alpha") {
+ @Override
+ public Integer get(PageIndicatorDots obj) {
+ return obj.mPaginationPaint.getAlpha();
+ }
+
+ @Override
+ public void setValue(PageIndicatorDots obj, int alpha) {
+ obj.mPaginationPaint.setAlpha(alpha);
+ obj.invalidate();
+ }
+ };
+
+ private final Handler mDelayedPaginationFadeHandler = new Handler(Looper.getMainLooper());
private final float mDotRadius;
private final float mCircleGap;
private final boolean mIsRtl;
- private final Paint mPaginationPaint;
-
private int mNumPages;
private int mActivePage;
+ private int mTotalScroll;
+ private boolean mShouldAutoHide;
+ private int mToAlpha;
/**
* The current position of the active dot including the animation progress.
@@ -100,9 +131,13 @@
private float mCurrentPosition;
private float mFinalPosition;
private ObjectAnimator mAnimator;
+ private @Nullable ObjectAnimator mAlphaAnimator;
private float[] mEntryAnimationRadiusFactors;
+ private final Runnable mHidePaginationRunnable =
+ () -> animatePaginationToAlpha(INVISIBLE_ALPHA);
+
public PageIndicatorDots(Context context) {
this(context, null);
}
@@ -116,34 +151,37 @@
mPaginationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaginationPaint.setStyle(Style.FILL);
-
- TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PagedIndicator);
- mPaginationPaint.setColor(ta.getColor(R.styleable.PagedIndicator_indicatorDotColor, 0));
- ta.recycle();
-
+ mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
mDotRadius = (SHOW_DOT_PAGINATION.get()
? getResources().getDimension(R.dimen.page_indicator_dot_size_v2)
: getResources().getDimension(R.dimen.page_indicator_dot_size))
/ 2;
mCircleGap = DOT_GAP_FACTOR * mDotRadius;
setOutlineProvider(new MyOutlineProver());
- mIsRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ mIsRtl = Utilities.isRtl(getResources());
}
+ @Override
public void setScroll(int currentScroll, int totalScroll) {
if (SHOW_DOT_PAGINATION.get() && mActivePage != 0 && currentScroll == 0) {
CURRENT_POSITION.set(this, (float) mActivePage);
return;
}
- if (mNumPages <= 1 || totalScroll == 0) {
+ if (mNumPages <= 1) {
return;
}
+ if (mShouldAutoHide) {
+ animatePaginationToAlpha(VISIBLE_ALPHA);
+ }
+
if (mIsRtl) {
currentScroll = totalScroll - currentScroll;
}
+ mTotalScroll = totalScroll;
+
int scrollPerPage = totalScroll / (mNumPages - 1);
int pageToLeft = scrollPerPage == 0 ? 0 : currentScroll / scrollPerPage;
int pageToLeftScroll = pageToLeft * scrollPerPage;
@@ -153,12 +191,87 @@
if (currentScroll < pageToLeftScroll + scrollThreshold) {
// scroll is within the left page's threshold
animateToPosition(pageToLeft);
+ if (mShouldAutoHide) {
+ hideAfterDelay();
+ }
} else if (currentScroll > pageToRightScroll - scrollThreshold) {
// scroll is far enough from left page to go to the right page
animateToPosition(pageToLeft + 1);
+ if (mShouldAutoHide) {
+ hideAfterDelay();
+ }
} else {
// scroll is between left and right page
animateToPosition(pageToLeft + SHIFT_PER_ANIMATION);
+ if (mShouldAutoHide) {
+ mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+ }
+ }
+ }
+
+ @Override
+ public void setShouldAutoHide(boolean shouldAutoHide) {
+ mShouldAutoHide = shouldAutoHide && SHOW_DOT_PAGINATION.get();
+ if (shouldAutoHide && mPaginationPaint.getAlpha() > INVISIBLE_ALPHA) {
+ hideAfterDelay();
+ } else if (!shouldAutoHide) {
+ mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ @Override
+ public void setPaintColor(int color) {
+ mPaginationPaint.setColor(color);
+ }
+
+ private void hideAfterDelay() {
+ mDelayedPaginationFadeHandler.removeCallbacksAndMessages(null);
+ mDelayedPaginationFadeHandler.postDelayed(mHidePaginationRunnable, PAGINATION_FADE_DELAY);
+ }
+
+ private void animatePaginationToAlpha(int alpha) {
+ if (alpha == mToAlpha) {
+ // Ignore the new animation if it is going to the same alpha as the current animation.
+ return;
+ }
+
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.cancel();
+ }
+ mAlphaAnimator = ObjectAnimator.ofInt(this, PAGINATION_ALPHA,
+ alpha);
+ // If we are animating to decrease the alpha, then it's a fade out animation
+ // whereas if we are animating to increase the alpha, it's a fade in animation.
+ mAlphaAnimator.setDuration(alpha < mToAlpha
+ ? PAGINATION_FADE_OUT_DURATION
+ : PAGINATION_FADE_IN_DURATION);
+ mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAlphaAnimator = null;
+ }
+ });
+ mAlphaAnimator.start();
+ mToAlpha = alpha;
+ }
+
+ /**
+ * Pauses all currently running animations.
+ */
+ @Override
+ public void pauseAnimations() {
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.pause();
+ }
+ }
+
+ /**
+ * Force-ends all currently running or paused animations.
+ */
+ @Override
+ public void skipAnimationsToEnd() {
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.end();
}
}
@@ -168,25 +281,15 @@
mCurrentPosition = mFinalPosition;
}
if (mAnimator == null && Float.compare(mCurrentPosition, mFinalPosition) != 0) {
- onAnimationStateChanged(false);
float positionForThisAnim = mCurrentPosition > mFinalPosition ?
mCurrentPosition - SHIFT_PER_ANIMATION : mCurrentPosition + SHIFT_PER_ANIMATION;
mAnimator = ObjectAnimator.ofFloat(this, CURRENT_POSITION, positionForThisAnim);
mAnimator.addListener(new AnimationCycleListener());
mAnimator.setDuration(ANIMATION_DURATION);
mAnimator.start();
- } else if (mAnimator == null) {
- // The state is only settled if the indicator lands on a int value
- onAnimationStateChanged(Float.compare(Math.round(mFinalPosition), mFinalPosition) == 0);
}
}
- /**
- * Called when the animation state of the page indicator changes.
- * @param isSettled true if the page indicator has settled at its final position
- */
- protected void onAnimationStateChanged(boolean isSettled) { }
-
public void stopAllAnimations() {
if (mAnimator != null) {
mAnimator.cancel();
@@ -242,10 +345,14 @@
animSet.start();
}
+ @Override
public void setActiveMarker(int activePage) {
- mActivePage = activePage;
+ if (mActivePage != activePage) {
+ mActivePage = activePage;
+ }
}
+ @Override
public void setMarkersCount(int numMarkers) {
mNumPages = numMarkers;
requestLayout();
@@ -267,6 +374,11 @@
return;
}
+ if (mShouldAutoHide && mTotalScroll == 0) {
+ mPaginationPaint.setAlpha(INVISIBLE_ALPHA);
+ return;
+ }
+
// Draw all page indicators;
float circleGap = mCircleGap;
float startX = (getWidth() - (mNumPages * circleGap) + mDotRadius) / 2;
@@ -368,9 +480,20 @@
@Override
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
+ if (mShouldAutoHide && SHOW_DOT_PAGINATION.get()) {
+ hideAfterDelay();
+ }
mAnimator = null;
animateToPosition(mFinalPosition);
}
}
}
+
+ /**
+ * We need to override setInsets to prevent InsettableFrameLayout from applying different
+ * margins on the pagination.
+ */
+ @Override
+ public void setInsets(Rect insets) {
+ }
}
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 125b4ce..47bfe85 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -29,14 +29,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -204,26 +201,6 @@
return list;
}
- /**
- * Attempt to restore workspace layout if the session is triggered due to device restore.
- */
- public boolean restoreDbIfApplicable(@NonNull final SessionInfo info) {
- if (!FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
- return false;
- }
- if (isRestore(info)) {
- LauncherSettings.Settings.call(mAppContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE);
- return true;
- }
- return false;
- }
-
- @RequiresApi(26)
- private static boolean isRestore(@NonNull final SessionInfo info) {
- return info.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_RESTORE;
- }
-
@WorkerThread
public boolean promiseIconAddedForId(final int sessionId) {
return getPromiseIconIds().contains(sessionId);
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 0edf292..5b493c2 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -109,7 +109,7 @@
protected final int mArrowPointRadius;
protected final View mArrow;
- private final int mMargin;
+ protected final int mChildContainerMargin;
protected boolean mIsLeftAligned;
protected boolean mIsAboveIcon;
@@ -145,7 +145,7 @@
// Initialize arrow view
final Resources resources = getResources();
mArrowColor = getColorStateList(getContext(), R.color.popup_shade_first).getDefaultColor();
- mMargin = resources.getDimensionPixelSize(R.dimen.popup_margin);
+ mChildContainerMargin = resources.getDimensionPixelSize(R.dimen.popup_margin);
mArrowWidth = resources.getDimensionPixelSize(R.dimen.popup_arrow_width);
mArrowHeight = resources.getDimensionPixelSize(R.dimen.popup_arrow_height);
mArrow = new View(context);
@@ -249,7 +249,7 @@
if (view.getVisibility() == VISIBLE) {
if (lastView != null) {
MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
- mlp.bottomMargin = mMargin;
+ mlp.bottomMargin = mChildContainerMargin;
}
lastView = view;
MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
@@ -441,7 +441,7 @@
numVisibleChildren++;
}
}
- int childMargins = (numVisibleChildren - 1) * mMargin;
+ int childMargins = (numVisibleChildren - 1) * mChildContainerMargin;
int height = getMeasuredHeight() + extraVerticalSpace + childMargins;
int width = getMeasuredWidth() + getPaddingLeft() + getPaddingRight();
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 3f75ecc..9cca29a 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -95,6 +95,8 @@
private static final int SHORTCUT_COLLAPSE_THRESHOLD = 6;
+ private final float mShortcutHeight;
+
private BubbleTextView mOriginalIcon;
private int mNumNotifications;
private NotificationContainer mNotificationContainer;
@@ -112,6 +114,7 @@
mStartDragThreshold = getResources().getDimensionPixelSize(
R.dimen.deep_shortcuts_start_drag_threshold);
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
+ mShortcutHeight = getResources().getDimension(R.dimen.system_shortcut_header_height);
}
public PopupContainerWithArrow(Context context, AttributeSet attrs) {
@@ -387,16 +390,18 @@
*/
private void addAllShortcutsMaterialU(int deepShortcutCount,
List<SystemShortcut> systemShortcuts) {
-
if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
// add all system shortcuts including widgets shortcut to same container
addSystemShortcutsMaterialU(systemShortcuts,
R.layout.system_shortcut_rows_container_material_u,
R.layout.system_shortcut);
- addDeepShortcutsMaterialU(deepShortcutCount);
+ float currentHeight = (mShortcutHeight * systemShortcuts.size())
+ + mChildContainerMargin;
+ addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
return;
}
+ float currentHeight = mShortcutHeight + mChildContainerMargin;
List<SystemShortcut> nonWidgetSystemShortcuts =
getNonWidgetSystemShortcuts(systemShortcuts);
// If total shortcuts over threshold, collapse system shortcuts to single row
@@ -411,8 +416,9 @@
mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container_material_u,
this);
initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
+ currentHeight += mShortcutHeight + mChildContainerMargin;
}
- addDeepShortcutsMaterialU(deepShortcutCount);
+ addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
}
/**
@@ -497,10 +503,14 @@
/**
* Inflates and adds [deepShortcutCount] number of DeepShortcutView for the to a new container
* @param deepShortcutCount number of DeepShortcutView instances to add
+ * @param currentHeight height of popup before adding deep shortcuts
*/
- private void addDeepShortcutsMaterialU(int deepShortcutCount) {
+ private void addDeepShortcutsMaterialU(int deepShortcutCount, float currentHeight) {
mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this);
for (int i = deepShortcutCount; i > 0; i--) {
+ currentHeight += mShortcutHeight;
+ // when there is limited vertical screen space, limit total popup rows to fit
+ if (currentHeight >= mActivityContext.getDeviceProfile().availableHeightPx) break;
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut_material_u,
mDeepShortcutContainer);
v.getLayoutParams().width = mContainerWidth;
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 6450c8e..c4eb14f 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -44,10 +44,10 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.LauncherProvider.DatabaseHelper;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.DeviceGridState;
import com.android.launcher3.model.GridBackupTable;
import com.android.launcher3.model.data.AppInfo;
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index f295204..1e3be27 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -40,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -65,6 +66,7 @@
* @param context
* @return String
*/
+ @WorkerThread
@Nullable
public static String getSearchWidgetPackageName(@NonNull Context context) {
String providerPkg = Settings.Global.getString(context.getContentResolver(),
@@ -84,6 +86,7 @@
* @param context
* @return AppWidgetProviderInfo
*/
+ @WorkerThread
@Nullable
public static AppWidgetProviderInfo getSearchWidgetProviderInfo(@NonNull Context context) {
String providerPkg = getSearchWidgetPackageName(context);
@@ -110,6 +113,7 @@
/**
* returns componentName for searchWidget if package name is known.
*/
+ @WorkerThread
@Nullable
public static ComponentName getSearchComponentName(@NonNull Context context) {
AppWidgetProviderInfo providerInfo =
@@ -317,6 +321,7 @@
* If widgetCategory is not supported, or no such widget is found, returns the first widget
* provided by the package.
*/
+ @WorkerThread
protected AppWidgetProviderInfo getSearchWidgetProvider() {
return getSearchWidgetProviderInfo(getContext());
}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index c146216..6573691 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -41,7 +41,6 @@
public static final String SEARCH_KEYBOARD_EDU_SEEN = "launcher.search_edu_seen";
public static final String SEARCH_SNACKBAR_COUNT = "launcher.keyboard_snackbar_count";
public static final String SEARCH_ONBOARDING_COUNT = "launcher.search_onboarding_count";
- public static final String TASKBAR_EDU_SEEN = "launcher.taskbar_edu_seen2";
public static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
public static final String QSB_SEARCH_ONBOARDING_CARD_DISMISSED = "launcher.qsb_edu_dismiss";
public static final String TASKBAR_EDU_TOOLTIP_STEP = "launcher.taskbar_edu_tooltip_step";
@@ -52,7 +51,7 @@
HOTSEAT_LONGPRESS_TIP_SEEN },
"Search Education", new String[] { SEARCH_KEYBOARD_EDU_SEEN, SEARCH_SNACKBAR_COUNT,
SEARCH_ONBOARDING_COUNT, QSB_SEARCH_ONBOARDING_CARD_DISMISSED},
- "Taskbar Education", new String[] { TASKBAR_EDU_SEEN, TASKBAR_EDU_TOOLTIP_STEP },
+ "Taskbar Education", new String[] { TASKBAR_EDU_TOOLTIP_STEP },
"All Apps Visited Count", new String[] {ALL_APPS_VISITED_COUNT}
);
@@ -63,7 +62,6 @@
HOME_BOUNCE_SEEN,
HOTSEAT_LONGPRESS_TIP_SEEN,
SEARCH_KEYBOARD_EDU_SEEN,
- TASKBAR_EDU_SEEN,
QSB_SEARCH_ONBOARDING_CARD_DISMISSED
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 5526839..a5c663f 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -32,10 +32,13 @@
import android.util.SparseArray;
import android.util.TypedValue;
+import androidx.annotation.ColorInt;
+
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.GraphicsUtils;
+import com.android.launcher3.views.ActivityContext;
/**
* Various utility methods associated with theming.
@@ -198,4 +201,12 @@
return result;
}
+
+ /** Returns the desired navigation bar scrim color depending on the {@code DeviceProfile}. */
+ @ColorInt
+ public static <T extends Context & ActivityContext> int getNavBarScrimColor(T context) {
+ return context.getDeviceProfile().isTaskbarPresent
+ ? context.getColor(R.color.taskbar_background)
+ : Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor);
+ }
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 07c6ba4..c3f26fa 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -37,6 +37,7 @@
import androidx.core.view.ViewCompat;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Insettable;
@@ -60,7 +61,7 @@
*/
public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
implements OnClickListener, OnLongClickListener, DragSource,
- PopupDataProvider.PopupDataChangeListener, Insettable {
+ PopupDataProvider.PopupDataChangeListener, Insettable, OnDeviceProfileChangeListener {
/** The default number of cells that can fit horizontally in a widget sheet. */
public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
@@ -84,7 +85,7 @@
mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
R.dimen.widget_cell_horizontal_padding);
mNavBarScrimPaint = new Paint();
- mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+ mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
}
protected int getScrimColor(Context context) {
@@ -98,12 +99,23 @@
.normalizeWindowInsets(getContext(), getRootWindowInsets(), new Rect());
mNavBarScrimHeight = getNavBarScrimHeight(windowInsets);
mActivityContext.getPopupDataProvider().setChangeListener(this);
+ mActivityContext.addOnDeviceProfileChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mActivityContext.getPopupDataProvider().setChangeListener(null);
+ mActivityContext.removeOnDeviceProfileChangeListener(this);
+ }
+
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ int navBarScrimColor = Themes.getNavBarScrimColor(mActivityContext);
+ if (mNavBarScrimPaint.getColor() != navBarScrimColor) {
+ mNavBarScrimPaint.setColor(navBarScrimColor);
+ invalidate();
+ }
}
@Override
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 9984991..80bc1a7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -16,7 +16,6 @@
package com.android.launcher3.widget;
-import static android.view.View.MeasureSpec.getSize;
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -119,8 +118,6 @@
private TextView mWidgetName;
private TextView mWidgetDims;
private TextView mWidgetDescription;
- private Consumer<Bitmap> mCallback;
- private @Nullable Bitmap mCachedPreview;
protected WidgetItem mItem;
@@ -432,8 +429,6 @@
*/
private void ensurePreviewWithCallback(Consumer<Bitmap> callback,
@Nullable Bitmap cachedPreview) {
- mCallback = callback;
- mCachedPreview = cachedPreview;
if (mAppWidgetHostViewPreview != null) {
int containerWidth = (int) (mTargetPreviewWidth * mPreviewContainerScale);
int containerHeight = (int) (mTargetPreviewHeight * mPreviewContainerScale);
@@ -474,7 +469,6 @@
INDEX_WIDGET_CENTERING,
-(params.width - (params.width * mPreviewContainerScale)) / 2.0f,
-(params.height - (params.height * mPreviewContainerScale)) / 2.0f);
- mWidgetImageContainer.removeAllViews();
mWidgetImageContainer.addView(mAppWidgetHostViewPreview, /* index= */ 0);
mWidgetImage.setVisibility(View.GONE);
applyPreview(null);
@@ -585,19 +579,4 @@
(mTargetPreviewHeight - verticalPadding) * mPreviewContainerScale
/ appWidgetContentHeight);
}
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int padding = getPaddingLeft() + getPaddingRight();
- int allowedWidth = getSize(widthMeasureSpec) - padding;
-
- // Here we prevent having clipped widgets when they're too large as the preview width is
- // larger than the max allowed width. We then re-do the preview with the new preview width
- if (allowedWidth > 0 && mCachedPreview == null && allowedWidth < mTargetPreviewWidth) {
- mTargetPreviewWidth = allowedWidth;
- ensurePreviewWithCallback(mCallback, null);
- }
-
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
}
diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
index d849c8f..8a092bf 100644
--- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
+++ b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
@@ -37,8 +37,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherProvider.DatabaseHelper;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
@@ -74,7 +72,7 @@
mSchemaFile.delete();
assertFalse(mSchemaFile.exists());
DbDowngradeHelper.updateSchemaFile(mSchemaFile, 0, mContext);
- assertEquals(LauncherProvider.SCHEMA_VERSION, DbDowngradeHelper.parse(mSchemaFile).version);
+ assertEquals(DatabaseHelper.SCHEMA_VERSION, DbDowngradeHelper.parse(mSchemaFile).version);
}
@Test
@@ -140,7 +138,7 @@
@Override
public void onOpen(SQLiteDatabase db) { }
};
- assertEquals(LauncherProvider.SCHEMA_VERSION, helper.getWritableDatabase().getVersion());
+ assertEquals(DatabaseHelper.SCHEMA_VERSION, helper.getWritableDatabase().getVersion());
try (Cursor c = helper.getWritableDatabase().query(Favorites.TABLE_NAME,
null, null, null, null, null, null)) {
@@ -165,7 +163,7 @@
mSchemaFile.delete();
mDbFile.delete();
- DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext);
+ DbDowngradeHelper.updateSchemaFile(mSchemaFile, DatabaseHelper.SCHEMA_VERSION, mContext);
DatabaseHelper dbHelper = new DatabaseHelper(mContext, DB_FILE, false) {
@Override
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 9c8de1c..aa091b6 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -26,8 +26,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.LauncherProvider.DatabaseHelper;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.DatabaseHelper;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 4f6cc64..cefba16 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -106,6 +106,8 @@
private static boolean sDumpWasGenerated = false;
private static boolean sActivityLeakReported = false;
+ private static boolean sSeenKeygard = false;
+
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
protected LooperExecutor mMainThreadExecutor = MAIN_EXECUTOR;
@@ -237,9 +239,13 @@
@Before
public void setUp() throws Exception {
mLauncher.onTestStart();
- Assert.assertTrue("Keyguard is visible, which is likely caused by a crash in SysUI",
- TestHelpers.wait(
- Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000));
+
+ sSeenKeygard = sSeenKeygard
+ || !TestHelpers.wait(
+ Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000);
+
+ Assert.assertFalse("Keyguard is visible, which is likely caused by a crash in SysUI",
+ sSeenKeygard);
final String launcherPackageName = mDevice.getLauncherPackageName();
try {
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index f30538d..217bec3 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -51,7 +51,6 @@
import com.android.launcher3.tapl.FolderIcon;
import com.android.launcher3.tapl.HomeAllApps;
import com.android.launcher3.tapl.HomeAppIcon;
-import com.android.launcher3.tapl.HomeAppIconMenu;
import com.android.launcher3.tapl.HomeAppIconMenuItem;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
@@ -391,23 +390,14 @@
.switchToAllApps();
allApps.freeze();
try {
- final HomeAppIconMenu menu = allApps
+ final HomeAppIconMenuItem menuItem = allApps
.getAppIcon(APP_NAME)
- .openDeepShortcutMenu();
- final HomeAppIconMenuItem menuItem0 = menu.getMenuItem(0);
- final HomeAppIconMenuItem menuItem2 = menu.getMenuItem(2);
+ .openDeepShortcutMenu()
+ .getMenuItem(0);
+ final String actualShortcutName = menuItem.getText();
+ final String expectedShortcutName = "Shortcut 1";
- final HomeAppIconMenuItem menuItem;
-
- final String expectedShortcutName = "Shortcut 3";
- if (menuItem0.getText().equals(expectedShortcutName)) {
- menuItem = menuItem0;
- } else {
- final String shortcutName2 = menuItem2.getText();
- assertEquals("Wrong menu item", expectedShortcutName, shortcutName2);
- menuItem = menuItem2;
- }
-
+ assertEquals(expectedShortcutName, actualShortcutName);
menuItem.dragToWorkspace(false, false);
mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName)
.launch(getAppPackageName());
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 545b645..fdfeb7d 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -61,6 +61,7 @@
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;