Merge "Import translations. DO NOT MERGE ANYWHERE" into udc-dev
diff --git a/quickstep/res/color-night/quick_switch_view_background.xml b/quickstep/res/color-night/quick_switch_view_background.xml
new file mode 100644
index 0000000..7280918
--- /dev/null
+++ b/quickstep/res/color-night/quick_switch_view_background.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:color="@android:color/system_neutral2_500"
+ android:lStar="80"/>
+</selector>
diff --git a/quickstep/res/color/all_set_bg_primary.xml b/quickstep/res/color/all_set_bg_primary.xml
new file mode 100644
index 0000000..4cf857d
--- /dev/null
+++ b/quickstep/res/color/all_set_bg_primary.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/materialColorPrimaryContainer"/>
+</selector>
diff --git a/quickstep/res/color/all_set_bg_tertiary.xml b/quickstep/res/color/all_set_bg_tertiary.xml
new file mode 100644
index 0000000..e62b094
--- /dev/null
+++ b/quickstep/res/color/all_set_bg_tertiary.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/materialColorTertiary"/>
+</selector>
diff --git a/quickstep/res/color/quick_switch_view_background.xml b/quickstep/res/color/quick_switch_view_background.xml
new file mode 100644
index 0000000..0eb2a6b
--- /dev/null
+++ b/quickstep/res/color/quick_switch_view_background.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:color="@android:color/system_neutral2_500"
+ android:lStar="35"/>
+</selector>
diff --git a/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml
index 15843af..2a4f087 100644
--- a/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml
+++ b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml
@@ -17,6 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
- <solid android:color="?androidprv:attr/materialColorSurfaceContainerHigh" />
+ <solid android:color="?androidprv:attr/materialColorSurfaceBright" />
<corners android:radius="@dimen/keyboard_quick_switch_task_view_radius" />
</shape>
diff --git a/quickstep/res/drawable/keyboard_quick_switch_view_background.xml b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml
index 19aaed4..573c93a 100644
--- a/quickstep/res/drawable/keyboard_quick_switch_view_background.xml
+++ b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml
@@ -16,6 +16,6 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="?attr/overviewScrimColor" />
+ <solid android:color="@color/quick_switch_view_background" />
<corners android:radius="@dimen/keyboard_quick_switch_view_radius" />
</shape>
diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
index 174a704..ebcbdcd 100644
--- a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<include
layout="@layout/keyboard_quick_switch_thumbnail"
diff --git a/quickstep/res/layout/bubble_view.xml b/quickstep/res/layout/bubble_view.xml
new file mode 100644
index 0000000..0b1ed9f
--- /dev/null
+++ b/quickstep/res/layout/bubble_view.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <ImageView
+ android:id="@+id/icon_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@null" />
+
+ <!--
+ Icon badge size is defined in Launcher3 BaseIconFactory as 0.444 of icon size.
+ Constraint guide starts from left, which means for a badge positioned on the right,
+ percent has to be 1 - 0.444 to have the same effect.
+ -->
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/app_icon_constraint_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ app:layout_constraintGuide_percent="0.556" />
+
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/app_icon_constraint_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintGuide_percent="0.556" />
+
+ <ImageView
+ android:id="@+id/app_icon_view"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@null"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="@id/app_icon_constraint_vertical"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="@id/app_icon_constraint_horizontal" />
+
+</merge>
\ No newline at end of file
diff --git a/quickstep/res/layout/bubblebar_item_view.xml b/quickstep/res/layout/bubblebar_item_view.xml
new file mode 100644
index 0000000..64fc4df
--- /dev/null
+++ b/quickstep/res/layout/bubblebar_item_view.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<com.android.launcher3.taskbar.bubbles.BubbleView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/bubble_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_overview.xml
index 7b34710..8c97c68 100644
--- a/quickstep/res/layout/keyboard_quick_switch_overview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_overview.xml
@@ -23,7 +23,7 @@
android:background="@drawable/keyboard_quick_switch_overview_button_background"
android:clipToOutline="true"
android:importantForAccessibility="yes"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<ImageView
android:id="@+id/icon"
@@ -32,7 +32,7 @@
android:layout_marginBottom="8dp"
android:src="@drawable/ic_empty_recents"
- app:tint="?android:attr/textColorPrimary"
+ app:tint="?androidprv:attr/materialColorOnSurface"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/text"
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
index 15b12dc..5e2d52a 100644
--- a/quickstep/res/layout/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<include
layout="@layout/keyboard_quick_switch_thumbnail"
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index faafec7..e981730 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -24,7 +24,7 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index ccd2592..fd82c66 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -25,7 +25,7 @@
android:clipToOutline="true"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<View
android:id="@+id/background"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index 66da6c5..65febba 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -29,7 +29,7 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorSecondaryContainer">
+ launcher:borderColor="?androidprv:attr/materialColorOutline">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/raw-land/all_set_page_bg.json b/quickstep/res/raw-land/all_set_page_bg.json
new file mode 100644
index 0000000..9e94c47
--- /dev/null
+++ b/quickstep/res/raw-land/all_set_page_bg.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":796,"h":412,"nm":"SUW_Welcome_Handheld_Landscape_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-55]},{"t":180,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.942},"o":{"x":0.167,"y":0.167},"t":0,"s":[700.266,85.857,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.043},"t":95,"s":[700.266,-103.727,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[700.266,85.857,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[-18.2,18.2,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[10.989],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[10.989],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.047]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-56]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.773],"y":[-0.035]},"t":95,"s":[-67]},{"t":180,"s":[-56]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.073]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[319.023]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.773],"y":[-0.054]},"t":95,"s":[388.573]},{"t":180,"s":[319.023]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.927]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[565.531]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.773],"y":[0.054]},"t":95,"s":[482.331]},{"t":180,"s":[565.531]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[65,65,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1193.125,1815.766],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"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":[398,206,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":[2472,5352],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.125489994124,0.1294119891,0.141176006841,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"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,0,0,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":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw-sw600dp-land/all_set_page_bg.json b/quickstep/res/raw-sw600dp-land/all_set_page_bg.json
index f53128c..63b64da 100644
--- a/quickstep/res/raw-sw600dp-land/all_set_page_bg.json
+++ b/quickstep/res/raw-sw600dp-land/all_set_page_bg.json
@@ -1 +1 @@
-{"v":"5.8.1","fr":60,"ip":0,"op":180,"w":1280,"h":800,"nm":"3Second_MainWelcomeScreen_Tablet_Landscape_V02","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[288,540,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[25,25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"F4BA9E","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[375.832,-1006.545,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":95,"s":[375.832,-1811,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[375.832,-1006.545,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[110,110,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.956862745098,0.729411764706,0.619607843137,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"C0C9C0","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[57]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":95,"s":[75]},{"t":180,"s":[57]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[2618]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":95,"s":[2442]},{"t":180,"s":[2618]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[891]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":95,"s":[694]},{"t":180,"s":[891]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.752941176471,0.788235294118,0.752941176471,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
+{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":841,"h":701,"nm":"SUW_WelcomeScreen_FoldableOpen_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.939},"o":{"x":0.167,"y":0.167},"t":0,"s":[140.975,228.318,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.045},"t":95,"s":[140.975,47.65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[140.975,228.318,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[18,18,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[11.111],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[11.111],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.913]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[639]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.06]},"t":95,"s":[704]},{"t":180,"s":[639]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.12]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[527.25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.083]},"t":95,"s":[471]},{"t":180,"s":[527.25]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-25,25,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[6],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[6],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"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":[420.5,350.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":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw-sw600dp/all_set_page_bg.json b/quickstep/res/raw-sw600dp/all_set_page_bg.json
index b2dd530..f2998a0 100644
--- a/quickstep/res/raw-sw600dp/all_set_page_bg.json
+++ b/quickstep/res/raw-sw600dp/all_set_page_bg.json
@@ -1 +1 @@
-{"v":"5.8.1","fr":60,"ip":0,"op":180,"w":800,"h":1280,"nm":"3Second_MainWelcomeScreen_Tablet_Portrait_V02","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[288,528,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[25,25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"F4BA9E","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[999.832,-2238.545,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":95,"s":[999.832,-3043,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[999.832,-2238.545,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[200,200,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.956862745098,0.729411764706,0.619607843137,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"C0C9C0","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-39]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":95,"s":[-21]},{"t":180,"s":[-39]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1490]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":95,"s":[1314]},{"t":180,"s":[1490]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[2967]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":95,"s":[2770]},{"t":180,"s":[2967]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[168,168,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.752941176471,0.788235294118,0.752941176471,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
+{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":701,"h":841,"nm":"SUW_WelcomeScreen_FoldableOpen_Portrait_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.949},"o":{"x":0.167,"y":0.167},"t":0,"s":[181.172,148.425,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.038},"t":95,"s":[181.172,-68.377,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[181.172,148.425,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[21.6,21.6,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":9.3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.927]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[458.803]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.05]},"t":95,"s":[536.803]},{"t":180,"s":[458.803]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[707.143]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.069]},"t":95,"s":[639.643]},{"t":180,"s":[707.143]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-30,30,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[350.5,420.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":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw-sw720dp-land/all_set_page_bg.json b/quickstep/res/raw-sw720dp-land/all_set_page_bg.json
new file mode 100644
index 0000000..a994b0f
--- /dev/null
+++ b/quickstep/res/raw-sw720dp-land/all_set_page_bg.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":180,"w":1280,"h":800,"nm":"SUW_WelcomeScreen_Tablet_Landscape_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[288,540,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[25,25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary","cl":"primary","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[375.832,-1006.545,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":95,"s":[375.832,-1811,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[375.832,-1006.545,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[110,110,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.956862745098,0.729411764706,0.619607843137,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".tertiary","cl":"tertiary","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[57]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":95,"s":[75]},{"t":180,"s":[57]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[2618]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":95,"s":[2442]},{"t":180,"s":[2618]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[891]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":95,"s":[694]},{"t":180,"s":[891]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.752941176471,0.788235294118,0.752941176471,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw-sw720dp/all_set_page_bg.json b/quickstep/res/raw-sw720dp/all_set_page_bg.json
new file mode 100644
index 0000000..1030ffa
--- /dev/null
+++ b/quickstep/res/raw-sw720dp/all_set_page_bg.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":180,"w":800,"h":1280,"nm":"SUW_WelcomeScreen_Tablet_Portrait_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[288,528,0],"ix":2,"l":2},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[25,25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary","cl":"primary","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[999.832,-2238.545,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":95,"s":[999.832,-3043,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[999.832,-2238.545,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[200,200,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.956862745098,0.729411764706,0.619607843137,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".tertiary","cl":"tertiary","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-39]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":95,"s":[-21]},{"t":180,"s":[-39]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1490]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":95,"s":[1314]},{"t":180,"s":[1490]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[2967]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":95,"s":[2770]},{"t":180,"s":[2967]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[168,168,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.752941176471,0.788235294118,0.752941176471,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/raw/all_set_page_bg.json b/quickstep/res/raw/all_set_page_bg.json
index 859d356..4ae179d 100644
--- a/quickstep/res/raw/all_set_page_bg.json
+++ b/quickstep/res/raw/all_set_page_bg.json
@@ -1 +1 @@
-{"v":"5.7.8","fr":24,"ip":0,"op":72,"w":2472,"h":5352,"nm":"3Second_MAIN_Welcome","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 60","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1508,1364,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,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"PinkFlower","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":72,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[1505.832,1379.455,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":38,"s":[1505.832,575,0],"to":[0,0,0],"ti":[0,0,0]},{"t":72,"s":[1505.832,1379.455,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,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":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.839215686275,0.439215686275,0.388235294118,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":[0.839215746113,0.439215716194,0.388235324037,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":true},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":288,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse_Bottom","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-56]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":38,"s":[-38]},{"t":72,"s":[-56]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1720]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":38,"s":[1544]},{"t":72,"s":[1720]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[4069]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":38,"s":[3872]},{"t":72,"s":[4069]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.305882352941,0.309803921569,0.321568627451,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":[0.882353001015,0.894118006089,0.886274988511,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":true},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
+{"v":"5.8.1","fr":24,"ip":0,"op":72,"w":2472,"h":5352,"nm":"SUW_Welcome_Handheld_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 60","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1508,1364,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,"ip":0,"op":240,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":72,"s":[56]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.986},"o":{"x":0.167,"y":0.167},"t":0,"s":[1505.832,1379.455,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.01},"t":38,"s":[1505.832,575,0],"to":[0,0,0],"ti":[0,0,0]},{"t":72,"s":[1505.832,1379.455,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,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":[[75.615,-96.908],[89.338,-70.276],[111.99,-50.668],[111.764,-20.709],[122.709,7.18],[108.586,33.602],[105.316,63.383],[80.533,80.216],[63.797,105.066],[34.03,108.453],[7.663,122.679],[-20.269,111.845],[-50.226,112.189],[-69.924,89.614],[-96.61,75.997],[-103.56,46.854],[-120.861,22.395],[-113.472,-6.639],[-117.425,-36.337],[-97.389,-58.612],[-87.087,-86.745],[-58.996,-97.158],[-36.8,-117.281],[-7.086,-113.445],[21.918,-120.948],[46.446,-103.744]],"o":[[-75.615,96.909],[-89.338,70.276],[-111.99,50.668],[-111.764,20.709],[-122.709,-7.18],[-108.586,-33.602],[-105.316,-63.383],[-80.533,-80.216],[-63.797,-105.066],[-34.03,-108.453],[-7.663,-122.679],[20.269,-111.845],[50.226,-112.188],[69.924,-89.614],[96.61,-75.997],[103.56,-46.854],[120.861,-22.395],[113.472,6.64],[117.425,36.337],[97.389,58.612],[87.088,86.745],[58.995,97.158],[36.8,117.281],[7.087,113.445],[-21.918,120.948],[-46.446,103.744]],"v":[[733.209,572.105],[531.711,675.932],[383.354,847.313],[156.685,845.606],[-54.323,928.412],[-254.235,821.562],[-479.555,796.823],[-606.913,609.309],[-794.927,482.691],[-820.554,257.47],[-928.191,57.981],[-846.217,-153.353],[-848.817,-380.013],[-678.021,-529.044],[-574.99,-730.949],[-354.499,-783.537],[-169.439,-914.435],[50.234,-858.532],[274.928,-888.434],[443.46,-736.847],[656.313,-658.903],[735.094,-446.359],[887.344,-278.426],[858.327,-53.616],[915.095,165.835],[784.928,351.409]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.839215686275,0.439215686275,0.388235294118,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":"tr","p":{"a":0,"k":[-3509.952,-363.731],"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":"Polystar 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":288,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.248]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-56]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.172]},"t":38,"s":[-38]},{"t":72,"s":[-56]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.032]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1720]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.022]},"t":38,"s":[1544]},{"t":72,"s":[1720]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.034]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[4069]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.024]},"t":38,"s":[3872]},{"t":72,"s":[4069]}],"ix":4}},"a":{"a":0,"k":[164.438,1433.781,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3079.125,4685.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.305882352941,0.309803921569,0.321568627451,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":"tr","p":{"a":0,"k":[164.438,1481.781],"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":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":240,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 3df5d57..cdb3b1c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -344,6 +344,19 @@
<!-- Recents overview -->
<dimen name="recents_filter_icon_size">30dp</dimen>
+ <!-- Bubble bar -->
+ <dimen name="bubblebar_size">72dp</dimen>
+ <dimen name="bubblebar_stashed_handle_width">55dp</dimen>
+ <dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
+ <dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
+ <dimen name="bubblebar_pointer_size">8dp</dimen>
+
+ <dimen name="bubblebar_icon_size">50dp</dimen>
+ <dimen name="bubblebar_badge_size">24dp</dimen>
+ <dimen name="bubblebar_icon_overlap">12dp</dimen>
+ <dimen name="bubblebar_icon_spacing">3dp</dimen>
+ <dimen name="bubblebar_icon_elevation">1dp</dimen>
+
<!-- Launcher splash screen -->
<!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
<!-- starting_surface_exit_animation_window_shift_length -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index f9f2175..6c12f11 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -14,7 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearance.GestureTutorial"
parent="android:TextAppearance.Material.Body1" />
@@ -217,7 +218,7 @@
<style name="KeyboardQuickSwitchOverview">
<item name="fontFamily">google-sans-text</item>
<item name="android:textSize">14sp</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
<item name="lineHeight">20sp</item>
</style>
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index a713ff5..9a9e0ba 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -714,6 +714,8 @@
* setup wizard, or normal 3 button nav.
*/
private void updateButtonLayoutSpacing() {
+ boolean isThreeButtonNav = mContext.isThreeButtonNav();
+
DeviceProfile dp = mContext.getDeviceProfile();
Resources res = mContext.getResources();
boolean isInSetup = !mContext.isUserSetupComplete();
@@ -721,7 +723,9 @@
boolean isInKidsMode = mContext.isNavBarKidsModeActive();
if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) {
- boolean isThreeButtonNav = mContext.isThreeButtonNav();
+ if (!isThreeButtonNav) {
+ return;
+ }
NavButtonLayoutter navButtonLayoutter =
NavButtonLayoutFactory.Companion.getUiLayoutter(
@@ -803,7 +807,7 @@
mNavButtonContainer.requestLayout();
mHomeButton.setOnLongClickListener(null);
- } else if (mContext.isThreeButtonNav()) {
+ } else if (isThreeButtonNav) {
final RotateDrawable rotateDrawable = new RotateDrawable();
rotateDrawable.setDrawable(mContext.getDrawable(R.drawable.ic_sysbar_back));
rotateDrawable.setFromDegrees(0f);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index c48d062..fe1c9d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -186,7 +186,8 @@
mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
// Inflate views.
- int taskbarLayout = DisplayController.isTransientTaskbar(this)
+ boolean phoneMode = TaskbarManager.isPhoneMode(mDeviceProfile);
+ int taskbarLayout = DisplayController.isTransientTaskbar(this) && !phoneMode
? R.layout.transient_taskbar
: R.layout.taskbar;
mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(taskbarLayout, null, false);
@@ -254,6 +255,12 @@
sharedState.systemBarAttrsBehavior);
onNavButtonsDarkIntensityChanged(sharedState.navButtonsDarkIntensity);
+ if (FLAG_HIDE_NAVBAR_WINDOW) {
+ // W/ the flag not set this entire class gets re-created, which resets the value of
+ // mIsDestroyed. We re-use the class for small-screen, so we explicitly have to mark
+ // this class as non-destroyed
+ mIsDestroyed = false;
+ }
if (!mAddedWindow) {
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
@@ -334,7 +341,7 @@
public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type, String title) {
DeviceProfile deviceProfile = getDeviceProfile();
// Taskbar is on the logical bottom of the screen
- boolean isVerticalBarLayout = TaskbarManager.isPhoneMode(deviceProfile) &&
+ boolean isVerticalBarLayout = TaskbarManager.isPhoneButtonNavMode(this) &&
deviceProfile.isLandscape;
int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index 07cea01..fe365f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -16,11 +16,13 @@
package com.android.launcher3.taskbar
+import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
+import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.Utilities.mapRange
@@ -61,7 +63,7 @@
private val invertedLeftCornerPath: Path = Path()
private val invertedRightCornerPath: Path = Path()
- private val stashedHandleWidth =
+ private var stashedHandleWidth =
context.resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width)
private val stashedHandleHeight =
@@ -86,6 +88,13 @@
setCornerRoundness(DEFAULT_ROUNDNESS)
}
+ fun updateStashedHandleWidth(dp: DeviceProfile, res: Resources) {
+ stashedHandleWidth = res.getDimensionPixelSize(
+ if (TaskbarManager.isPhoneMode(dp)) R.dimen.taskbar_stashed_small_screen
+ else R.dimen.taskbar_stashed_handle_width
+ )
+ }
+
/**
* Sets the roundness of the round corner above Taskbar. No effect on transient Taskkbar.
*
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index c53460d..7681fe0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -71,7 +71,7 @@
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
mControllerCallbacks = callbacks;
-
+ mBackgroundRenderer.updateStashedHandleWidth(mActivity.getDeviceProfile(), getResources());
recreateControllers();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 4373a88..2c686b8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.taskbar
-import android.graphics.PorterDuff.Mode.SRC_ATOP
-import android.graphics.PorterDuffColorFilter
import android.os.Bundle
import android.view.View
import android.view.View.GONE
@@ -27,14 +25,13 @@
import androidx.annotation.IntDef
import androidx.annotation.LayoutRes
import com.airbnb.lottie.LottieAnimationView
-import com.airbnb.lottie.LottieProperty.COLOR_FILTER
-import com.airbnb.lottie.model.KeyPath
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
+import com.android.quickstep.util.LottieAnimationColorUtils
import java.io.PrintWriter
/** First EDU step for swiping up to show transient Taskbar. */
@@ -239,11 +236,5 @@
return
}
- addLottieOnCompositionLoadedListener {
- DARK_TO_LIGHT_COLORS.forEach { (key, color) ->
- addValueCallback(KeyPath("**", key, "**"), COLOR_FILTER) {
- PorterDuffColorFilter(context.getColor(color), SRC_ATOP)
- }
- }
- }
+ LottieAnimationColorUtils.updateColors(this, DARK_TO_LIGHT_COLORS, context.theme)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 90fcd37..5abeac7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -137,6 +137,7 @@
if (folder != null) {
folder.iterateOverItems(op);
}
+ mControllers.taskbarAllAppsController.updateNotificationDots(updatedDots);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index a3e6814..6034739 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -114,7 +114,8 @@
mActivityContext = ActivityContext.lookupContext(context);
mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
Resources resources = getResources();
- boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext);
+ boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext)
+ && !TaskbarManager.isPhoneMode(mActivityContext.getDeviceProfile());
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = mContext.getResources().getDimension(
R.dimen.transient_taskbar_min_width);
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 4a95a8f..0c9dc5b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -24,8 +24,10 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.util.PackageUserKey;
import java.util.List;
+import java.util.function.Predicate;
/**
* Handles the all apps overlay window initialization, updates, and its data.
@@ -91,6 +93,13 @@
}
}
+ /** Updates the current notification dots. */
+ public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
+ if (mAppsView != null) {
+ mAppsView.getAppsStore().updateNotificationDots(updatedDots);
+ }
+ }
+
/** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
public void show() {
show(true);
@@ -135,7 +144,6 @@
overlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
}
-
@VisibleForTesting
public int getTaskbarAllAppsTopPadding() {
// Allow null-pointer since this should only be null if the apps view is not showing.
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
new file mode 100644
index 0000000..667c6f5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
@@ -0,0 +1,134 @@
+/*
+ * 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.taskbar.bubbles
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.ColorFilter
+import android.graphics.Paint
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.ShapeDrawable
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.Utilities.mapToRange
+import com.android.launcher3.anim.Interpolators
+import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
+import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.wm.shell.common.TriangleShape
+
+/** Drawable for the background of the bubble bar. */
+class BubbleBarBackground(context: TaskbarActivityContext, private val backgroundHeight: Float) :
+ Drawable() {
+
+ private val DARK_THEME_SHADOW_ALPHA = 51f
+ private val LIGHT_THEME_SHADOW_ALPHA = 25f
+
+ private val paint: Paint = Paint()
+ private val pointerSize: Float
+
+ private val shadowAlpha: Float
+ private var shadowBlur = 0f
+ private var keyShadowDistance = 0f
+
+ private var arrowPositionX: Float = 0f
+ private var showingArrow: Boolean = false
+ private var arrowDrawable: ShapeDrawable
+
+ init {
+ paint.color = context.getColor(R.color.taskbar_background)
+ paint.flags = Paint.ANTI_ALIAS_FLAG
+ paint.style = Paint.Style.FILL
+
+ val res = context.resources
+ shadowBlur = res.getDimension(R.dimen.transient_taskbar_shadow_blur)
+ keyShadowDistance = res.getDimension(R.dimen.transient_taskbar_key_shadow_distance)
+ pointerSize = res.getDimension(R.dimen.bubblebar_pointer_size)
+
+ shadowAlpha =
+ if (Utilities.isDarkTheme(context)) DARK_THEME_SHADOW_ALPHA
+ else LIGHT_THEME_SHADOW_ALPHA
+
+ arrowDrawable =
+ ShapeDrawable(TriangleShape.create(pointerSize, pointerSize, /* pointUp= */ true))
+ arrowDrawable.setBounds(0, 0, pointerSize.toInt(), pointerSize.toInt())
+ arrowDrawable.paint.flags = Paint.ANTI_ALIAS_FLAG
+ arrowDrawable.paint.style = Paint.Style.FILL
+ arrowDrawable.paint.color = context.getColor(R.color.taskbar_background)
+ }
+
+ fun showArrow(show: Boolean) {
+ showingArrow = show
+ }
+
+ fun setArrowPosition(x: Float) {
+ arrowPositionX = x
+ }
+
+ /** Draws the background with the given paint and height, on the provided canvas. */
+ override fun draw(canvas: Canvas) {
+ canvas.save()
+
+ // TODO (b/277359345): Should animate the alpha similar to taskbar (see TaskbarDragLayer)
+ // Draw shadows.
+ val newShadowAlpha =
+ mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, shadowAlpha, Interpolators.LINEAR)
+ paint.setShadowLayer(
+ shadowBlur,
+ 0f,
+ keyShadowDistance,
+ setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha))
+ )
+ arrowDrawable.paint.setShadowLayer(
+ shadowBlur,
+ 0f,
+ keyShadowDistance,
+ setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha))
+ )
+
+ // Draw background.
+ val radius = backgroundHeight / 2f
+ canvas.drawRoundRect(
+ 0f,
+ 0f,
+ canvas.width.toFloat(),
+ canvas.height.toFloat(),
+ radius,
+ radius,
+ paint
+ )
+
+ if (showingArrow) {
+ // Draw arrow.
+ val transX = arrowPositionX - pointerSize / 2f
+ canvas.translate(transX, -pointerSize)
+ arrowDrawable.draw(canvas)
+ }
+
+ canvas.restore()
+ }
+
+ override fun getOpacity(): Int {
+ return paint.alpha
+ }
+
+ override fun setAlpha(alpha: Int) {
+ paint.alpha = alpha
+ }
+
+ override fun setColorFilter(colorFilter: ColorFilter?) {
+ paint.colorFilter = colorFilter
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
new file mode 100644
index 0000000..b1633e7
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.taskbar.bubbles
+
+import android.graphics.Bitmap
+import android.graphics.Path
+import com.android.wm.shell.common.bubbles.BubbleInfo
+
+/** Contains state info about a bubble in the bubble bar as well as presentation information. */
+data class BubbleBarBubble(
+ val info: BubbleInfo,
+ val view: BubbleView,
+ val badge: Bitmap,
+ val icon: Bitmap,
+ val dotColor: Int,
+ val dotPath: Path,
+ val appName: String
+) {
+
+ fun getKey(): String {
+ return info.key
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
new file mode 100644
index 0000000..07daf06
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -0,0 +1,304 @@
+/*
+ * 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.taskbar.bubbles;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.List;
+
+/**
+ * The view that holds all the bubble views. Modifying this view should happen through
+ * {@link BubbleBarViewController}. Updates to the bubbles themselves (adds, removes, updates,
+ * selection) should happen through BubbleBarController which is the source of truth
+ * for state information about the bubbles.
+ * <p>
+ * The bubble bar has a couple of visual states:
+ * - stashed as a handle
+ * - unstashed but collapsed, in this state the bar is showing but the bubbles are stacked within it
+ * - unstashed and expanded, in this state the bar is showing and the bubbles are shown in a row
+ * with one of the bubbles being selected. Additionally, WMShell will display the expanded bubble
+ * view above the bar.
+ * <p>
+ * The bubble bar has some behavior related to taskbar:
+ * - When taskbar is unstashed, bubble bar will also become unstashed (but in its "collapsed"
+ * state)
+ * - When taskbar is stashed, bubble bar will also become stashed (unless bubble bar is in its
+ * "expanded" state)
+ * - When bubble bar is in its "expanded" state, taskbar becomes stashed
+ * <p>
+ * If there are no bubbles, the bubble bar and bubble stashed handle are not shown. Additionally
+ * the bubble bar and stashed handle are not shown on lockscreen.
+ * <p>
+ * When taskbar is in persistent or 3 button nav mode, the bubble bar is not available, and instead
+ * the bubbles are shown fully by WMShell in their floating mode.
+ */
+public class BubbleBarView extends FrameLayout {
+
+ private static final String TAG = BubbleBarView.class.getSimpleName();
+
+ // TODO: (b/273594744) calculate the amount of space we have and base the max on that
+ // if it's smaller than 5.
+ private static final int MAX_BUBBLES = 5;
+
+ private final TaskbarActivityContext mActivityContext;
+ private final BubbleBarBackground mBubbleBarBackground;
+
+ // The current bounds of all the bubble bar.
+ private final Rect mBubbleBarBounds = new Rect();
+ // The amount the bubbles overlap when they are stacked in the bubble bar
+ private final float mIconOverlapAmount;
+ // The spacing between the bubbles when they are expanded in the bubble bar
+ private final float mIconSpacing;
+ // The size of a bubble in the bar
+ private final float mIconSize;
+ // The elevation of the bubbles within the bar
+ private final float mBubbleElevation;
+
+ // Whether the bar is expanded (i.e. the bubble activity is being displayed).
+ private boolean mIsBarExpanded = false;
+ // The currently selected bubble view.
+ private BubbleView mSelectedBubbleView;
+ // The click listener when the bubble bar is collapsed.
+ private View.OnClickListener mOnClickListener;
+
+ private final Rect mTempRect = new Rect();
+
+ // We don't reorder the bubbles when they are expanded as it could be jarring for the user
+ // this runnable will be populated with any reordering of the bubbles that should be applied
+ // once they are collapsed.
+ @Nullable
+ private Runnable mReorderRunnable;
+
+ public BubbleBarView(Context context) {
+ this(context, null);
+ }
+
+ public BubbleBarView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BubbleBarView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public BubbleBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mActivityContext = ActivityContext.lookupContext(context);
+
+ mIconOverlapAmount = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_overlap);
+ mIconSpacing = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
+ mIconSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
+ mBubbleElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_elevation);
+ setClipToPadding(false);
+
+ mBubbleBarBackground = new BubbleBarBackground(mActivityContext,
+ getResources().getDimensionPixelSize(R.dimen.bubblebar_size));
+ setBackgroundDrawable(mBubbleBarBackground);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mBubbleBarBounds.left = left;
+ mBubbleBarBounds.top = top;
+ mBubbleBarBounds.right = right;
+ mBubbleBarBounds.bottom = bottom;
+
+ // The bubble bar handle is aligned to the bottom edge of the screen so scale towards that.
+ setPivotX(getWidth());
+ setPivotY(getHeight());
+
+ // Position the views
+ updateChildrenRenderNodeProperties();
+ }
+
+ /**
+ * Returns the bounds of the bubble bar.
+ */
+ public Rect getBubbleBarBounds() {
+ return mBubbleBarBounds;
+ }
+
+ // TODO: (b/273592694) animate it
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ if (getChildCount() + 1 > MAX_BUBBLES) {
+ removeViewInLayout(getChildAt(getChildCount() - 1));
+ }
+ super.addView(child, index, params);
+ }
+
+ /**
+ * Updates the z order, positions, and badge visibility of the bubble views in the bar based
+ * on the expanded state.
+ */
+ // TODO: (b/273592694) animate it
+ private void updateChildrenRenderNodeProperties() {
+ int bubbleCount = getChildCount();
+ final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
+ for (int i = 0; i < bubbleCount; i++) {
+ BubbleView bv = (BubbleView) getChildAt(i);
+ bv.setTranslationY(ty);
+ if (mIsBarExpanded) {
+ final float tx = i * (mIconSize + mIconSpacing);
+ bv.setTranslationX(tx);
+ bv.setZ(0);
+ bv.showBadge();
+ } else {
+ bv.setZ((MAX_BUBBLES * mBubbleElevation) - i);
+ bv.setTranslationX(i * mIconOverlapAmount);
+ if (i > 0) {
+ bv.hideBadge();
+ } else {
+ bv.showBadge();
+ }
+ }
+ }
+ }
+
+ /**
+ * Reorders the views to match the provided list.
+ */
+ public void reorder(List<BubbleView> viewOrder) {
+ if (isExpanded()) {
+ mReorderRunnable = () -> doReorder(viewOrder);
+ } else {
+ doReorder(viewOrder);
+ }
+ }
+
+ // TODO: (b/273592694) animate it
+ private void doReorder(List<BubbleView> viewOrder) {
+ if (!isExpanded()) {
+ for (int i = 0; i < viewOrder.size(); i++) {
+ View child = viewOrder.get(i);
+ if (child != null) {
+ removeViewInLayout(child);
+ addViewInLayout(child, i, child.getLayoutParams());
+ }
+ }
+ updateChildrenRenderNodeProperties();
+ }
+ }
+
+ /**
+ * Sets which bubble view should be shown as selected.
+ */
+ // TODO: (b/273592694) animate it
+ public void setSelectedBubble(BubbleView view) {
+ mSelectedBubbleView = view;
+ updateArrowForSelected();
+ invalidate();
+ }
+
+ private void updateArrowForSelected() {
+ if (mSelectedBubbleView == null) {
+ Log.w(TAG, "trying to update selection arrow without a selected view!");
+ return;
+ }
+ final int index = indexOfChild(mSelectedBubbleView);
+ // Find the center of the bubble when it's expanded, set the arrow position to it.
+ final float tx = getPaddingStart() + index * (mIconSize + mIconSpacing) + mIconSize / 2f;
+ mBubbleBarBackground.setArrowPosition(tx);
+ }
+
+ @Override
+ public void setOnClickListener(View.OnClickListener listener) {
+ mOnClickListener = listener;
+ setOrUnsetClickListener();
+ }
+
+ /**
+ * The click listener used for the bubble view gets added / removed depending on whether
+ * the bar is expanded or collapsed, this updates whether the listener is set based on state.
+ */
+ private void setOrUnsetClickListener() {
+ super.setOnClickListener(mIsBarExpanded ? null : mOnClickListener);
+ }
+
+ /**
+ * Sets whether the bubble bar is expanded or collapsed.
+ */
+ // TODO: (b/273592694) animate it
+ public void setExpanded(boolean isBarExpanded) {
+ if (mIsBarExpanded != isBarExpanded) {
+ mIsBarExpanded = isBarExpanded;
+ updateArrowForSelected();
+ setOrUnsetClickListener();
+ if (!isBarExpanded && mReorderRunnable != null) {
+ mReorderRunnable.run();
+ mReorderRunnable = null;
+ }
+ mBubbleBarBackground.showArrow(mIsBarExpanded);
+ requestLayout(); // trigger layout to reposition views & update size for expansion
+ }
+ }
+
+ /**
+ * Returns whether the bubble bar is expanded.
+ */
+ public boolean isExpanded() {
+ return mIsBarExpanded;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int childCount = getChildCount();
+ final float iconWidth = mIsBarExpanded
+ ? (childCount * (mIconSize + mIconSpacing))
+ : mIconSize + ((childCount - 1) * mIconOverlapAmount);
+ final int totalWidth = (int) iconWidth + getPaddingStart() + getPaddingEnd();
+ setMeasuredDimension(totalWidth, MeasureSpec.getSize(heightMeasureSpec));
+
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ measureChild(child, (int) mIconSize, (int) mIconSize);
+ }
+ }
+
+ /**
+ * Returns whether the given MotionEvent, *in screen coordinates*, is within bubble bar
+ * touch bounds.
+ */
+ public boolean isEventOverAnyItem(MotionEvent ev) {
+ if (getVisibility() == View.VISIBLE) {
+ getBoundsOnScreen(mTempRect);
+ return mTempRect.contains((int) ev.getX(), (int) ev.getY());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (!mIsBarExpanded) {
+ // When the bar is collapsed, all taps on it should expand it.
+ return true;
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
new file mode 100644
index 0000000..deac42f
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -0,0 +1,276 @@
+/*
+ * 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.taskbar.bubbles;
+
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.util.MultiPropertyFactory;
+import com.android.launcher3.util.MultiValueAlpha;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Controller for {@link BubbleBarView}. Manages the visibility of the bubble bar as well as
+ * responding to changes in bubble state provided by BubbleBarController.
+ */
+public class BubbleBarViewController {
+
+ private static final String TAG = BubbleBarViewController.class.getSimpleName();
+
+ private final TaskbarActivityContext mActivity;
+ private final BubbleBarView mBarView;
+ private final int mIconSize;
+
+ // Initialized in init.
+ private View.OnClickListener mBubbleClickListener;
+ private View.OnClickListener mBubbleBarClickListener;
+
+ // These are exposed to BubbleStashController to animate for stashing/un-stashing
+ private final MultiValueAlpha mBubbleBarAlpha;
+ private final AnimatedFloat mBubbleBarScale = new AnimatedFloat(this::updateScale);
+ private final AnimatedFloat mBubbleBarTranslationY = new AnimatedFloat(
+ this::updateTranslationY);
+
+ // Modified when swipe up is happening on the bubble bar or task bar.
+ private float mBubbleBarSwipeUpTranslationY;
+
+ // Whether the bar is hidden for a sysui state.
+ private boolean mHiddenForSysui;
+ // Whether the bar is hidden because there are no bubbles.
+ private boolean mHiddenForNoBubbles;
+
+ public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
+ mActivity = activity;
+ mBarView = barView;
+ mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */);
+ mBubbleBarAlpha.setUpdateVisibility(true);
+ mIconSize = activity.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
+ }
+
+ public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
+ mActivity.addOnDeviceProfileChangeListener(dp ->
+ mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight
+ );
+ mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight;
+ mBubbleBarScale.updateValue(1f);
+ mBubbleClickListener = v -> onBubbleClicked(v);
+ mBubbleBarClickListener = v -> setExpanded(true);
+ mBarView.setOnClickListener(mBubbleBarClickListener);
+ // TODO: when barView layout changes tell taskbarInsetsController the insets have changed.
+ }
+
+ private void onBubbleClicked(View v) {
+ BubbleBarBubble bubble = ((BubbleView) v).getBubble();
+ if (bubble == null) {
+ Log.e(TAG, "bubble click listener, bubble was null");
+ }
+ // TODO: handle the click
+ }
+
+ //
+ // The below animators are exposed to BubbleStashController so it can manage the stashing
+ // animation.
+ //
+
+ public MultiPropertyFactory<View> getBubbleBarAlpha() {
+ return mBubbleBarAlpha;
+ }
+
+ public AnimatedFloat getBubbleBarScale() {
+ return mBubbleBarScale;
+ }
+
+ public AnimatedFloat getBubbleBarTranslationY() {
+ return mBubbleBarTranslationY;
+ }
+
+ /**
+ * Whether the bubble bar is visible or not.
+ */
+ public boolean isBubbleBarVisible() {
+ return mBarView.getVisibility() == VISIBLE;
+ }
+
+ /**
+ * The bounds of the bubble bar.
+ */
+ public Rect getBubbleBarBounds() {
+ return mBarView.getBubbleBarBounds();
+ }
+
+ /**
+ * When the bubble bar is not stashed, it can be collapsed (the icons are in a stack) or
+ * expanded (the icons are in a row). This indicates whether the bubble bar is expanded.
+ */
+ public boolean isExpanded() {
+ return mBarView.isExpanded();
+ }
+
+ /**
+ * Whether the motion event is within the bounds of the bubble bar.
+ */
+ public boolean isEventOverAnyItem(MotionEvent ev) {
+ return mBarView.isEventOverAnyItem(ev);
+ }
+
+ //
+ // Visibility of the bubble bar
+ //
+
+ /**
+ * Returns whether the bubble bar is hidden because there are no bubbles.
+ */
+ public boolean isHiddenForNoBubbles() {
+ return mHiddenForNoBubbles;
+ }
+
+ /**
+ * Sets whether the bubble bar should be hidden because there are no bubbles.
+ */
+ public void setHiddenForBubbles(boolean hidden) {
+ if (mHiddenForNoBubbles != hidden) {
+ mHiddenForNoBubbles = hidden;
+ updateVisibilityForStateChange();
+ }
+ }
+
+ /**
+ * Sets whether the bubble bar should be hidden due to SysUI state (e.g. on lockscreen).
+ */
+ public void setHiddenForSysui(boolean hidden) {
+ if (mHiddenForSysui != hidden) {
+ mHiddenForSysui = hidden;
+ updateVisibilityForStateChange();
+ }
+ }
+
+ // TODO: (b/273592694) animate it
+ private void updateVisibilityForStateChange() {
+ // TODO: check if it's stashed
+ if (!mHiddenForSysui && !mHiddenForNoBubbles) {
+ mBarView.setVisibility(VISIBLE);
+ } else {
+ mBarView.setVisibility(INVISIBLE);
+ }
+ }
+
+ //
+ // Modifying view related properties.
+ //
+
+ /**
+ * Sets the translation of the bubble bar during the swipe up gesture.
+ */
+ public void setTranslationYForSwipe(float transY) {
+ mBubbleBarSwipeUpTranslationY = transY;
+ updateTranslationY();
+ }
+
+ private void updateTranslationY() {
+ mBarView.setTranslationY(mBubbleBarTranslationY.value
+ + mBubbleBarSwipeUpTranslationY);
+ }
+
+ /**
+ * Applies scale properties for the entire bubble bar.
+ */
+ private void updateScale() {
+ float scale = mBubbleBarScale.value;
+ mBarView.setScaleX(scale);
+ mBarView.setScaleY(scale);
+ }
+
+ //
+ // Manipulating the specific bubble views in the bar
+ //
+
+ /**
+ * Removes the provided bubble from the bubble bar.
+ */
+ public void removeBubble(BubbleBarBubble b) {
+ if (b != null) {
+ mBarView.removeView(b.getView());
+ } else {
+ Log.w(TAG, "removeBubble, bubble was null!");
+ }
+ }
+
+ /**
+ * Adds the provided bubble to the bubble bar.
+ */
+ public void addBubble(BubbleBarBubble b) {
+ if (b != null) {
+ mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
+ b.getView().setOnClickListener(mBubbleClickListener);
+ } else {
+ Log.w(TAG, "addBubble, bubble was null!");
+ }
+ }
+
+ /**
+ * Reorders the bubbles based on the provided list.
+ */
+ public void reorderBubbles(List<BubbleBarBubble> newOrder) {
+ List<BubbleView> viewList = newOrder.stream().filter(Objects::nonNull)
+ .map(BubbleBarBubble::getView).toList();
+ mBarView.reorder(viewList);
+ }
+
+ /**
+ * Updates the selected bubble.
+ */
+ public void updateSelectedBubble(BubbleBarBubble newlySelected) {
+ mBarView.setSelectedBubble(newlySelected.getView());
+ }
+
+ /**
+ * Sets whether the bubble bar should be expanded (not unstashed, but have the contents
+ * within it expanded). This method notifies SystemUI that the bubble bar is expanded and
+ * showing a selected bubble. This method should ONLY be called from UI events originating
+ * from Launcher.
+ */
+ public void setExpanded(boolean isExpanded) {
+ if (isExpanded != mBarView.isExpanded()) {
+ mBarView.setExpanded(isExpanded);
+ if (!isExpanded) {
+ // TODO: Tell SysUi to collapse the bubble
+ } else {
+ // TODO: Tell SysUi to show the bubble
+ // TODO: Tell taskbar stash controller to stash without bubbles following
+ }
+ }
+ }
+
+ /**
+ * Sets whether the bubble bar should be expanded. This method is used in response to UI events
+ * from SystemUI.
+ */
+ public void setExpandedFromSysui(boolean isExpanded) {
+ // TODO: Tell bubble bar stash controller to stash or unstash the bubble bar
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
new file mode 100644
index 0000000..e92d4fb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -0,0 +1,66 @@
+/*
+ * 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.taskbar.bubbles;
+
+import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.util.RunnableList;
+
+/**
+ * Hosts various bubble controllers to facilitate passing between one another.
+ */
+public class BubbleControllers {
+
+ public final BubbleBarViewController bubbleBarViewController;
+
+ private final RunnableList mPostInitRunnables = new RunnableList();
+
+ /**
+ * Want to add a new controller? Don't forget to:
+ * * Call init
+ * * Call onDestroy
+ */
+ public BubbleControllers(BubbleBarViewController bubbleBarViewController) {
+ this.bubbleBarViewController = bubbleBarViewController;
+ }
+
+ /**
+ * Initializes all controllers. Note that controllers can now reference each other through this
+ * BubbleControllers instance, but should be careful to only access things that were created
+ * in constructors for now, as some controllers may still be waiting for init().
+ */
+ public void init(TaskbarControllers taskbarControllers) {
+ bubbleBarViewController.init(taskbarControllers, this);
+
+ mPostInitRunnables.executeAllAndDestroy();
+ }
+
+ /**
+ * If all controllers are already initialized, runs the given callback immediately. Otherwise,
+ * queues it to run after calling init() on all controllers. This should likely be used in any
+ * case where one controller is telling another controller to do something inside init().
+ */
+ public void runAfterInit(Runnable runnable) {
+ // If this has been executed in init, it automatically runs adds to it.
+ mPostInitRunnables.add(runnable);
+ }
+
+ /**
+ * Cleans up all controllers.
+ */
+ public void onDestroy() {
+ // TODO
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
new file mode 100644
index 0000000..e22e63a
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -0,0 +1,134 @@
+/*
+ * 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.taskbar.bubbles;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.widget.ImageView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.icons.IconNormalizer;
+
+// TODO: (b/276978250) This is will be similar to WMShell's BadgedImageView, it'd be nice to share.
+// TODO: (b/269670235) currently this doesn't show the 'update dot'
+/**
+ * View that displays a bubble icon, along with an app badge on either the left or
+ * right side of the view.
+ */
+public class BubbleView extends ConstraintLayout {
+
+ // TODO: (b/269670235) currently we don't render the 'update dot', this will be used for that.
+ public static final int DEFAULT_PATH_SIZE = 100;
+
+ private final ImageView mBubbleIcon;
+ private final ImageView mAppIcon;
+ private final int mBubbleSize;
+
+ // TODO: (b/273310265) handle RTL
+ private boolean mOnLeft = false;
+
+ private BubbleBarBubble mBubble;
+
+ public BubbleView(Context context) {
+ this(context, null);
+ }
+
+ public BubbleView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BubbleView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public BubbleView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ // We manage positioning the badge ourselves
+ setLayoutDirection(LAYOUT_DIRECTION_LTR);
+
+ LayoutInflater.from(context).inflate(R.layout.bubble_view, this);
+
+ mBubbleSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
+ mBubbleIcon = findViewById(R.id.icon_view);
+ mAppIcon = findViewById(R.id.app_icon_view);
+
+ setFocusable(true);
+ setClickable(true);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ BubbleView.this.getOutline(outline);
+ }
+ });
+ }
+
+ private void getOutline(Outline outline) {
+ final int normalizedSize = IconNormalizer.getNormalizedCircleSize(mBubbleSize);
+ final int inset = (mBubbleSize - normalizedSize) / 2;
+ outline.setOval(inset, inset, inset + normalizedSize, inset + normalizedSize);
+ }
+
+ /** Sets the bubble being rendered in this view. */
+ void setBubble(BubbleBarBubble bubble) {
+ mBubble = bubble;
+ mBubbleIcon.setImageBitmap(bubble.getIcon());
+ mAppIcon.setImageBitmap(bubble.getBadge());
+ }
+
+ /** Returns the bubble being rendered in this view. */
+ @Nullable
+ BubbleBarBubble getBubble() {
+ return mBubble;
+ }
+
+ /** Shows the app badge on this bubble. */
+ void showBadge() {
+ Bitmap appBadgeBitmap = mBubble.getBadge();
+ if (appBadgeBitmap == null) {
+ mAppIcon.setVisibility(GONE);
+ return;
+ }
+
+ int translationX;
+ if (mOnLeft) {
+ translationX = -(mBubble.getIcon().getWidth() - appBadgeBitmap.getWidth());
+ } else {
+ translationX = 0;
+ }
+
+ mAppIcon.setTranslationX(translationX);
+ mAppIcon.setVisibility(VISIBLE);
+ }
+
+ /** Hides the app badge on this bubble. */
+ void hideBadge() {
+ mAppIcon.setVisibility(GONE);
+ }
+
+ @Override
+ public String toString() {
+ return "BubbleView{" + mBubble + "}";
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 89920f0..fdf0c6a 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -77,6 +77,7 @@
import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -839,12 +840,18 @@
// If Taskbar is present, we listen for long press to unstash it.
TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
- if (tac != null && canStartSystemGesture) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("TaskbarActivityContext != null, using TaskbarStashInputConsumer");
- base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat, tac);
+ if (tac != null) {
+ // Present always on large screen or on small screen w/ flag
+ DeviceProfile dp = tac.getDeviceProfile();
+ boolean useTaskbarConsumer = dp.isTaskbarPresent && !TaskbarManager.isPhoneMode(dp);
+ if (canStartSystemGesture && useTaskbarConsumer) {
+ reasonString.append(NEWLINE_PREFIX)
+ .append(reasonPrefix)
+ .append(SUBSTRING_PREFIX)
+ .append("TaskbarActivityContext != null, "
+ + "using TaskbarStashInputConsumer");
+ base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat, tac);
+ }
}
if (mDeviceState.isBubblesExpanded()) {
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 79971de..8274a51 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -63,11 +64,13 @@
import com.android.launcher3.util.Executors;
import com.android.quickstep.GestureState;
import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.util.LottieAnimationColorUtils;
import com.android.quickstep.util.TISBindHelper;
import com.airbnb.lottie.LottieAnimationView;
import java.net.URISyntaxException;
+import java.util.Map;
/**
* A page shows after SUW flow to hint users to swipe up from the bottom of the screen to go home
@@ -82,6 +85,9 @@
private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "suwColorAccentLight";
private static final String EXTRA_DEVICE_NAME = "suwDeviceName";
+ private static final String LOTTIE_PRIMARY_COLOR_TOKEN = ".primary";
+ private static final String LOTTIE_TERTIARY_COLOR_TOKEN = ".tertiary";
+
private static final float HINT_BOTTOM_FACTOR = 1 - .94f;
private static final int MAX_SWIPE_DURATION = 350;
@@ -114,7 +120,8 @@
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ Resources resources = getResources();
+ int mode = resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
Intent intent = getIntent();
int accentColor = intent.getIntExtra(
@@ -126,7 +133,7 @@
mBackground = new BgDrawable(this);
findViewById(R.id.root_view).setBackground(mBackground);
mContentView = findViewById(R.id.content_view);
- mSwipeUpShift = getResources().getDimension(R.dimen.allset_swipe_up_shift);
+ mSwipeUpShift = resources.getDimension(R.dimen.allset_swipe_up_shift);
TextView subtitle = findViewById(R.id.subtitle);
String suwDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
@@ -188,8 +195,15 @@
// There's a bug in the currently used external Lottie library (v5.2.0), and it doesn't load
// the correct animation from the raw resources when configuration changes, so we need to
// manually load the resource and pass it to Lottie.
- mAnimatedBackground.setAnimation(getResources().openRawResource(R.raw.all_set_page_bg),
+ mAnimatedBackground.setAnimation(resources.openRawResource(R.raw.all_set_page_bg),
null);
+
+ LottieAnimationColorUtils.updateColors(
+ mAnimatedBackground,
+ Map.of(LOTTIE_PRIMARY_COLOR_TOKEN, R.color.all_set_bg_primary,
+ LOTTIE_TERTIARY_COLOR_TOKEN, R.color.all_set_bg_tertiary),
+ getTheme());
+
startBackgroundAnimation();
}
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.java b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
index 1f1c15b..c30661c 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
@@ -26,7 +26,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Px;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.Interpolators;
@@ -61,7 +60,7 @@
@NonNull private final Interpolator mInterpolator;
@NonNull private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private int mAlignmentAdjustment;
+ private float mAlignmentAdjustment;
@Nullable private Animator mRunningBorderAnimation;
@@ -106,16 +105,12 @@
private void updateOutline() {
float interpolatedProgress = mInterpolator.getInterpolation(
mBorderAnimationProgress.value);
- mAlignmentAdjustment = (int) Utilities.mapBoundToRange(
- mBorderAnimationProgress.value,
- /* lowerBound= */ 0f,
- /* upperBound= */ 1f,
- /* toMin= */ 0f,
- /* toMax= */ (float) (mBorderWidthPx / 2f),
- mInterpolator);
+ float borderWidth = mBorderWidthPx * interpolatedProgress;
+ // Inset the border by half the width to create an inwards-growth animation
+ mAlignmentAdjustment = borderWidth / 2f;
mBorderPaint.setAlpha(Math.round(255 * interpolatedProgress));
- mBorderPaint.setStrokeWidth(Math.round(mBorderWidthPx * interpolatedProgress));
+ mBorderPaint.setStrokeWidth(borderWidth);
mInvalidateViewCallback.run();
}
diff --git a/quickstep/src/com/android/quickstep/util/LottieAnimationColorUtils.java b/quickstep/src/com/android/quickstep/util/LottieAnimationColorUtils.java
new file mode 100644
index 0000000..f98b04b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LottieAnimationColorUtils.java
@@ -0,0 +1,90 @@
+/*
+ * 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.quickstep.util;
+
+import static com.airbnb.lottie.LottieProperty.COLOR_FILTER;
+
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.airbnb.lottie.LottieAnimationView;
+import com.airbnb.lottie.model.KeyPath;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/** Utility class for programmatically updating Lottie animation tokenized colors. */
+public final class LottieAnimationColorUtils {
+
+ private LottieAnimationColorUtils() {}
+
+ /**
+ * Updates the given Lottie animation's tokenized colors according to the given mapping.
+ * <p>
+ * Use this method signature only when {@code tokenToColorCodeMap} maps to packed ARBG color
+ * integers.
+ * <p>
+ * @param animationView {@link LottieAnimationView} whose animation's colors need to be updated
+ * @param tokenToColorCodeMap A mapping from the color tokens used in the Lottie file used in
+ * {@code animationView} to packed ARBG color integers.
+ */
+ public static void updateColors(
+ @NonNull LottieAnimationView animationView,
+ @NonNull Map<String, Integer> tokenToColorCodeMap) {
+ updateColors(animationView, tokenToColorCodeMap, null);
+ }
+
+ /**
+ * Updates the given Lottie animation's tokenized colors according to the given mapping.
+ * <p>
+ * Use this method signature with a non-null theme only when {@code tokenToColorCodeMap} maps
+ * to color resource references.
+ * <p>
+ * @param animationView {@link LottieAnimationView} whose animation's colors need to be updated
+ * @param tokenToColorCodeMap A mapping from the color tokens used in the Lottie file used in
+ * {@code animationView} to packed ARBG color integers or color
+ * resource references.
+ * @param theme {@link Theme} to be used when resolving color resource references. {@code null}
+ * iff {@code tokenToColorCodeMap} maps to packed ARBG color integers.
+ */
+ public static void updateColors(
+ @NonNull LottieAnimationView animationView,
+ @NonNull Map<String, Integer> tokenToColorCodeMap,
+ @Nullable Theme theme) {
+ Resources resources = animationView.getResources();
+ final Map<String, Integer> tokenToColorMap = theme == null
+ // tokenToColorCodeMap maps directly to ARBG values
+ ? tokenToColorCodeMap
+ // tokenToColorCodeMap maps to color references, build a mapping to resolved colors
+ : tokenToColorCodeMap.keySet().stream().collect(Collectors.toMap(
+ Function.identity(),
+ token -> resources.getColor(tokenToColorCodeMap.get(token), theme)));
+
+ animationView.addLottieOnCompositionLoadedListener(
+ composition -> tokenToColorMap.forEach(
+ (token, color) -> animationView.addValueCallback(
+ new KeyPath("**", token, "**"),
+ COLOR_FILTER,
+ frameInfo -> new PorterDuffColorFilter(
+ color, PorterDuff.Mode.SRC_ATOP))));
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 428bd95..8ee0fbb 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -77,10 +77,10 @@
shouldScaleArrow = true
mIsArrowRotated = true
// This synchronizes the arrow and menu to open at the same time
- OPEN_CHILD_FADE_START_DELAY = OPEN_FADE_START_DELAY
- OPEN_CHILD_FADE_DURATION = OPEN_FADE_DURATION
- CLOSE_FADE_START_DELAY = CLOSE_CHILD_FADE_START_DELAY
- CLOSE_FADE_DURATION = CLOSE_CHILD_FADE_DURATION
+ mOpenChildFadeStartDelay = mOpenFadeStartDelay
+ mOpenChildFadeDuration = mOpenFadeDuration
+ mCloseFadeStartDelay = mCloseChildFadeStartDelay
+ mCloseFadeDuration = mCloseChildFadeDuration
}
private var alignedOptionIndex: Int = 0
@@ -213,7 +213,7 @@
scrim?.let {
anim.play(
ObjectAnimator.ofFloat(it, View.ALPHA, 0f, scrimAlpha)
- .setDuration(OPEN_DURATION.toLong())
+ .setDuration(mOpenDuration.toLong())
)
}
}
@@ -222,7 +222,7 @@
scrim?.let {
anim.play(
ObjectAnimator.ofFloat(it, View.ALPHA, scrimAlpha, 0f)
- .setDuration(CLOSE_DURATION.toLong())
+ .setDuration(mCloseDuration.toLong())
)
}
}
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index e543370..f041ffb 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -16,6 +16,7 @@
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -51,8 +52,8 @@
* Updates the app widgets whose id has changed during the restore process.
*/
@WorkerThread
- public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds,
- @NonNull AppWidgetHost host) {
+ public static void restoreAppWidgetIds(Context context, DatabaseHelper helper,
+ int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
if (WidgetsModel.GO_DISABLE_WIDGETS) {
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
host.deleteHost();
@@ -90,14 +91,16 @@
String oldWidgetId = Integer.toString(oldWidgetIds[i]);
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
- int result = new ContentWriter(context, new ContentWriter.CommitParams(where, args))
+ int result = new ContentWriter(context,
+ new ContentWriter.CommitParams(helper, where, args))
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
.put(LauncherSettings.Favorites.RESTORED, state)
.commit();
if (result == 0) {
- Cursor cursor = cr.query(Favorites.CONTENT_URI,
+ Cursor cursor = helper.getWritableDatabase().query(
+ Favorites.TABLE_NAME,
new String[] {Favorites.APPWIDGET_ID},
- "appWidgetId=?", new String[] { oldWidgetId }, null);
+ "appWidgetId=?", new String[] { oldWidgetId }, null, null, null);
try {
if (!cursor.moveToFirst()) {
// The widget no long exists.
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 06ac44a..0e027f8 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -50,6 +50,7 @@
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.LauncherBinder;
import com.android.launcher3.model.LoaderTask;
+import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.ModelDelegate;
import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.model.PackageIncrementalDownloadUpdatedTask;
@@ -94,6 +95,8 @@
@NonNull
private final LauncherAppState mApp;
@NonNull
+ private final ModelDbController mModelDbController;
+ @NonNull
private final Object mLock = new Object();
@Nullable
private LoaderTask mLoaderTask;
@@ -143,6 +146,7 @@
@NonNull final IconCache iconCache, @NonNull final AppFilter appFilter,
final boolean isPrimaryInstance) {
mApp = app;
+ mModelDbController = new ModelDbController(context);
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
mModelDelegate = ModelDelegate.newInstance(context, app, mBgAllAppsList, mBgDataModel,
isPrimaryInstance);
@@ -153,6 +157,10 @@
return mModelDelegate;
}
+ public ModelDbController getModelDbController() {
+ return mModelDbController;
+ }
+
/**
* Adds the provided items to the workspace.
*/
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index d30d23c..0df4bd4 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -50,8 +50,6 @@
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
- protected ModelDbController mModelDbController;
-
/**
* $ adb shell dumpsys activity provider com.android.launcher3
*/
@@ -69,7 +67,6 @@
if (FeatureFlags.IS_STUDIO_BUILD) {
Log.d(TAG, "Launcher process started");
}
- mModelDbController = new ModelDbController(getContext());
// The content provider exists for the entire duration of the launcher main process and
// is the first component to get created.
@@ -77,6 +74,10 @@
return true;
}
+ public ModelDbController getModelDbController() {
+ return LauncherAppState.getInstance(getContext()).getModel().getModelDbController();
+ }
+
@Override
public String getType(Uri uri) {
SqlArguments args = new SqlArguments(uri, null, null);
@@ -95,7 +96,7 @@
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(args.table);
- Cursor result = mModelDbController.query(
+ Cursor result = getModelDbController().query(
args.table, projection, args.where, args.args, sortOrder);
result.setNotificationUri(getContext().getContentResolver(), uri);
return result;
@@ -120,7 +121,7 @@
}
SqlArguments args = new SqlArguments(uri);
- int rowId = mModelDbController.insert(args.table, initialValues);
+ int rowId = getModelDbController().insert(args.table, initialValues);
if (rowId < 0) return null;
uri = ContentUris.withAppendedId(uri, rowId);
@@ -130,7 +131,7 @@
private boolean initializeExternalAdd(ContentValues values) {
// 1. Ensure that externally added items have a valid item id
- int id = mModelDbController.generateNewItemId();
+ int id = getModelDbController().generateNewItemId();
values.put(LauncherSettings.Favorites._ID, id);
// 2. In the case of an app widget, and if no app widget id is specified, we
@@ -171,7 +172,7 @@
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
SqlArguments args = new SqlArguments(uri);
- mModelDbController.bulkInsert(args.table, values);
+ getModelDbController().bulkInsert(args.table, values);
reloadLauncherIfExternal();
return values.length;
}
@@ -180,7 +181,7 @@
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
- try (SQLiteTransaction t = mModelDbController.newTransaction()) {
+ try (SQLiteTransaction t = getModelDbController().newTransaction()) {
final int numOperations = operations.size();
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i < numOperations; i++) {
@@ -196,7 +197,7 @@
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
- int count = mModelDbController.delete(args.table, args.where, args.args);
+ int count = getModelDbController().delete(args.table, args.where, args.args);
if (count > 0) {
reloadLauncherIfExternal();
}
@@ -206,7 +207,7 @@
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
- int count = mModelDbController.update(args.table, values, args.where, args.args);
+ int count = getModelDbController().update(args.table, values, args.where, args.args);
reloadLauncherIfExternal();
return count;
}
@@ -219,59 +220,59 @@
switch (method) {
case LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG: {
- mModelDbController.clearEmptyDbFlag();
+ getModelDbController().clearEmptyDbFlag();
return null;
}
case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: {
Bundle result = new Bundle();
result.putIntArray(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.deleteEmptyFolders().toArray());
+ getModelDbController().deleteEmptyFolders().toArray());
return result;
}
case LauncherSettings.Settings.METHOD_NEW_ITEM_ID: {
Bundle result = new Bundle();
result.putInt(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.generateNewItemId());
+ getModelDbController().generateNewItemId());
return result;
}
case LauncherSettings.Settings.METHOD_NEW_SCREEN_ID: {
Bundle result = new Bundle();
result.putInt(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.getNewScreenId());
+ getModelDbController().getNewScreenId());
return result;
}
case LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB: {
- mModelDbController.createEmptyDB();
+ getModelDbController().createEmptyDB();
return null;
}
case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
- mModelDbController.loadDefaultFavoritesIfNecessary();
+ getModelDbController().loadDefaultFavoritesIfNecessary();
return null;
}
case LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS: {
- mModelDbController.removeGhostWidgets();
+ getModelDbController().removeGhostWidgets();
return null;
}
case LauncherSettings.Settings.METHOD_NEW_TRANSACTION: {
Bundle result = new Bundle();
result.putBinder(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.newTransaction());
+ getModelDbController().newTransaction());
return result;
}
case LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE: {
- mModelDbController.refreshHotseatRestoreTable();
+ getModelDbController().refreshHotseatRestoreTable();
return null;
}
case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.updateCurrentOpenHelper(arg /* dbFile */));
+ getModelDbController().updateCurrentOpenHelper(arg /* dbFile */));
return result;
}
case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- mModelDbController.prepareForPreview(arg /* dbFile */));
+ getModelDbController().prepareForPreview(arg /* dbFile */));
return result;
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 0c653cd..bedb41c 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -362,6 +362,10 @@
"Enables the ability to create and save app pairs on the Home screen for easy"
+ " split screen launching.");
+ public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
+ "ENABLE_CURSOR_HOVER_STATES", DISABLED,
+ "Enables cursor hover states for certain elements.");
+
public static class BooleanFlag {
private final boolean mCurrentValue;
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index b569fc3..d366c4a 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -78,9 +78,9 @@
private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V3.get() ? 0.8f : 0.7f;
private static final float PROGRESS_STROKE_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get()
- ? 0.06666667f
+ ? 0.055f
: 0.075f;
- private static final float PROGRESS_BOUNDS_SCALE = 0.08f;
+ private static final float PROGRESS_BOUNDS_SCALE = 0.075f;
private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 01e58f2..bf839bf 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.model;
+import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
+
import android.util.Log;
import androidx.annotation.NonNull;
@@ -30,6 +32,7 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
@@ -106,6 +109,10 @@
List<WorkspaceItemInfo> workspaceUpdates = allUpdates.stream()
.filter(info -> info.id != ItemInfo.NO_ID)
.collect(Collectors.toList());
+ if (TestProtocol.sDebugTracing) {
+ Log.d(WORK_TAB_MISSING, "allUpdates: " + allUpdates.size() + ", workspaceUpdates "
+ + workspaceUpdates.size());
+ }
if (!workspaceUpdates.isEmpty()) {
scheduleCallbackTask(c -> c.bindWorkspaceItemsChanged(workspaceUpdates));
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index c237f5b..a5dccc1 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -65,6 +65,7 @@
private final LongSparseArray<UserHandle> allUsers;
+ private final LauncherAppState mApp;
private final Uri mContentUri;
private final Context mContext;
private final PackageManager mPM;
@@ -111,6 +112,7 @@
UserManagerState userManagerState) {
super(cursor);
+ mApp = app;
allUsers = userManagerState.allUsers;
mContentUri = contentUri;
mContext = app.getContext();
@@ -388,6 +390,7 @@
*/
public ContentWriter updater() {
return new ContentWriter(mContext, new ContentWriter.CommitParams(
+ mApp.getModel().getModelDbController().getDatabaseHelper(),
BaseColumns._ID + "= ?", new String[]{Integer.toString(id)}));
}
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index 9b54ce1..97bce8c 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -50,6 +50,8 @@
import android.util.Log;
import android.util.Xml;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.AutoInstallsLayout.SourceResources;
import com.android.launcher3.DefaultLayoutParser;
@@ -115,6 +117,7 @@
/**
* Refer {@link SQLiteDatabase#query}
*/
+ @WorkerThread
public Cursor query(String table, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
createDbIfNotExists();
@@ -131,6 +134,7 @@
/**
* Refer {@link SQLiteDatabase#insert(String, String, ContentValues)}
*/
+ @WorkerThread
public int insert(String table, ContentValues initialValues) {
createDbIfNotExists();
@@ -146,6 +150,7 @@
/**
* Similar to insert but for adding multiple values in a transaction.
*/
+ @WorkerThread
public int bulkInsert(String table, ContentValues[] values) {
createDbIfNotExists();
@@ -167,6 +172,7 @@
/**
* Refer {@link SQLiteDatabase#delete(String, String, String[])}
*/
+ @WorkerThread
public int delete(String table, String selection, String[] selectionArgs) {
createDbIfNotExists();
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -185,6 +191,7 @@
/**
* Refer {@link SQLiteDatabase#update(String, ContentValues, String, String[])}
*/
+ @WorkerThread
public int update(String table, ContentValues values,
String selection, String[] selectionArgs) {
createDbIfNotExists();
@@ -198,6 +205,7 @@
/**
* Clears a previously set flag corresponding to empty db creation
*/
+ @WorkerThread
public void clearEmptyDbFlag() {
createDbIfNotExists();
clearFlagEmptyDbCreated();
@@ -206,6 +214,7 @@
/**
* Generates an id to be used for new item in the favorites table
*/
+ @WorkerThread
public int generateNewItemId() {
createDbIfNotExists();
return mOpenHelper.generateNewItemId();
@@ -214,6 +223,7 @@
/**
* Generates an id to be used for new workspace screen
*/
+ @WorkerThread
public int getNewScreenId() {
createDbIfNotExists();
return mOpenHelper.getNewScreenId();
@@ -222,6 +232,7 @@
/**
* Creates an empty DB clearing all existing data
*/
+ @WorkerThread
public void createEmptyDB() {
createDbIfNotExists();
mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
@@ -230,6 +241,7 @@
/**
* Removes any widget which are present in the framework, but not in out internal DB
*/
+ @WorkerThread
public void removeGhostWidgets() {
createDbIfNotExists();
mOpenHelper.removeGhostWidgets(mOpenHelper.getWritableDatabase());
@@ -238,6 +250,7 @@
/**
* Returns a new {@link SQLiteTransaction}
*/
+ @WorkerThread
public SQLiteTransaction newTransaction() {
createDbIfNotExists();
return new SQLiteTransaction(mOpenHelper.getWritableDatabase());
@@ -246,6 +259,7 @@
/**
* Refreshes the internal state corresponding to presence of hotseat table
*/
+ @WorkerThread
public void refreshHotseatRestoreTable() {
createDbIfNotExists();
mOpenHelper.mHotseatRestoreTableExists = tableExists(
@@ -256,6 +270,7 @@
* Updates the current DB and copies all the existing data to the temp table
* @param dbFile name of the target db file name
*/
+ @WorkerThread
public boolean updateCurrentOpenHelper(String dbFile) {
createDbIfNotExists();
return prepForMigration(
@@ -270,6 +285,7 @@
* Returns the current DatabaseHelper.
* Only for tests
*/
+ @WorkerThread
public DatabaseHelper getDatabaseHelper() {
createDbIfNotExists();
return mOpenHelper;
@@ -278,6 +294,7 @@
/**
* Prepares the DB for preview by copying all existing data to preview table
*/
+ @WorkerThread
public boolean prepareForPreview(String dbFile) {
createDbIfNotExists();
return prepForMigration(
@@ -296,6 +313,7 @@
* Deletes any empty folder from the DB.
* @return Ids of deleted folders.
*/
+ @WorkerThread
public IntArray deleteEmptyFolders() {
createDbIfNotExists();
@@ -338,6 +356,7 @@
* 3) From a partner configuration APK, already in the system image
* 4) The default configuration for the particular device
*/
+ @WorkerThread
public synchronized void loadDefaultFavoritesIfNecessary() {
createDbIfNotExists();
SharedPreferences sp = LauncherPrefs.getPrefs(mContext);
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 772ffa4..ddb8b05 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -33,7 +33,6 @@
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
@@ -267,8 +266,7 @@
item.onAddToDatabase(writer);
writer.put(Favorites._ID, item.id);
- cr.insert(Favorites.CONTENT_URI, writer.getValues(mContext));
-
+ mModel.getModelDbController().insert(Favorites.TABLE_NAME, writer.getValues(mContext));
synchronized (mBgDataModel) {
checkItemInfoLocked(item.id, item, stackTrace);
mBgDataModel.addItem(mContext, item, true);
@@ -324,13 +322,13 @@
notifyDelete(Collections.singleton(info));
enqueueDeleteRunnable(() -> {
- ContentResolver cr = mContext.getContentResolver();
- cr.delete(LauncherSettings.Favorites.CONTENT_URI,
- LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+ mModel.getModelDbController().delete(Favorites.TABLE_NAME,
+ Favorites.CONTAINER + "=" + info.id, null);
mBgDataModel.removeItem(mContext, info.contents);
info.contents.clear();
- cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
+ mModel.getModelDbController().delete(Favorites.TABLE_NAME,
+ Favorites._ID + "=" + info.id, null);
mBgDataModel.removeItem(mContext, info);
verifier.verifyModel();
});
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 63ca35b..cb78138 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -16,10 +16,12 @@
package com.android.launcher3.model;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
+import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
+import android.util.Log;
import androidx.annotation.NonNull;
@@ -29,6 +31,7 @@
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -60,6 +63,10 @@
if (mIsUserUnlocked) {
QueryResult shortcuts = new ShortcutRequest(context, mUser)
.query(ShortcutRequest.PINNED);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(WORK_TAB_MISSING, "shortcutQuery success? "
+ + shortcuts.wasSuccess());
+ }
if (shortcuts.wasSuccess()) {
for (ShortcutInfo shortcut : shortcuts) {
pinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut);
@@ -82,6 +89,9 @@
if (mIsUserUnlocked) {
ShortcutKey key = ShortcutKey.fromItemInfo(si);
ShortcutInfo shortcut = pinnedShortcuts.get(key);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(WORK_TAB_MISSING, "shortcutInfo: " + shortcut);
+ }
// We couldn't verify the shortcut during loader. If its no longer available
// (probably due to clear data), delete the workspace item as well
if (shortcut == null) {
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 5b493c2..b59b37a 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -70,17 +70,17 @@
extends AbstractFloatingView {
// Duration values (ms) for popup open and close animations.
- protected int OPEN_DURATION = 276;
- protected int OPEN_FADE_START_DELAY = 0;
- protected int OPEN_FADE_DURATION = 38;
- protected int OPEN_CHILD_FADE_START_DELAY = 38;
- protected int OPEN_CHILD_FADE_DURATION = 76;
+ protected int mOpenDuration = 276;
+ protected int mOpenFadeStartDelay = 0;
+ protected int mOpenFadeDuration = 38;
+ protected int mOpenChildFadeStartDelay = 38;
+ protected int mOpenChildFadeDuration = 76;
- protected int CLOSE_DURATION = 200;
- protected int CLOSE_FADE_START_DELAY = 140;
- protected int CLOSE_FADE_DURATION = 50;
- protected int CLOSE_CHILD_FADE_START_DELAY = 0;
- protected int CLOSE_CHILD_FADE_DURATION = 140;
+ protected int mCloseDuration = 200;
+ protected int mCloseFadeStartDelay = 140;
+ protected int mCloseFadeDuration = 50;
+ protected int mCloseChildFadeStartDelay = 0;
+ protected int mCloseChildFadeDuration = 140;
private static final int OPEN_DURATION_U = 200;
private static final int OPEN_FADE_START_DELAY_U = 0;
@@ -583,11 +583,11 @@
EMPHASIZED_DECELERATE)
: getOpenCloseAnimator(
true,
- OPEN_DURATION,
- OPEN_FADE_START_DELAY,
- OPEN_FADE_DURATION,
- OPEN_CHILD_FADE_START_DELAY,
- OPEN_CHILD_FADE_DURATION,
+ mOpenDuration,
+ mOpenFadeStartDelay,
+ mOpenFadeDuration,
+ mOpenChildFadeStartDelay,
+ mOpenChildFadeDuration,
DECELERATED_EASE);
onCreateOpenAnimation(mOpenCloseAnimator);
@@ -672,8 +672,8 @@
}
mIsOpen = false;
- mOpenCloseAnimator = getOpenCloseAnimator(false, CLOSE_DURATION, CLOSE_FADE_START_DELAY,
- CLOSE_FADE_DURATION, CLOSE_CHILD_FADE_START_DELAY, CLOSE_CHILD_FADE_DURATION,
+ mOpenCloseAnimator = getOpenCloseAnimator(false, mCloseDuration, mCloseFadeStartDelay,
+ mCloseFadeDuration, mCloseChildFadeStartDelay, mCloseChildFadeDuration,
ACCELERATED_EASE);
mOpenCloseAnimator = ENABLE_MATERIAL_U_POPUP.get()
@@ -686,11 +686,11 @@
CLOSE_CHILD_FADE_DURATION_U,
EMPHASIZED_ACCELERATE)
: getOpenCloseAnimator(false,
- CLOSE_DURATION,
- CLOSE_FADE_START_DELAY,
- CLOSE_FADE_DURATION,
- CLOSE_CHILD_FADE_START_DELAY,
- CLOSE_CHILD_FADE_DURATION,
+ mCloseDuration,
+ mCloseFadeStartDelay,
+ mCloseFadeDuration,
+ mCloseChildFadeStartDelay,
+ mCloseChildFadeDuration,
ACCELERATED_EASE);
onCreateCloseAnimation(mOpenCloseAnimator);
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index ba5249c..ac72164 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -107,7 +107,7 @@
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
RestoreDbTask task = new RestoreDbTask();
task.sanitizeDB(context, helper, db, new BackupManager(context));
- task.restoreAppWidgetIdsIfExists(context);
+ task.restoreAppWidgetIdsIfExists(context, helper);
t.commit();
return true;
} catch (Exception e) {
@@ -321,11 +321,11 @@
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
}
- private void restoreAppWidgetIdsIfExists(Context context) {
+ private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) {
LauncherPrefs lp = LauncherPrefs.get(context);
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
- AppWidgetsRestoredReceiver.restoreAppWidgetIds(context,
+ AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper,
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
host);
diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java
index 55c2585..e509235 100644
--- a/src/com/android/launcher3/util/ContentWriter.java
+++ b/src/com/android/launcher3/util/ContentWriter.java
@@ -19,13 +19,14 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import android.os.UserHandle;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.GraphicsUtils;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.pm.UserCache;
/**
@@ -105,7 +106,8 @@
public int commit() {
if (mCommitParams != null) {
- return mContext.getContentResolver().update(mCommitParams.mUri, getValues(mContext),
+ mCommitParams.mDatabaseHelper.getWritableDatabase().update(
+ Favorites.TABLE_NAME, getValues(mContext),
mCommitParams.mWhere, mCommitParams.mSelectionArgs);
}
return 0;
@@ -113,12 +115,12 @@
public static final class CommitParams {
- final Uri mUri;
+ final DatabaseHelper mDatabaseHelper;
final String mWhere;
final String[] mSelectionArgs;
- public CommitParams(String where, String[] selectionArgs) {
- mUri = LauncherSettings.Favorites.CONTENT_URI;
+ public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) {
+ mDatabaseHelper = helper;
mWhere = where;
mSelectionArgs = selectionArgs;
}
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 9e88c06..bf31e39 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -62,7 +62,6 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
@@ -423,12 +422,11 @@
@Override
public boolean onCreate() {
- mModelDbController = new ModelDbController(getContext());
return true;
}
public SQLiteDatabase getDb() {
- return mModelDbController.getDatabaseHelper().getWritableDatabase();
+ return getModelDbController().getDatabaseHelper().getWritableDatabase();
}
}