Merge changes from topic "revert-20479526-revert-20427045-258023561-BPDASTWITO-FBDWZBDEFC" into tm-qpr-dev
* changes:
Fixing the revert by not continuing the reorder if the solution is null.
Revert "Revert "Reorder widgets no longer overlaps when no space..."
diff --git a/go/quickstep/res/values-en-rCA/strings.xml b/go/quickstep/res/values-en-rCA/strings.xml
index 676ac43..664bd94 100644
--- a/go/quickstep/res/values-en-rCA/strings.xml
+++ b/go/quickstep/res/values-en-rCA/strings.xml
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_share_drop_target_label" msgid="5804774105974539508">"Share app"</string>
+ <string name="app_share_drop_target_label" msgid="5804774105974539508">"Share App"</string>
<string name="action_listen" msgid="2370304050784689486">"Listen"</string>
<string name="action_translate" msgid="8028378961867277746">"Translate"</string>
<string name="action_search" msgid="6269564710943755464">"Lens"</string>
- <string name="dialog_acknowledge" msgid="2804025517675853172">"OK"</string>
+ <string name="dialog_acknowledge" msgid="2804025517675853172">"GOT IT"</string>
<string name="dialog_cancel" msgid="6464336969134856366">"CANCEL"</string>
<string name="dialog_settings" msgid="6564397136021186148">"SETTINGS"</string>
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Translate or listen to text on screen"</string>
- <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Information such as text on your screen, web addresses and screenshots may be shared with Google.\n\nTo change what information you share, go to "<b>"Settings > Apps > Default apps > Digital assistant app"</b>"."</string>
+ <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Information such as text on your screen, web addresses, and screenshots may be shared with Google.\n\nTo change what information you share, go to "<b>"Settings > Apps > Default apps > Digital assistant app"</b>"."</string>
<string name="assistant_not_selected_title" msgid="5017072974603345228">"Choose an assistant to use this feature"</string>
- <string name="assistant_not_selected_text" msgid="3244613673884359276">"To listen to or translate text on your screen, choose a digital assistant app in settings"</string>
+ <string name="assistant_not_selected_text" msgid="3244613673884359276">"To listen to or translate text on your screen, choose a digital assistant app in Settings"</string>
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Change your assistant to use this feature"</string>
- <string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in settings"</string>
+ <string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in Settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index c997e52..253147d 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -50,8 +50,8 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseActivity;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.views.ArrowTipView;
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.util.RecentsOrientedState;
@@ -124,7 +124,7 @@
AssistContentRequester assistContentRequester) {
super(taskThumbnailView);
mFactoryContentRequester = assistContentRequester;
- mSharedPreferences = Utilities.getPrefs(mApplicationContext);
+ mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
}
/**
@@ -151,7 +151,7 @@
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
- mSharedPreferences = Utilities.getPrefs(mApplicationContext);
+ mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
checkSettings();
if (!mAssistStructurePermitted || !mAssistScreenshotPermitted
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 9a000d6..1aa5d03 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -41,10 +41,8 @@
*/
public class WidgetsModel {
- // True if the widget support is disabled.
+ // True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = true;
- // True if the shortcut support is disabled.
- public static final boolean GO_DISABLE_SHORTCUTS = true;
public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
private static final ArrayList<WidgetsListBaseEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
diff --git a/lint-baseline-launcher3.xml b/lint-baseline-launcher3.xml
index 107a346..a9dc0c6 100644
--- a/lint-baseline-launcher3.xml
+++ b/lint-baseline-launcher3.xml
@@ -606,4 +606,20 @@
column="61"/>
</issue>
+ <issue
+ id="NewApi"
+ message="Call requires API level 33 (current min is 26): `android.app.Activity#getOnBackInvokedDispatcher`">
+ <location
+ file="packages/apps/Launcher3/src/com/android/launcher3/BaseActivity.java"
+ line="182"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 33 (current min is 26): `android.window.OnBackInvokedDispatcher#registerOnBackInvokedCallback`">
+ <location
+ file="packages/apps/Launcher3/src/com/android/launcher3/BaseActivity.java"
+ line="182"/>
+ </issue>
+
</issues>
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index 7292c44..f5a8253 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -38,6 +38,7 @@
name: "launcher3-quickstep-oop-tests-src",
path: "tests",
srcs: [
+ "tests/src/com/android/quickstep/TaskbarModeSwitchRule.java",
"tests/src/com/android/quickstep/NavigationModeSwitchRule.java",
"tests/src/com/android/quickstep/AbstractQuickStepTest.java",
"tests/src/com/android/quickstep/TaplTestsQuickstep.java",
diff --git a/quickstep/res/layout-sw600dp-land/allset_navigation_and_hint.xml b/quickstep/res/layout-sw600dp-land/allset_navigation_and_hint.xml
deleted file mode 100644
index 3bfa6da..0000000
--- a/quickstep/res/layout-sw600dp-land/allset_navigation_and_hint.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <TextView
- android:id="@+id/navigation_settings"
- style="@style/TextAppearance.GestureTutorial.LinkText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="32dp"
- android:background="?android:attr/selectableItemBackground"
- android:minHeight="48dp"
- android:text="@string/allset_navigation_settings"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/subtitle" />
-
- <TextView
- android:id="@+id/hint"
- style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/allset_page_margin_bottom"
- android:text="@string/allset_hint"
- android:textSize="@dimen/allset_page_swipe_up_text_size"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent" />
-
-</merge>
\ No newline at end of file
diff --git a/quickstep/res/layout-sw600dp/allset_navigation_and_hint.xml b/quickstep/res/layout-sw600dp/allset_navigation_and_hint.xml
index 9559072..44b3ecb 100644
--- a/quickstep/res/layout-sw600dp/allset_navigation_and_hint.xml
+++ b/quickstep/res/layout-sw600dp/allset_navigation_and_hint.xml
@@ -21,12 +21,11 @@
style="@style/TextAppearance.GestureTutorial.LinkText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="96dp"
+ android:layout_marginTop="24dp"
android:background="?android:attr/selectableItemBackground"
android:minHeight="48dp"
android:text="@string/allset_navigation_settings"
- app:layout_constraintBottom_toTopOf="@id/hint"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/subtitle"
app:layout_constraintStart_toStartOf="parent" />
<TextView
@@ -34,7 +33,7 @@
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/allset_page_margin_bottom"
+ android:layout_marginBottom="24dp"
android:text="@string/allset_hint"
android:textSize="@dimen/allset_page_swipe_up_text_size"
app:layout_constraintBottom_toBottomOf="parent"
diff --git a/quickstep/res/layout/all_apps_edu_view.xml b/quickstep/res/layout/all_apps_edu_view.xml
index e7ef6e6..0dd4df1 100644
--- a/quickstep/res/layout/all_apps_edu_view.xml
+++ b/quickstep/res/layout/all_apps_edu_view.xml
@@ -3,4 +3,5 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="@dimen/swipe_edu_width"
- android:layout_height="@dimen/swipe_edu_max_height"/>
+ android:layout_height="@dimen/swipe_edu_max_height"
+ android:accessibilityPaneTitle="@string/taskbar_edu_a11y_title"/>
diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml
index 34d4b23..a0dce65 100644
--- a/quickstep/res/layout/taskbar_all_apps.xml
+++ b/quickstep/res/layout/taskbar_all_apps.xml
@@ -17,7 +17,8 @@
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:accessibilityPaneTitle="@string/all_apps_label">
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
android:id="@+id/apps_view"
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 34805ea..8bfca3f 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutoriaal <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Gereed!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swiep op om na die tuisskerm toe te gaan"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Jy is gereed om jou foon te begin gebruik"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Jy is gereed om jou tablet te begin gebruik"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Stelselnavigasie-instellings"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
<string name="action_split" msgid="2098009717623550676">"Verdeel"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Probeer ander program om verdeelde skerm te gebruik"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Program steun nie verdeelde skerm nie."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Jou organisasie laat nie hierdie program toe nie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Slaan navigasietutoriaal oor?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Jy kan dit later in die <xliff:g id="NAME">%1$s</xliff:g>-program kry"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 1789c2b..bc4209e 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"አጋዥ ሥልጠና <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"ሁሉም ዝግጁ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ወደ መነሻ ለመሄድ በጣት ወደ ላይ ማንሸራተት"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ስልክዎን መጠቀም ለመጀመር ዝግጁ ነዎት"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ጡባዊዎን መጠቀም ለመጀመር ዝግጁ ነዎት"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"የስርዓት አሰሳ ቅንብሮች"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
<string name="action_split" msgid="2098009717623550676">"ክፈል"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"የተከፈለ ማያን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ይህ ድርጊት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"የአሰሳ አጋዥ ሥልጠናን ይዝለሉ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ይህን በኋላ በ<xliff:g id="NAME">%1$s</xliff:g> መተግበሪያው ውስጥ ማግኘት ይችላሉ"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index f9755d2..b461230 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"الدليل التوجيهي <xliff:g id="CURRENT">%1$d</xliff:g> من إجمالي <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"اكتملت عملية الإعداد"</string>
<string name="allset_hint" msgid="2384632994739392447">"مرِّر سريعًا للأعلى للانتقال إلى الشاشة الرئيسية."</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"يمكنك الآن بدء استخدام هاتفك."</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"يمكنك الآن بدء استخدام جهازك اللوحي."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"إعدادات التنقّل داخل النظام"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
<string name="action_split" msgid="2098009717623550676">"تقسيم"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"التطبيق لا يتيح تقسيم الشاشة."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"هل تريد تخطي الدليل التوجيهي؟"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"يمكنك العثور على هذا الدليل التوجيهي لاحقًا في التطبيق \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index ec47dd4..3bae94e 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"টিউট’ৰিয়েল <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"সকলো সাজু!"</string>
<string name="allset_hint" msgid="2384632994739392447">"গৃহ স্ক্ৰীনলৈ যাবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"আপুনি আপোনাৰ ফ’নটো ব্যৱহাৰ কৰিবলৈ সাজু"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"আপুনি আপোনাৰ টেবলেটটো ব্যৱহাৰ কৰিবলৈ সাজু"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ছিষ্টেম নেভিগেশ্বনৰ ছেটিং"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
<string name="action_split" msgid="2098009717623550676">"বিভাজন কৰক"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"এপ্টোৱে বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"এপ্টোৱে অথবা আপোনাৰ প্ৰতিষ্ঠানে এই কাৰ্যটোৰ অনুমতি নিদিয়ে"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশ্বনৰ টিউট’ৰিয়েল এৰিব বিচাৰে নেকি?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপুনি এয়া পাছত <xliff:g id="NAME">%1$s</xliff:g> এপ্টোত বিচাৰিব পাৰিব"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 7d15232..ff01f86 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Dərslik <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Hər şey hazırdır!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Əsas səhifəyə keçmək üçün yuxarı çəkin"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Telefondan istifadəyə başlamağa hazırsınız"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Planşetdən istifadəyə başlamağa hazırsınız"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistem naviqasiya ayarları"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skrinşot"</string>
<string name="action_split" msgid="2098009717623550676">"Ayırın"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Bölmə ekranını istifadə etmək üçün başqa tətbiqə toxunun"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Tətbiq ekran bölünməsini dəstəkləmir."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu əməliyyata tətbiq və ya təşkilatınız tərəfindən icazə verilmir"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Naviqasiya dərsliyi ötürülsün?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu sonra <xliff:g id="NAME">%1$s</xliff:g> tətbiqində tapa bilərsiniz"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 6387953..881237c 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Vodič <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Gotovo!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prevucite nagore da biste otvorili početni ekran"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Spremni ste da počnete da koristite telefon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Spremni ste da počnete da koristite tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Podešavanja kretanja kroz sistem"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podeli"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu aplikaciju za podeljeni ekran"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacija ne podržava podeljeni ekran."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili organizacija ne dozvoljavaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite da preskočite vodič za kretanje?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Možete da pronađete ovo kasnije u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 5e5f147..db280f2 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Дапаможнік <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Гатова!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Каб перайсці на галоўны экран, правядзіце пальцам уверх"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Вы можаце пачаць карыстанне тэлефонам"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Вы можаце пачаць карыстанне планшэтам"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Налады навігацыі ў сістэме"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
<string name="action_split" msgid="2098009717623550676">"Падзелены экран"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Для падзеленага экрана націсніце на іншую праграму"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Праграма не падтрымлівае рэжым падзеленага экрана."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Гэта дзеянне не дазволена праграмай ці вашай арганізацыяй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Прапусціць дапаможнік па навігацыі?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Знайсці дапаможнік можна ў праграме \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index ca61151..375fa6a 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Урок <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Прекарайте пръст нагоре, за да отворите началния екран"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Можете да започнете да използвате телефона си"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Можете да започнете да използвате таблета си"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Настройки за навигиране в системата"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
<string name="action_split" msgid="2098009717623550676">"Разделяне на екрана"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Докоснете друго прил., за да ползвате разд. екран"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Приложението не поддържа разделен екран."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Това действие не е разрешено от приложението или организацията ви"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропускане на урока за навигиране?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Урокът е налице в приложението <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 268e736..24d2f1a 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"টিউটোরিয়াল <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"সব রেডি!"</string>
<string name="allset_hint" msgid="2384632994739392447">"হোম স্ক্রিনে যেতে উপরের দিকে সোয়াইপ করুন"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"এবারে আপনি ফোন ব্যবহার করতে পারবেন"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"এবারে আপনি ট্যাবলেট ব্যবহার করতে পারবেন"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"সিস্টেম নেভিগেশন সেটিংস"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
<string name="action_split" msgid="2098009717623550676">"স্প্লিট"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"স্প্লিটস্ক্রিন ব্যবহার করতে অন্য অ্যাপে ট্যাপ করুন"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"স্প্লিট-স্ক্রিনে এই অ্যাপ কাজ করে না।"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশন টিউটোরিয়াল এড়িয়ে যেতে চান?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"আপনি <xliff:g id="NAME">%1$s</xliff:g> অ্যাপে পরে এটি খুঁজে পাবেন"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 1ff0817..208e457 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Vodič <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prevucite prema gore da odete na početni ekran"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Sve je spremno da počnete koristiti telefon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Sve je spremno da počnete koristiti tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigiranja sistemom"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu apl. da koristite podijeljeni ekran"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacija ne podržava podijeljeni ekran."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Ovu radnju ne dozvoljava aplikacija ili vaša organizacija"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Preskočiti vodič za navigiranje?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Možete ga pronaći kasnije u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 4957aee..2eb1492 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Tot a punt!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Llisca cap amunt per anar a la pàgina d\'inici"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Ja pots començar a utilitzar el telèfon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Ja pots començar a utilitzar la tauleta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuració de navegació del sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="action_split" msgid="2098009717623550676">"Divideix"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Toca una altra aplicació per dividir la pantalla"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"L\'aplicació no admet la pantalla dividida."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'aplicació o la teva organització no permeten aquesta acció"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vols ometre el tutorial de navegació?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pots trobar-lo més tard a l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index fa707ac..e337de0 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Výukový program <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Hotovo!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Přejetím nahoru se vrátíte na plochu"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Jste připraveni začít používat telefon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Jste připraveni začít používat tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavení navigace v systému"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
<string name="action_split" msgid="2098009717623550676">"Rozdělit"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Klepnutím na jinou aplikaci rozdělíte obrazovku"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikace nepodporuje režim rozdělené obrazovky."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikace nebo organizace zakazuje tuto akci"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Přeskočit výukový program k navigaci?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Program později najdete v aplikaci <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index d88061d..2c9591a 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Selvstudie <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Alt er parat!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Stryg opad for at gå til startsiden"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Du er klar til at bruge din telefon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Du er klar til at bruge din tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Indstillinger for systemnavigation"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Opdel"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tryk på en anden app for at bruge opdelt skærm"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Appen understøtter ikke opdelt skærm."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller din organisation tillader ikke denne handling"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe selvstudiet for navigation over?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finde dette senere i appen <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 3728b35..d0b8983 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Anleitung <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Nach oben wischen, um den Startbildschirm aufzurufen"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Du kannst dein Smartphone jetzt verwenden"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Du kannst dein Tablet jetzt verwenden"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Teilen"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Für „Bildschirm teilen“ auf weitere App tippen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"„Geteilter Bildschirm“ wird v. d. App nicht unterstützt."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Die App oder deine Organisation lässt diese Aktion nicht zu"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigationstutorial überspringen?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du findest es später auch in der <xliff:g id="NAME">%1$s</xliff:g> App"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 5ff882e..a2ab151 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Οδηγός <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Όλα έτοιμα!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Σύρετε προς τα πάνω για μετάβαση στην αρχική οθόνη."</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Είστε έτοιμοι να ξεκινήσετε να χρησιμοποιείτε το τηλέφωνό σας"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Είστε έτοιμοι να ξεκινήσετε να χρησιμοποιείτε το tablet."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ρυθμίσεις πλοήγησης συστήματος"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
<string name="action_split" msgid="2098009717623550676">"Διαχωρισμός"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Πατήστε άλλη εφαρμογή για χρήση διαχωρισμού οθόνης"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Αυτή η ενέργεια δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Παράβλεψη οδηγού πλοήγησης;"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Βρείτε τον αργότερα στην εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 5b378b4..19b0c3c 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index ab0a8e9..f6498c3 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -25,18 +25,18 @@
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
- <string name="task_view_closed" msgid="9170038230110856166">"Task closed"</string>
+ <string name="task_view_closed" msgid="9170038230110856166">"Task Closed"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"< 1 minute"</string>
<string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> left today"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"App suggestions"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Your predicted apps"</string>
- <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Get app suggestions on the bottom row of your home screen"</string>
- <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Get app suggestions on the favourites row of your home screen"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Easily access your most-used apps directly from the home screen. Suggestions will change based on your routines. Apps on the bottom row will move up to your home screen."</string>
- <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Easily access your most-used apps directly from the home screen. Suggestions will change based on your routines. Apps in the favourites row will move to your home screen."</string>
+ <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Get app suggestions on the bottom row of your Home screen"</string>
+ <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Get app suggestions on favorites row of your Home screen"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move up to your Home screen."</string>
+ <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps in favorites row will move to your Home screen."</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"Get app suggestions"</string>
- <string name="hotseat_edu_dismiss" msgid="2781161822780201689">"No, thanks"</string>
+ <string name="hotseat_edu_dismiss" msgid="2781161822780201689">"No thanks"</string>
<string name="hotseat_prediction_settings" msgid="6246554993566070818">"Settings"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Most-used apps appear here, and change based on routines"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Drag apps off the bottom row to get app suggestions"</string>
@@ -44,47 +44,50 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App suggestions enabled"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App suggestions are disabled"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Make sure that you swipe from the far-right or far-left edge."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Make sure that you swipe from the right or left edge to the middle of the screen and let go."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"You learned how to swipe from the right to go back. Next, learn how to switch apps."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Make sure you swipe from the far-right or far-left edge."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Make sure you swipe from the right or left edge to the middle of the screen and let go."</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"You learned how to swipe from the right to go back. Next up, learn how to switch apps."</string>
<string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"You completed the go back gesture."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Make sure that you don\'t swipe too close to the bottom of the screen."</string>
- <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"To change sensitivity of the back gesture, go to Settings"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Make sure you don\'t swipe too close to the bottom of the screen."</string>
+ <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"To change the sensitivity of the back gesture, go to Settings"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Swipe to go back"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"To go back to the last screen, swipe from the left or right edge to the middle of the screen."</string>
- <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"To go back to the last screen, swipe with two fingers from the left or right edge to the middle of the screen."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Make sure that you swipe up from the bottom edge of the screen."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Make sure that you don\'t pause before letting go."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Make sure that you swipe straight up."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"You completed the go home gesture. Next, learn how to go back."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go home gesture."</string>
+ <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"To go back to the last screen, swipe with 2 fingers from the left or right edge to the middle of the screen."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Make sure you swipe up from the bottom edge of the screen."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Make sure you don\'t pause before letting go."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Make sure you swipe straight up."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"You completed the go Home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go Home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the home screen."</string>
- <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with two fingers from the bottom of the screen. This gesture always takes you to the home screen."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure that you swipe up from the bottom edge of the screen."</string>
+ <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the Home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen."</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure you swipe up from the bottom edge of the screen."</string>
<string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Try holding the window for longer before releasing."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Make sure that you swipe straight up, then pause."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Make sure you swipe straight up, then pause."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"You learned how to use gestures. To turn off gestures, go to Settings."</string>
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with two fingers from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release."</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"All set"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Done"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Settings"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Try again"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Nice!"</string>
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
- <string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
- <string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
+ <string name="allset_title" msgid="5021126669778966707">"All set!"</string>
+ <string name="allset_hint" msgid="2384632994739392447">"Swipe up to go Home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
- <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
+ <string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use splitscreen"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organization"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 5b378b4..19b0c3c 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 5b378b4..19b0c3c 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use split-screen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index f0b2066..55b99c8 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"All set!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go Home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027">""<annotation id="link">"System navigation settings"</annotation>""</string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tap another app to use splitscreen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App does not support split-screen."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organization"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"You can find this later in the <xliff:g id="NAME">%1$s</xliff:g> app"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index b9bb70f..7bb40e9 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Instructivo <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Todo listo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Desliza el dedo hacia arriba para ir a la pantalla principal"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Ya puedes empezar a usar tu teléfono"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Ya puedes empezar a usar tu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuración de navegación del sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="action_split" msgid="2098009717623550676">"Pantalla dividida"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Presiona otra app para usar la pantalla dividida"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"La app no es compatible con la función de pantalla dividida."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"La app o tu organización no permiten realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Omitir el instructivo de navegación?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes encontrarlo en la app de <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index f3d7a31..6610768 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"¡Ya está!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Desliza el dedo hacia arriba para ir a la pantalla de inicio"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Ya puedes empezar a usar tu teléfono"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Ya puedes empezar a usar tu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ajustes de navegación del sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Toca otra aplicación para usar la pantalla dividida"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"La aplicación no admite la pantalla dividida."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"No puedes hacerlo porque la aplicación o tu organización no lo permiten"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Saltar tutorial de navegación?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puedes consultarlo en otro momento en la aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 73c1c1d..67f4e1c 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Õpetus <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Valmis!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Avakuvale liikumiseks pühkige üles"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Olete valmis oma telefoni kasutama."</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Olete valmis oma tahvelarvutit kasutama"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Süsteemi navigeerimisseaded"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
<string name="action_split" msgid="2098009717623550676">"Eralda"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Jagatud kuva kasutamiseks puudutage muud rakendust"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Rakendus ei toeta jagatud ekraani."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Rakendus või teie organisatsioon on selle toimingu keelanud"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kas jätta navigeerimise õpetused vahele?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Leiate selle hiljem rakendusest <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 5b83633..0185bb9 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutoriala: <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Dena prest!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Pasatu hatza gora hasierako pantailara joateko"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Prest zaude telefonoa erabiltzen hasteko"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Prest zaude tableta erabiltzen hasteko"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sisteman nabigatzeko ezarpenak"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Atera pantaila-argazki bat"</string>
<string name="action_split" msgid="2098009717623550676">"Zatitu"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Sakatu beste aplikazio bat pantaila zatitzeko"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikazioak ez du onartzen pantaila zatitua."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikazioak edo erakundeak ez du eman ekintza hori gauzatzeko baimena"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Nabigazio-tutoriala saltatu nahi duzu?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> aplikazioan dago eskuragarri tutoriala"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index a64a876..44c9975 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"آموزش گامبهگام <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"همه چیز آماده است!"</string>
<string name="allset_hint" msgid="2384632994739392447">"برای رفتن به «صفحه اصلی»، تند بهبالا بکشید"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"آمادهاید از تلفنتان استفاده کنید"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"آمادهاید از رایانه لوحیتان استفاده کنید"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"تنظیمات پیمایش سیستم"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
<string name="action_split" msgid="2098009717623550676">"دونیمه"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"برای استفاده از صفحهٔ دونیمه، روی برنامه دیگری ضربه بزنید"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"برنامه از صفحهٔ دونیمه پشتیبانی نمیکند."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"برنامه یا سازمان شما اجازه نمیدهد این کنش انجام شود."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"آموزش گامبهگام پیمایش رد شود؟"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"میتوانید آن را بعداً در برنامه <xliff:g id="NAME">%1$s</xliff:g> پیدا کنید"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 08a9248..adff666 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Ohje <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Valmis"</string>
<string name="allset_hint" msgid="2384632994739392447">"Siirry aloitusnäytölle pyyhkäisemällä ylös"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Olet valmis aloittamaan puhelimen käytön"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Olet valmis aloittamaan tabletin käytön"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Järjestelmän navigointiasetukset"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
<string name="action_split" msgid="2098009717623550676">"Jaa"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Sovellus ei tue jaetun näytön tilaa."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Sovellus tai organisaatio ei salli tätä toimintoa"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ohitetaanko navigointiohje?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Löydät tämän myöhemmin sovelluksesta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 6199a14..63f1a1a 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Étape <xliff:g id="CURRENT">%1$d</xliff:g> sur <xliff:g id="TOTAL">%2$d</xliff:g> du tutoriel"</string>
<string name="allset_title" msgid="5021126669778966707">"Tout est prêt!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Balayez l\'écran vers le haut pour accéder à l\'écran d\'accueil"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Vous êtes maintenant prêt à utiliser votre téléphone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Vous êtes maintenant prêt à utiliser votre tablette"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Paramètres de navigation du système"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="action_split" msgid="2098009717623550676">"Séparé"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Touchez une autre appli pour partager l\'écran"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"L\'appli n\'est pas compatible avec l\'écran partagé."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'application ou votre organisation n\'autorise pas cette action"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel sur la navigation?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous trouverez le tutoriel dans l\'application <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index c66da27..5eccc91 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutoriel <xliff:g id="CURRENT">%1$d</xliff:g> sur <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Tout est prêt !"</string>
<string name="allset_hint" msgid="2384632994739392447">"Balayez l\'écran vers le haut pour revenir à l\'accueil"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Vous pouvez maintenant utiliser votre téléphone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Vous pouvez maintenant utiliser votre tablette"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Paramètres de navigation système"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="action_split" msgid="2098009717623550676">"Partager"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Appuyez sur autre appli pour utiliser écran partagé"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Appli incompatible avec l\'écran partagé."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Cette action n\'est pas autorisée par l\'application ou par votre organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel de navigation ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Vous le retrouverez dans l\'appli <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 9946f17..95c8761 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Titorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Todo listo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Pasa o dedo cara arriba para ir á pantalla de inicio"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Xa podes comezar a utilizar o teléfono"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Todo está listo para comezar a utilizar a tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuración da navegación do sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Para usar a pantalla dividida, toca outra app"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"A app non admite a función de pantalla dividida."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"A aplicación ou a túa organización non permite realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Queres omitir o titorial de navegación?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Podes atopalo máis tarde na aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 3439410..051077d 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ટ્યૂટૉરિઅલ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"બધું સેટ થઈ ગયું!"</string>
<string name="allset_hint" msgid="2384632994739392447">"હોમપેજ પર જવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"તમે તમારા ફોનનો ઉપયોગ કરવા માટે તૈયાર છો"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"તમે તમારા ટૅબ્લેટનો ઉપયોગ કરવા માટે તૈયાર છો"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"સિસ્ટમના નૅવિગેશન સેટિંગ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
<string name="action_split" msgid="2098009717623550676">"વિભાજિત કરો"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"સ્પલિટસ્ક્રીનના વપરાશ માટે, કોઈ અન્ય ઍપ પર ટૅપ કરો"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ઍપ સ્ક્રીન-વિભાજનને સપોર્ટ કરતી નથી."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"તમે આને પછીથી <xliff:g id="NAME">%1$s</xliff:g> ઍપમાં જોઈ શકો છો"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index be5a277..434845f 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ट्यूटोरियल <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"हो गया!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होम स्क्रीन पर जाने के लिए, ऊपर की ओर स्वाइप करें"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"अब आपका फ़ोन, इस्तेमाल के लिए तैयार है"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"आप टैबलेट को इस्तेमाल करने के लिए तैयार हैं"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टम नेविगेशन सेटिंग"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट स्क्रीन मोड"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिट स्क्रीन मोड के लिए, दूसरे ऐप पर टैप करें"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"यह ऐप्लिकेशन, स्प्लिट स्क्रीन पर काम नहीं करता है."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ऐप्लिकेशन या आपका संगठन इस कार्रवाई की अनुमति नहीं देता"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"क्या आपको नेविगेशन ट्यूटोरियल छोड़ना है?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"इसे बाद में <xliff:g id="NAME">%1$s</xliff:g> ऐप्लिकेशन पर देखा जा सकता है"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 620ba51..681105e 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Vodič <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prijeđite prstom prema gore da biste otvorili početni zaslon"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Spremni ste za početak upotrebe telefona"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Spremni ste za početak upotrebe tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigacije sustavom"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Dodirnite drugu aplikaciju za podijeljeni zaslon"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacija ne podržava podijeljeni zaslon."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili vaša organizacija ne dopuštaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite li preskočiti vodič za kretanje?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Kasnije ga možete pronaći u aplikaciji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 61f0a3b..46e4b2b 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Útmutató (<xliff:g id="TOTAL">%2$d</xliff:g>/<xliff:g id="CURRENT">%1$d</xliff:g>.)"</string>
<string name="allset_title" msgid="5021126669778966707">"Kész is!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Felfelé csúsztatva megjelenik a Kezdőképernyő"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Készen áll a telefon használatára"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Készen áll a táblagép használatára"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Rendszer-navigációs beállítások"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Képernyőkép"</string>
<string name="action_split" msgid="2098009717623550676">"Felosztás"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Koppintson másik appra a képernyőmegosztáshoz"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Az alkalmazás nem támogatja az osztott képernyőt."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Az alkalmazás vagy az Ön szervezete nem engedélyezi ezt a műveletet"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kihagyja a navigáció bemutatóját?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ezt később megtalálhatja a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazásban"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 0f9356a..cc49954 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Ուղեցույց <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Պատրաստ է"</string>
<string name="allset_hint" msgid="2384632994739392447">"Մատը սահեցրեք վերև՝ հիմնական էկրան անցնելու համար"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Դուք արդեն կարող եք օգտագործել ձեր հեռախոսը"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Դուք արդեն կարող եք օգտագործել ձեր պլանշետը"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Նավիգացիայի համակարգային կարգավորումներ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
<string name="action_split" msgid="2098009717623550676">"Տրոհել"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Հպեք այլ հավելվածի՝ էկրանը տրոհելու համար"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Հավելվածը չի աջակցում էկրանի տրոհումը։"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Այս գործողությունն արգելված է հավելվածի կամ ձեր կազմակերպության կողմից"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Բաց թողնե՞լ նավիգացիայի ուղեցույցը"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Հետագայում սա կարող եք գտնել «<xliff:g id="NAME">%1$s</xliff:g>» հավելվածում"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index b95871f..9012ba6 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Semua siap."</string>
<string name="allset_hint" msgid="2384632994739392447">"Geser ke atas untuk beralih ke Layar utama"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Anda sudah siap untuk mulai menggunakan ponsel"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Anda sudah siap untuk mulai menggunakan tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Setelan navigasi sistem"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Pisahkan"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Ketuk aplikasi lain untuk menggunakan layar terpisah"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikasi tidak mendukung layar terpisah."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Lewati tutorial gestur?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda dapat menemukan tutorial ini di lain waktu di aplikasi <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 5730900..d7f2075 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Leiðsögn <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Allt tilbúið!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Strjúktu upp til að fara á heimaskjáinn"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Þú getur byrjað að nota símann"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Þú getur byrjað að nota spjaldtölvuna"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Stillingar kerfisstjórnunar"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
<string name="action_split" msgid="2098009717623550676">"Skipta"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Ýttu á annað forrit til að nota skjáskiptingu"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Forritið styður ekki að skjánum sé skipt."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Forritið eða fyrirtækið leyfir ekki þessa aðgerð"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Sleppa flettileiðsögn?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Þú getur fundið þetta síðar í forritinu <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 7e04cf6..7df4dee 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Finito."</string>
<string name="allset_hint" msgid="2384632994739392447">"Scorri verso l\'alto per andare alla schermata Home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Puoi iniziare a usare il tuo telefono"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Puoi iniziare a usare il tuo tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Impostazioni Navigazione del sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Dividi"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tocca un\'altra app per usare lo schermo diviso"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"L\'app non supporta la modalità Schermo diviso."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Questa azione non è consentita dall\'app o dall\'organizzazione"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Saltare il tutorial di navigazione?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Puoi trovarlo in un secondo momento nell\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 56148e7..899011a 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"מדריך <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"הכול מוכן!"</string>
<string name="allset_hint" msgid="2384632994739392447">"כדי לעבור לדף הבית, מחליקים כלפי מעלה"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"הכול מוכן ואפשר להתחיל להשתמש בטלפון"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"הכול מוכן ואפשר להתחיל להשתמש בטאבלט"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"הגדרות הניווט של המערכת"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
<string name="action_split" msgid="2098009717623550676">"פיצול"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"האפליקציה אינה תומכת במסך מפוצל."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"האפליקציה או הארגון שלך אינם מתירים את הפעולה הזאת"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"לדלג על המדריך לניווט?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ניתן למצוא את המדריך מאוחר יותר באפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 013939f..3614e2d 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"チュートリアル <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"設定完了"</string>
<string name="allset_hint" msgid="2384632994739392447">"ホームに移動するには上にスワイプします"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"スマートフォンを使用する準備ができました"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"これでタブレットが使えるようになりました"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"システム ナビゲーションの設定"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"分割画面を使用するには、他のアプリをタップします"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"アプリで分割画面がサポートされていません。"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"この操作はアプリまたは組織で許可されていません"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"操作チュートリアルをスキップしますか?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"チュートリアルは後から <xliff:g id="NAME">%1$s</xliff:g> アプリで確認できます"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index d54ac881c..b862c6f 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"სახელმძღვანელო <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"მზადაა!"</string>
<string name="allset_hint" msgid="2384632994739392447">"მთავარ გვერდზე გადასასვლელად გადაფურცლეთ ზევით"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"მზად ხართ ტელეფონის გამოსაყენებლად"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"მზად ხართ ტაბლეტის გამოსაყენებლად"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"სისტემის ნავიგაციის პარამეტრები"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
<string name="action_split" msgid="2098009717623550676">"გაყოფა"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"შეეხეთ სხვა აპს ეკრანის გასაყოფად"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ეს მოქმედება არ არის დაშვებული აპის ან თქვენი ორგანიზაციის მიერ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"გსურთ, გამოტოვოთ ნავიგაციის სახელმძღვანელო?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ამის მოგვიანებით პოვნა <xliff:g id="NAME">%1$s</xliff:g> აპში შეგიძლიათ"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index bfa2a5c..8f42ff6 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Оқулық: <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Бәрі дайын!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Негізгі экранға өту үшін жоғары қарай сырғытыңыз."</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Телефоныңыз пайдалануға дайын."</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Планшетіңіз пайдалануға дайын."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Навигацияның жүйелік параметрлері"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлу"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Экранды бөлу режимін пайдалану үшін басқа қолданбаны түртіңіз."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Қолданбада экранды бөлу мүмкін емес."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Бұл әрекетке қолданба не ұйым рұқсат етпейді."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Қимылдар оқулығын өткізіп жіберу керек пе?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Мұны кейін <xliff:g id="NAME">%1$s</xliff:g> қолданбасынан таба аласыз."</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 4a78d9d..d1ed528 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"មេរៀនទី <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"រួចហើយ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"អូសឡើងលើ ដើម្បីទៅកាន់អេក្រង់ដើម"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"អ្នកអាចចាប់ផ្ដើមប្រើទូរសព្ទរបស់អ្នកបានហើយ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"អ្នកអាចចាប់ផ្ដើមប្រើថេប្លេតរបស់អ្នកបានហើយ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ការកំណត់ការរុករកប្រព័ន្ធ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
<string name="action_split" msgid="2098009717623550676">"បំបែក"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ចុចកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"កម្មវិធីមិនអាចប្រើមុខងារបំបែកអេក្រង់បានទេ។"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"សកម្មភាពនេះមិនត្រូវបានអនុញ្ញាតដោយកម្មវិធី ឬស្ថាប័នរបស់អ្នកទេ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"រំលងមេរៀនអំពីការរុករកឬ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"អ្នកអាចស្វែងរកមេរៀននេះនៅពេលក្រោយក្នុងកម្មវិធី <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 91a12f8..99fb8ba 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ಟ್ಯುಟೋರಿಯಲ್ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"ಎಲ್ಲವೂ ಸಿದ್ಧವಾಗಿದೆ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ನಿಮ್ಮ ಫೋನ್ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನೀವು ಸಿದ್ದರಾಗಿರುವಿರಿ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನೀವು ಸಿದ್ದರಾಗಿರುವಿರಿ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಶನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="action_split" msgid="2098009717623550676">"ವಿಭಜಿಸಿ"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬಳಸಲು ಬೇರೊಂದು ಆ್ಯಪ್ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಆ್ಯಪ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಶನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಬೇಕೇ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್ನಲ್ಲಿ ಇದನ್ನು ನಂತರ ಕಾಣಬಹುದು"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index bfe98f9..8af2ef7 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"튜토리얼 <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"설정 완료"</string>
<string name="allset_hint" msgid="2384632994739392447">"위로 스와이프하여 홈으로 이동"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"휴대전화를 사용할 준비가 되었습니다."</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"태블릿을 사용할 준비가 되었습니다."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"시스템 탐색 설정"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
<string name="action_split" msgid="2098009717623550676">"분할"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"다른 앱을 탭하여 화면 분할 사용"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"앱이 화면 분할을 지원하지 않습니다."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"이 작업은 앱 또는 조직에서 허용되지 않습니다."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"이동 방법 튜토리얼을 건너뛰시겠습니까?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"이 튜토리얼은 <xliff:g id="NAME">%1$s</xliff:g> 앱에서 다시 볼 수 있습니다."</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 5472ead..b7721f4 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Үйрөткүч: <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Бүттү!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Башкы бетке өтүү үчүн экранды өйдө сүрүңүз"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Телефонуңузду колдоно берсеңиз болот"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Планшетиңизди колдоно берсеңиз болот"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Өтүү аракетинин системалык параметрлери"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлүү"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Экранды бөлүү үчүн башка колдонмону таптап коюңуз"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Колдонмодо экран бөлүнбөйт."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Бул аракетти аткарууга колдонмо же ишканаңыз тыюу салган"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Жаңсоолор үйрөткүчүн өткөрүп жибересизби?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Аны кийин <xliff:g id="NAME">%1$s</xliff:g> колдонмосунан табасыз"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 7d87ec4..a1d8640 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ການສອນການນຳໃຊ້ທີ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"ຮຽບຮ້ອຍໝົດແລ້ວ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ປັດຂຶ້ນເພື່ອໄປຫາໜ້າຫຼັກ"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ທ່ານພ້ອມເລີ່ມຕົ້ນໃຊ້ໂທລະສັບຂອງທ່ານແລ້ວ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ທ່ານພ້ອມເລີ່ມຕົ້ນໃຊ້ແທັບເລັດຂອງທ່ານແລ້ວ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ການຕັ້ງຄ່າການນຳທາງລະບົບ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
<string name="action_split" msgid="2098009717623550676">"ແບ່ງ"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ແຕະແອັບອື່ນເພື່ອໃຊ້ການແຍກໜ້າຈໍ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ແອັບບໍ່ຮອງຮັບການແບ່ງໜ້າຈໍ."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ແອັບ ຫຼື ອົງການຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ໃຊ້ຄຳສັ່ງນີ້"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ຂ້າມການສອນການນຳໃຊ້ການນຳທາງບໍ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ທ່ານສາມາດຊອກສ່ວນນີ້ພາຍຫຼັງໄດ້ໃນແອັບ <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index b60146f..0ee9f0a 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Mokymo programa: <xliff:g id="CURRENT">%1$d</xliff:g> iš <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Paruošta!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Perbraukite aukštyn, kad grįžtumėte į pagrindinį ekraną"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Esate pasiruošę pradėti naudoti telefoną"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Esate pasiruošę pradėti naudoti planšetinį kompiuterį"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistemos naršymo nustatymai"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
<string name="action_split" msgid="2098009717623550676">"Išskaidymo režimas"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Pal. kitą progr., kad gal. naud. išsk. ekr. rež."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Programoje nepalaikomas išskaidyto ekrano režimas."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Jūsų organizacijoje arba naudojant šią programą neleidžiama atlikti šio veiksmo"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Praleisti naršymo mokymo programą?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tai galėsite rasti vėliau programoje „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index d3c3b80..27460f4 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"<xliff:g id="CURRENT">%1$d</xliff:g>. mācību darbība no <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Gatavs!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Velciet augšup, lai pārietu uz sākuma ekrānu."</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Varat sākt izmantot savu tālruni"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Varat sākt izmantot savu planšetdatoru"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistēmas navigācijas iestatījumi"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
<string name="action_split" msgid="2098009717623550676">"Sadalīt"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Piesk. citai lietotnei, lai izm. ekrāna sadalīšanu"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Lietotne vai jūsu organizācija neatļauj veikt šo darbību."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vai izlaist navigācijas mācības?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Varēsiet to vēlāk atrast lietotnē <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 7ac9ad0..38ec94b 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Упатство <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Повлечете нагоре за да појдете на почетниот екран"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Спремни сте да почнете да го користите телефонот"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Спремни сте да почнете да го користите таблетот"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Поставки за системска навигација"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
<string name="action_split" msgid="2098009717623550676">"Раздели"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Допрете друга апликација за да користите поделен екран"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Апликацијата не поддржува поделен екран."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликацијата или вашата организација не го дозволува дејствово"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Да се прескокне упатството за навигација?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ова може да го најдете подоцна во апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 90fc513..bc7efb9 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ട്യൂട്ടോറിയൽ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"എല്ലാം സജ്ജീകരിച്ചു!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ഹോമിലേക്ക് പോകാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ഫോൺ ഉപയോഗിച്ച് തുടങ്ങാൻ നിങ്ങൾ തയ്യാറാണ്"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ടാബ്ലെറ്റ് ഉപയോഗിച്ച് തുടങ്ങാൻ നിങ്ങൾ തയ്യാറാണ്"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"സിസ്റ്റം നാവിഗേഷൻ ക്രമീകരണം"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
<string name="action_split" msgid="2098009717623550676">"വിഭജിക്കുക"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"സ്പ്ലിറ്റ് സ്ക്രീനിനായി മറ്റൊരു ആപ്പ് ടാപ്പുചെയ്യൂ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ഈ നടപടി എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"നാവിഗേഷൻ ട്യൂട്ടോറിയൽ ഒഴിവാക്കണോ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ആപ്പിൽ നിങ്ങൾക്ക് ഇത് പിന്നീട് കാണാനാകും"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index c435528..45e66e4 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"<xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g> практик хичээл"</string>
<string name="allset_title" msgid="5021126669778966707">"Тохируулж дууслаа!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Нүүр хуудас руу очихын тулд дээш шударна уу"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Та утсаа ашиглаж эхлэхэд бэлэн боллоо"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Та таблетаа ашиглаж эхлэхэд бэлэн боллоо"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системийн навигацын тохиргоо"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
<string name="action_split" msgid="2098009717623550676">"Хуваах"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Дэлгэц хуваахыг ашиглах бол өөр аппыг товшино уу"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Апп дэлгэцийг хуваах горимыг дэмждэггүй."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Энэ үйлдлийг апп эсвэл танай байгууллага зөвшөөрдөггүй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Навигацын практик хичээлийг алгасах уу?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Та үүнийг дараа нь <xliff:g id="NAME">%1$s</xliff:g> аппаас олох боломжтой"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index fc90271..f6f8c14 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ट्यूटोरियल <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"सर्व तयार आहे!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होम वर जाण्यासाठी वरती स्वाइप करा"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"तुम्ही तुमचा फोन वापरण्यास सुरुवात करू शकता"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"तुम्ही तुमचा टॅबलेट वापरण्यास सुरुवात करू शकता"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टीम नेव्हिगेशन सेटिंग्ज"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटस्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"अॅप हे स्प्लिट-स्क्रीनला सपोर्ट करत नाही."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"अॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्यूटोरियल वगळायचे आहे का?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तुम्हाला हे नंतर <xliff:g id="NAME">%1$s</xliff:g> ॲपमध्ये मिळेल"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 5d3f4a8..d173790 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Siap!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Leret ke atas untuk kembali ke Laman Utama"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Anda sudah sedia untuk mula menggunakan telefon anda"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Anda bersedia untuk mula menggunakan tablet anda"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Tetapan navigasi sistem"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
<string name="action_split" msgid="2098009717623550676">"Pisah"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Ketik apl lain untuk menggunakan skrin pisah"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Apl tidak menyokong skrin pisah."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak dibenarkan oleh apl atau organisasi anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Langkau tutorial navigasi?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Anda boleh mendapatkan tutorial ini kemudian dalam apl <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 8f6af71..20441d1 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ရှင်းလင်းပို့ချချက် <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"အားလုံး အဆင်သင့်ပါ။"</string>
<string name="allset_hint" msgid="2384632994739392447">"ပင်မစာမျက်နှာသို့သွားရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"သင့်ဖုန်း စသုံးရန် အသင့်ဖြစ်ပါပြီ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"သင့်တက်ဘလက်ကို စသုံးရန် အသင့်ဖြစ်ပါပြီ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"စနစ် လမ်းညွှန် ဆက်တင်များ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"မျက်နှာပြင်ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"အက်ပ်တွင် မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံး၍မရပါ။"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ဤလုပ်ဆောင်ချက်ကို အက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်ကို ကျော်မလား။"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"၎င်းကို နောက်မှ <xliff:g id="NAME">%1$s</xliff:g> အက်ပ်တွင် ရှာနိုင်သည်"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index eff2e3c..4045c7c 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Veiledning <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Alt er klart!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Sveip opp for å gå til startskjermen"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Du er klar til å begynne å bruke telefonen"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Du er klar til å begynne å bruke nettbrettet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Innstillinger for systemnavigasjon"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
<string name="action_split" msgid="2098009717623550676">"Del opp"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Trykk på en annen app for å bruke delt skjerm"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Appen støtter ikke delt skjerm."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisasjonen din tillater ikke denne handlingen"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du hoppe over navigeringsveiledningen?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du kan finne dette i <xliff:g id="NAME">%1$s</xliff:g>-appen senere"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 3a23567..fe081fe 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ट्युटोरियल <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"सबै तयार भयो!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होममा जान माथितिर स्वाइप गर्नुहोस्"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"तपाईं आफ्नो फोन चलाउन थाल्न सक्नुहुन्छ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"तपाईं अब आफ्नो ट्याब्लेट चलाउन थाल्न सक्नुहुन्छ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टम नेभिगेसनसम्बन्धी सेटिङ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट गर्नुहोस्"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"स्प्लिटक्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नुहोस्"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"यो एपको स्क्रिन विभाजन गर्न मिल्दैन।"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"यो एप वा तपाईंको सङ्गठनले यो कारबाही गर्ने अनुमति दिँदैन"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेभिगेसन ट्युटोरियल स्किप गर्ने हो?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तपाईं पछि <xliff:g id="NAME">%1$s</xliff:g> नामक एपमा गई यो ट्युटोरियल भेट्टाउन सक्नुहुन्छ"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 650e340..5439833 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Klaar"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe omhoog om naar het startscherm te gaan"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Je bent klaar om je telefoon te gebruiken"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Je bent klaar om je tablet te gebruiken"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Navigatie-instellingen van systeem"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Splitsen"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tik op nog een app om je scherm te splitsen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"App ondersteunt geen gesplitst scherm."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Deze actie wordt niet toegestaan door de app of je organisatie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatietutorial overslaan?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Je vindt dit later terug in de app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 5016399..aa998ba 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ଟ୍ୟୁଟୋରିଆଲ୍ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ପ୍ରସ୍ତୁତ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ହୋମକୁ ଯିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ଆପଣ ଆପଣଙ୍କ ଫୋନ୍ ବ୍ୟବହାର କରିବା ପାଇଁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ଆପଣ ଆପଣଙ୍କ ଟାବଲେଟ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ସିଷ୍ଟମ ନାଭିଗେସନ ସେଟିଂସ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
<string name="action_split" msgid="2098009717623550676">"ସ୍ପ୍ଲିଟ୍"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ସ୍ପ୍ଲିଟସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପରେ ଟାପ କର"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ସ୍ପ୍ଲିଟ-ସ୍କ୍ରିନକୁ ଆପ ସମର୍ଥନ କରେ ନାହିଁ।"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ଆପ୍ କିମ୍ବା ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଏହି କାର୍ଯ୍ୟକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ନାଭିଗେସନ୍ ଟ୍ୟୁଟୋରିଆଲକୁ ବାଦ୍ ଦେବେ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ଆପଣ ପରେ ଏହାକୁ <xliff:g id="NAME">%1$s</xliff:g> ଆପରେ ପାଇପାରିବେ"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 7d1d2b5..4bcf4d6 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ਟਿਊਟੋਰੀਅਲ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਤਿਆਰ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਵਰਤਣ ਲਈ ਤਿਆਰ ਹੋ"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ਤੁਸੀਂ ਆਪਣਾ ਟੈਬਲੈੱਟ ਵਰਤਣ ਲਈ ਤਿਆਰ ਹੋ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਸੈਟਿੰਗਾਂ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="action_split" msgid="2098009717623550676">"ਸਪਲਿਟ"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਕਾਰਵਾਈ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ਕੀ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਛੱਡਣਾ ਹੈ?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ਤੁਸੀਂ ਇਸਨੂੰ ਬਾਅਦ ਵਿੱਚ <xliff:g id="NAME">%1$s</xliff:g> ਐਪ ਵਿੱਚ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 3c73de4..0394bb7 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Samouczek <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Wszystko gotowe"</string>
<string name="allset_hint" msgid="2384632994739392447">"Aby przejść na ekran główny, przesuń palcem w górę"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Teraz możesz zacząć używać telefonu"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Teraz możesz zacząć używać tabletu"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ustawienia nawigacji w systemie"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
<string name="action_split" msgid="2098009717623550676">"Podziel"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Kliknij drugą aplikację, aby podzielić ekran"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacja nie obsługuje podzielonego ekranu."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Nie możesz wykonać tego działania, bo nie zezwala na to aplikacja lub Twoja organizacja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pominąć samouczek nawigacji?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Znajdziesz to później w aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 5e01dc1..47bc834 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Tudo pronto!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Deslize rapidamente para cima para aceder ao ecrã principal"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Já pode começar a utilizar o seu telemóvel"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Já pode começar a usar o seu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Definições de navegação do sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Fazer captura de ecrã"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Toque noutra app para utilizar o ecrã dividido"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"A app não é compatível com o ecrã dividido."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Esta ação não é permitida pela app ou a sua entidade."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorar o tutorial de navegação?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Pode encontrar isto mais tarde na app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index fad2170..6a36608 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Tudo pronto!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Deslize para cima para acessar a tela inicial"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Você já pode começar a usar seu smartphone"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Você já pode começar a usar seu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configurações de navegação do sistema"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Toque em outro app para dividir a tela"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"O app não tem suporte para a divisão de tela."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Essa ação não é permitida pelo app ou pela organização"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pular o tutorial de navegação?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Veja o tutorial mais tarde no app <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 8b8c187..9856a6c 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorialul <xliff:g id="CURRENT">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Gata!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Glisează în sus pentru a accesa ecranul de pornire"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Ești gata să folosești telefonul"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Ești gata să folosești tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Setările de navigare ale sistemului"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
<string name="action_split" msgid="2098009717623550676">"Împărțit"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Atinge altă aplicație pentru ecranul împărțit"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplicația nu acceptă ecranul împărțit."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Această acțiune nu este permisă de aplicație sau de organizația ta"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Omiți tutorialul de navigare?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Îl poți găsi mai târziu în aplicația <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index e078ba0..de3343e 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Руководство (шаг <xliff:g id="CURRENT">%1$d</xliff:g> из <xliff:g id="TOTAL">%2$d</xliff:g>)"</string>
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Чтобы перейти на главный экран, проведите вверх."</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Теперь вы можете использовать телефон."</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Теперь вы можете использовать планшет."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системные настройки навигации"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Разделить"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Для разделения экрана нажмите на другое приложение."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Приложение не поддерживает разделение экрана."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Это действие заблокировано приложением или организацией."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустить руководство по жестам?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Его можно найти в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\"."</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index f890548..509490c 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"නිබන්ධනය <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"සියල්ල සූදානම්!"</string>
<string name="allset_hint" msgid="2384632994739392447">"මුල් පිටුවට යාමට ඉහළට ස්වයිප් කරන්න"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"ඔබ ඔබගේ දුරකථනය භාවිත කිරීම පටන් ගැනීමට සූදානම්"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"ඔබ ඔබගේ ටැබ්ලටය භාවිත කිරීම පටන් ගැනීමට සූදානම්"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"පද්ධති සංචාලන සැකසීම්"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
<string name="action_split" msgid="2098009717623550676">"බෙදන්න"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"බෙදුම් තිරය භාවිත කිරීමට තවත් යෙදුමක් තට්ටු කරන්න"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"යෙදුම බෙදුම් තිරය සඳහා සහාය නොදක්වයි."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"මෙම ක්රියාව යෙදුම හෝ ඔබේ සංවිධානය මගින් ඉඩ නොදේ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"නිබන්ධනය සංචාලනය මඟ හරින්නද?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"ඔබට මෙය පසුව <xliff:g id="NAME">%1$s</xliff:g> යෙදුම තුළ සොයා ගත හැකිය"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index cdf3339..f9372de 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Návod <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Hotovo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Potiahnutím nahor prejdete na plochu"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Telefón môžete začať používať"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Tablet môžete začať používať"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavenia navigácie systémom"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
<string name="action_split" msgid="2098009717623550676">"Rozdeliť"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Rozdel. obrazovku spustíte klepnutím na inú aplik."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikácia nepodporuje rozdelenú obrazovku."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikácia alebo vaša organizácia túto akciu nepovoľuje"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Chcete preskočiť návod na navigáciu?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Tento návod nájdete v aplikácii <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 3e7c5ce..0a5a271 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Vadnica <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Končano"</string>
<string name="allset_hint" msgid="2384632994739392447">"Povlecite navzgor za začetni zaslon"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Pripravljeni ste, da začnete uporabljati telefon"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Pripravljeni ste, da začnete uporabljati tablični računalnik."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavitve krmarjenja po sistemu"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Razdeli"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Za uporabo razdeljenega zaslona se dotaknite še ene aplikacije."</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacija ne podpira načina razdeljenega zaslona."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ali vaša organizacija ne dovoljuje tega dejanja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite preskočiti vadnico za krmarjenje?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"To lahko pozneje najdete v aplikaciji <xliff:g id="NAME">%1$s</xliff:g>."</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 04b7bc1..f326693 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Udhëzuesi <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Plotësisht gati!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Rrëshqit shpejt lart për të shkuar tek \"Ekrani bazë\""</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Je gati për të filluar përdorimin e telefonit tënd"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Je gati që të fillosh të përdorësh tabletin"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Cilësimet e navigimit të sistemit"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
<string name="action_split" msgid="2098009717623550676">"Ndaj"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Trokit aplikacion tjetër e përdor ekranin e ndarë"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplikacioni nuk mbështet ekranin e ndarë."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Ky veprim nuk lejohet nga aplikacioni ose organizata jote"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Të kapërcehet udhëzuesi i navigimit?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Këtë mund ta gjesh më vonë tek aplikacioni \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 215fde9..518023a 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Водич <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Превуците нагоре да бисте отворили почетни екран"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Спремни сте да почнете да користите телефон"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Спремни сте да почнете да користите таблет"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Подешавања кретања кроз систем"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Подели"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Додирните другу апликацију за подељени екран"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Апликација не подржава подељени екран."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликација или организација не дозвољавају ову радњу"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Желите да прескочите водич за кретање?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Можете да пронађете ово касније у апликацији <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index e7c0226..2d9db93 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Självstudie <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Klart!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Svep uppåt för att öppna startskärmen"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Nu kan du börja använda telefonen"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Nu kan du börja använda surfplattan"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Systemnavigeringsinställningar"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
<string name="action_split" msgid="2098009717623550676">"Delat"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Tryck på en annan app för att använda delad skärm"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Appen har inte stöd för delad skärm."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisationen tillåter inte den här åtgärden"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vill du hoppa över självstudierna?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Du hittar det här igen i <xliff:g id="NAME">%1$s</xliff:g>-appen"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index b1a178e..aadf378 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Mafunzo ya <xliff:g id="CURRENT">%1$d</xliff:g> kati ya <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Tayari!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Telezesha kidole juu ili uende kwenye skrini ya kwanza"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Uko tayari kuanza kutumia simu yako"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Uko tayari kuanza kutumia kompyuta kibao yako"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Mipangilio ya usogezaji kwenye mfumo"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
<string name="action_split" msgid="2098009717623550676">"Iliyogawanywa"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Gusa programu nyingine ili utumie skrini iliyogawanywa"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Programu haiwezi kutumia skrini iliyogawanywa."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Kitendo hiki hakiruhusiwi na programu au shirika lako"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ungependa kuruka mafunzo ya usogezaji?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Utapata mafunzo haya baadaye katika programu ya <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
index 5507fcf..dc10c24 100644
--- a/quickstep/res/values-sw600dp-land/dimens.xml
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -20,6 +20,5 @@
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">48dp</dimen>
- <dimen name="allset_page_margin_bottom">24dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index c96ad11..5899814 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -36,7 +36,6 @@
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">120dp</dimen>
- <dimen name="allset_page_margin_bottom">24dp</dimen>
<dimen name="allset_page_allset_text_size">38sp</dimen>
<dimen name="allset_page_swipe_up_text_size">15sp</dimen>
diff --git a/quickstep/res/values-sw720dp-land/dimens.xml b/quickstep/res/values-sw720dp-land/dimens.xml
index 4bc8bf3..02d1189 100644
--- a/quickstep/res/values-sw720dp-land/dimens.xml
+++ b/quickstep/res/values-sw720dp-land/dimens.xml
@@ -17,7 +17,4 @@
<resources>
<!-- Overview actions -->
<dimen name="overview_actions_top_margin">20dp</dimen>
-
- <!-- All Set page-->
- <dimen name="allset_page_margin_bottom">24dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index a84b939..585f01e 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -35,7 +35,6 @@
<dimen name="overview_grid_side_margin">64dp</dimen>
<!-- All Set page-->
- <dimen name="allset_page_margin_bottom">0dp</dimen>
<dimen name="allset_page_allset_text_size">42sp</dimen>
<dimen name="allset_page_swipe_up_text_size">16sp</dimen>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 431ae3c..77c3c37 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"பயிற்சி <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"அனைத்தையும் அமைத்துவிட்டீர்கள்!"</string>
<string name="allset_hint" msgid="2384632994739392447">"முகப்புத் திரைக்குச் செல்ல மேல்நோக்கி ஸ்வைப் செய்யுங்கள்"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"மொபைலைப் பயன்படுத்தத் தயாராகிவிட்டீர்கள்"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"உங்கள் டேப்லெட்டைப் பயன்படுத்தத் தயாராகிவிட்டீர்கள்"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"சிஸ்டம் வழிசெலுத்தல் அமைப்புகள்"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
<string name="action_split" msgid="2098009717623550676">"பிரி"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"ஸ்பிளிட் ஸ்கிரீனுக்கு மற்றொரு ஆப்ஸைத் தட்டவும்"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"திரைப் பிரிப்பு அம்சத்தை ஆப்ஸ் ஆதரிக்கவில்லை."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ஆப்ஸோ உங்கள் நிறுவனமோ இந்த செயலை அனுமதிப்பதில்லை"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"வழிகாட்டுதல் பயிற்சியைத் தவிர்க்கவா?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ஆப்ஸில் பிறகு இதைக் கண்டறியலாம்"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 7b6dedf..052ca5d 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ట్యుటోరియల్ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"అంతా సెట్ అయింది!"</string>
<string name="allset_hint" msgid="2384632994739392447">"మొదటి స్క్రీన్కు వెళ్లడానికి పైకి స్వైప్ చేయండి"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"మీరు మీ ఫోన్ను ఉపయోగించడానికి సిద్ధంగా ఉన్నారు"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"మీరు మీ టాబ్లెట్ను ఉపయోగించడానికి సిద్ధంగా ఉన్నారు"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"సిస్టమ్ నావిగేషన్ సెట్టింగ్లు"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్షాట్"</string>
<string name="action_split" msgid="2098009717623550676">"స్ప్లిట్ చేయండి"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"స్క్రీన్ విభజనను ఉపయోగించడానికి మరొక యాప్ నొక్కండి"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"యాప్లో స్ప్లిట్-స్క్రీన్ పని చేయదు."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్ను స్కిప్ చేయాలా?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> యాప్లో మీరు తర్వాత కనుగొనవచ్చు"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 4d5794b..13f0e12 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"บทแนะนำ <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"เรียบร้อยแล้ว"</string>
<string name="allset_hint" msgid="2384632994739392447">"ปัดขึ้นเพื่อไปที่หน้าแรก"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"คุณเริ่มใช้โทรศัพท์ได้แล้ว"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"คุณเริ่มใช้แท็บเล็ตได้แล้ว"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"การตั้งค่าการนำทางของระบบ"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
<string name="action_split" msgid="2098009717623550676">"แยก"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"แตะที่แอปอื่นเพื่อใช้แบ่งหน้าจอ"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"แอปไม่รองรับการแบ่งหน้าจอ"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"แอปหรือองค์กรของคุณไม่อนุญาตการดำเนินการนี้"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ข้ามบทแนะนำการนำทางไหม"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"คุณดูบทแนะนำนี้ได้ภายหลังในแอป \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 6699ed8..68b3902 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Tutorial <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Handa na ang lahat!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Mag-swipe pataas para pumunta sa Home"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Handa mo nang simulan ang paggamit sa iyong telepono"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Handa mo nang simulan ang paggamit sa iyong tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Mga setting ng navigation ng system"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Mag-tap ng ibang app para gamitin ang splitscreen"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Hindi sinusuportahan ng app ang split-screen."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkilos na ito"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Laktawan ang tutorial sa pag-navigate?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Makikita mo ito sa <xliff:g id="NAME">%1$s</xliff:g> app sa ibang pagkakataon"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 24e25ff..c7f7ac9 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Eğitim <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"İşlem tamam!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Ana ekrana gitmek için yukarı kaydırın"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Telefonunuzu kullanmaya hazırsınız"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Tabletinizi kullanmaya hazırsınız"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistem gezinme ayarları"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekran görüntüsü"</string>
<string name="action_split" msgid="2098009717623550676">"Böl"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Bölünmüş ekran için başka bir uygulamaya dokunun"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Uygulama bölünmüş ekranı desteklemiyor."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Uygulamanız veya kuruluşunuz bu işleme izin vermiyor"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Gezinme eğitimi atlansın mı?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bunu daha sonra <xliff:g id="NAME">%1$s</xliff:g> uygulamasında bulabilirsiniz"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 8dd65e2..173f637 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Навчальний посібник <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Готово."</string>
<string name="allset_hint" msgid="2384632994739392447">"Щоб перейти на головний екран, проведіть пальцем угору"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Тепер ви можете користуватися телефоном"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Тепер ви можете користуватися планшетом"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системні налаштування навігації"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Розділити"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Щоб розділити екран, виберіть ще один додаток"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Додаток не підтримує розділення екрана."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Ця дія заборонена додатком або адміністратором організації"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустити посібник із навігації?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Ви знайдете його пізніше в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 2d9a1e3..89e518b 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"ٹیوٹوریل <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"سب کچھ تیار ہے!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ہوم پر جانے کے لیے اوپر سوائپ کریں"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"آپ اپنا فون استعمال شروع کرنے کے لیے تیار ہیں"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"آپ اپنے ٹیبلیٹ کا استعمال شروع کرنے کے لیے تیار ہیں"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"سسٹم نیویگیشن کی ترتیبات"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
<string name="action_split" msgid="2098009717623550676">"اسپلٹ"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"اسپلٹ اسکرین کا استعمال کرنے کیلئے دوسری ایپ پر تھپتھپائیں"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"آپ اسے بعد میں <xliff:g id="NAME">%1$s</xliff:g> ایپ میں تلاش کر سکتے ہیں"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 9446325..56a76d5 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Darslik: <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Hammasi tayyor!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Boshiga qaytish uchun tepaga suring"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Telefoningiz xizmatga tayyor"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Planshetingiz xizmatga tayyor"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Tizim navigatsiya sozlamalari"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skrinshot"</string>
<string name="action_split" msgid="2098009717623550676">"Ajratish"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Ekranni ikkiga ajratish uchun boshqa ilovani bosing"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Bu ilovada ekranni ikkiga ajratish ishlamaydi."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu amal ilova yoki tashkilotingiz tomonidan taqiqlangan"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatsiya darsi yopilsinmi?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bu darslar <xliff:g id="NAME">%1$s</xliff:g> ilovasida chiqadi"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 55027ae..3b17966 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Hướng dẫn <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Đã hoàn tất!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Vuốt lên để chuyển đến Màn hình chính"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Vậy là bạn đã sẵn sàng sử dụng điện thoại của mình"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Bạn đã sẵn sàng sử dụng máy tính bảng"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Chế độ cài đặt di chuyển trên hệ thống"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
<string name="action_split" msgid="2098009717623550676">"Chia đôi màn hình"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Nhấn vào một ứng dụng khác để dùng màn hình chia đôi"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Ứng dụng hoặc tổ chức của bạn không cho phép thực hiện hành động này"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Bỏ qua phần hướng dẫn thao tác?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Bạn có thể tìm lại phần hướng dẫn này trong ứng dụng <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index debf23a..0ff369e 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"教程 <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"大功告成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑动即可转到主屏幕"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"您可以开始使用手机了"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"您可以开始使用平板电脑了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系统导航设置"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
<string name="action_split" msgid="2098009717623550676">"拆分"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"点按另一个应用即可使用分屏"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"应用不支持分屏。"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"该应用或您所在的单位不允许执行此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要跳过导航教程吗?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"您之后可以在“<xliff:g id="NAME">%1$s</xliff:g>”应用中找到此教程"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index c7a44e7..ff648df 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"教學課程 <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"設定完成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑動即可前往主畫面"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"您可以開始使用手機了"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"您可以開始使用平板電腦了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系統導覽設定"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"輕按其他應用程式以使用分割螢幕"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"應用程式不支援分割螢幕。"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"應用程式或您的機構不允許此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"您之後可以在「<xliff:g id="NAME">%1$s</xliff:g>」應用程式找到這些說明"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 15d5de5..23bee17 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"教學課程 <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"設定完成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑動即可前往主畫面"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"你可以開始使用手機了"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"你可以開始使用平板電腦了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系統操作機制設定"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"輕觸另一個應用程式即可使用分割畫面"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"這個應用程式不支援分割畫面。"</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"這個應用程式或貴機構不允許執行這個動作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"你之後可以在「<xliff:g id="NAME">%1$s</xliff:g>」應用程式找到這些說明"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 3db5836..46ba929 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -77,6 +77,8 @@
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Okokufundisa <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Konke kusethiwe!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swayiphela phezulu ukuze uye Ekhaya"</string>
+ <!-- no translation found for allset_button_hint (2395219947744706291) -->
+ <skip />
<string name="allset_description" msgid="6350320429953234580">"Usulungele ukuqala ukusebenzisa ifoni yakho"</string>
<string name="allset_description_tablet" msgid="7332070270570039247">"Usulungele ukuqala ukusebenzisa ithebulethi yakho"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Amasethingi wokuzulazula isistimu"</annotation></string>
@@ -84,7 +86,8 @@
<string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
<string name="action_split" msgid="2098009717623550676">"Hlukanisa"</string>
<string name="toast_split_select_app" msgid="5453865907322018352">"Thepha enye i-app ukuze usebenzise isikrini sokuhlukanisa"</string>
- <string name="toast_split_app_unsupported" msgid="3271526028981899666">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string>
+ <!-- no translation found for toast_split_app_unsupported (2360229567007828914) -->
+ <skip />
<string name="blocked_by_policy" msgid="2071401072261365546">"Lesi senzo asivunyelwanga uhlelo lokusebenza noma inhlangano yakho"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Yeqa isifundo sokuzulazula?"</string>
<string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Lokhu ungakuthola kamuva ku-app ye-<xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 6e3fd32..50f1236 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -202,7 +202,6 @@
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">40dp</dimen>
- <dimen name="allset_page_margin_bottom">0dp</dimen>
<dimen name="allset_page_allset_text_size">36sp</dimen>
<dimen name="allset_page_swipe_up_text_size">14sp</dimen>
@@ -290,11 +289,17 @@
<dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
<dimen name="transient_taskbar_stashed_size">32dp</dimen>
<dimen name="transient_taskbar_icon_spacing">10dp</dimen>
+ <!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
+ <dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
<!-- Taskbar swipe up thresholds -->
+ <dimen name="taskbar_nav_threshold">40dp</dimen>
<dimen name="taskbar_app_window_threshold">150dp</dimen>
<dimen name="taskbar_home_overview_threshold">225dp</dimen>
<dimen name="taskbar_catch_up_threshold">300dp</dimen>
- <dimen name="taskbar_nav_threshold">40dp</dimen>
+
+ <dimen name="taskbar_nav_threshold_v2">30dp</dimen>
+ <dimen name="taskbar_app_window_threshold_v2">100dp</dimen>
+ <dimen name="taskbar_home_overview_threshold_v2">200dp</dimen>
<!-- Taskbar 3 button spacing -->
<dimen name="taskbar_button_space_inbetween">24dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index c0d52a4..eabe079 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -187,10 +187,12 @@
<string name="allset_title">All set!</string>
<!-- Hint string at the bottom of "All Set" page [CHAR LIMIT=NONE] -->
<string name="allset_hint">Swipe up to go Home</string>
- <!-- Description of "All Set" page on phones [CHAR LIMIT=NONE] -->
- <string name="allset_description">You\u2019re ready to start using your phone</string>
- <!-- Description of "All Set" page on tablets [CHAR LIMIT=NONE] -->
- <string name="allset_description_tablet">You\u2019re ready to start using your tablet</string>
+ <!-- Hint string at the bottom of "All Set" page for button navigation [CHAR LIMIT=NONE] -->
+ <string name="allset_button_hint">Tap the home button to go to your home screen</string>
+ <!-- Description of "All Set" page on the user's device [CHAR LIMIT=NONE] -->
+ <string name="allset_description_generic">You\u2019re ready to start using your <xliff:g id="device" example="Pixel 6">%1$s</xliff:g></string>
+ <!-- A default device name to use in the description of the "All Set" page [CHAR LIMIT=NONE] -->
+ <string name="default_device_name">device</string>
<!-- String linking to navigation settings on "All Set" page [CHAR LIMIT=NONE] -->
<string name="allset_navigation_settings"><annotation id="link">System navigation settings</annotation></string>
@@ -204,7 +206,7 @@
<!-- Label for toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
<string name="toast_split_select_app">Tap another app to use splitscreen</string>
<!-- Label for toast when app selected for split isn't supported. [CHAR_LIMIT=50] -->
- <string name="toast_split_app_unsupported">App does not support split-screen.</string>
+ <string name="toast_split_app_unsupported">Choose another app to use split screen</string>
<!-- Message shown when an action is blocked by a policy enforced by the app or the organization managing the device. [CHAR_LIMIT=NONE] -->
<string name="blocked_by_policy">This action isn\'t allowed by the app or your organization</string>
@@ -222,6 +224,8 @@
<string name="accessibility_rotate_button">Rotate screen</string>
<!-- ******* Taskbar Edu ******* -->
+ <!-- Accessibility title for the taskbar education window. [CHAR_LIMIT=NONE] -->
+ <string name="taskbar_edu_a11y_title">Taskbar education</string>
<!-- Accessibility text spoken when the taskbar education panel appears [CHAR_LIMIT=NONE] -->
<string name="taskbar_edu_opened">Taskbar education appeared</string>
<!-- Accessibility text spoken when the taskbar education panel disappears [CHAR_LIMIT=NONE] -->
@@ -257,6 +261,10 @@
<string name="taskbar_button_notifications">Notifications</string>
<!-- Content description for quick settings button [CHAR_LIMIT=16] -->
<string name="taskbar_button_quick_settings">Quick Settings</string>
+ <!-- Accessibility title for the taskbar window. [CHAR_LIMIT=NONE] -->
+ <string name="taskbar_a11y_title">Taskbar</string>
+ <!-- Accessibility title for the taskbar window on phones. [CHAR_LIMIT=NONE] -->
+ <string name="taskbar_phone_a11y_title">Navigation bar</string>
<!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
<string name="move_drop_target_top_or_left">Move to top/left</string>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 868d38b..4f0fdf1 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -152,6 +152,8 @@
<item name="android:background">@drawable/bg_overview_clear_all_button</item>
<item name="android:minWidth">96dp</item>
<item name="android:minHeight">48dp</item>
+ <item name="android:paddingStart">12dp</item>
+ <item name="android:paddingEnd">12dp</item>
<item name="android:stateListAnimator">@null</item>
</style>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 1b47939..59dbd4b 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -194,6 +194,7 @@
public static final int SPLIT_DIVIDER_ANIM_DURATION = 100;
public static final int CONTENT_ALPHA_DURATION = 217;
+ public static final int TRANSIENT_TASKBAR_TRANSITION_DURATION = 417;
public static final int TASKBAR_TO_APP_DURATION = 600;
// TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation
// is solved.
@@ -1677,9 +1678,10 @@
mLauncher.getStateManager().moveToRestState();
}
+ RectF windowTargetBounds =
+ new RectF(getWindowTargetBounds(appTargets, getRotationChange(appTargets)));
Pair<RectFSpringAnim, AnimatorSet> pair = createWallpaperOpenAnimations(
- appTargets, wallpaperTargets, mFromUnlock,
- new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx),
+ appTargets, wallpaperTargets, mFromUnlock, windowTargetBounds,
QuickStepContract.getWindowCornerRadius(mLauncher));
mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 05b8167..0a2a9b3 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -305,7 +305,7 @@
* Sets or updates the predicted items only once the hotseat becomes hidden to the user
*/
private void applyPredictedItems(FixedContainerItems items) {
- mPredictedItems = items.items;
+ mPredictedItems = new ArrayList(items.items);
if (mPredictedItems.isEmpty()) {
HotseatRestoreHelper.restoreBackup(mLauncher);
}
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index bc3253f..e504141 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -30,12 +30,14 @@
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -59,7 +61,7 @@
Context context = app.getContext();
// TODO: remove this
- Utilities.getDevicePrefs(context).edit()
+ LauncherPrefs.getDevicePrefs(context).edit()
.putBoolean(LAST_PREDICTION_ENABLED_STATE, !mTargets.isEmpty()).apply();
Set<UserHandle> usersForChangedShortcuts =
@@ -68,7 +70,7 @@
.map(info -> info.user)
.collect(Collectors.toSet());
- FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId);
+ List<ItemInfo> items = new ArrayList<>(mTargets.size());
for (AppTarget target : mTargets) {
WorkspaceItemInfo itemInfo;
ShortcutInfo si = target.getShortcutInfo();
@@ -107,10 +109,11 @@
}
}
- itemInfo.container = fci.containerId;
- fci.items.add(itemInfo);
+ itemInfo.container = mPredictorState.containerId;
+ items.add(itemInfo);
}
+ FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId, items);
dataModel.extraItems.put(fci.containerId, fci);
bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index de0b14d..118cfc6 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -18,12 +18,12 @@
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.formatElapsedTime;
+import static com.android.launcher3.LauncherPrefs.getDevicePrefs;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.hybridhotseat.HotseatPredictionModel.convertDataModelToAppTargetBundle;
import static com.android.launcher3.model.PredictionHelper.getAppTargetFromItemInfo;
import static com.android.launcher3.model.PredictionHelper.wrapAppTargetWithItemLocation;
@@ -132,7 +132,8 @@
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
- new FixedContainerItems(mWidgetsRecommendationState.containerId));
+ new FixedContainerItems(mWidgetsRecommendationState.containerId,
+ new ArrayList<>()));
mActive = true;
}
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index 68ed682..fb2d0dc 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -18,8 +18,6 @@
import static android.content.ContentResolver.SCHEME_CONTENT;
-import static com.android.launcher3.Utilities.newContentObserver;
-
import android.annotation.TargetApi;
import android.app.RemoteAction;
import android.content.ContentProviderClient;
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 1beabf1..6160378 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -25,6 +25,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -91,10 +92,12 @@
if (servicePredictedItems.isEmpty()) {
servicePredictedItems.addAll(localFilteredWidgets);
}
+
+ List<ItemInfo> items = servicePredictedItems.stream()
+ .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION))
+ .collect(Collectors.toList());
FixedContainerItems fixedContainerItems =
- new FixedContainerItems(mPredictorState.containerId);
- servicePredictedItems.forEach(w -> fixedContainerItems.items.add(
- new PendingAddWidgetInfo(w.widgetInfo, CONTAINER_WIDGETS_PREDICTION)));
+ new FixedContainerItems(mPredictorState.containerId, items);
dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
bindExtraContainerItems(fixedContainerItems);
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 7c3281a..7cf8201 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -15,20 +15,29 @@
*/
package com.android.launcher3.popup;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.quickstep.util.SplitSelectStateController;
+import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.RecentsView;
public interface QuickstepSystemShortcut {
@@ -44,6 +53,10 @@
class SplitSelectSystemShortcut extends SystemShortcut<QuickstepLauncher> {
+ private final int mSplitPlaceholderSize;
+ private final int mSplitPlaceholderInset;
+
+ private final Rect mTempRect = new Rect();
private final SplitPositionOption mPosition;
public SplitSelectSystemShortcut(QuickstepLauncher launcher, ItemInfo itemInfo,
@@ -51,6 +64,11 @@
super(position.iconResId, position.textResId, launcher, itemInfo, originalView);
mPosition = position;
+
+ mSplitPlaceholderSize = launcher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_size);
+ mSplitPlaceholderInset = launcher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_inset);
}
@Override
@@ -72,11 +90,39 @@
return;
}
- RecentsView recentsView = mTarget.getOverviewPanel();
StatsLogManager.EventEnum splitEvent = getLogEventForPosition(mPosition.stagePosition);
- recentsView.initiateSplitSelect(
- new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent,
- mPosition, mItemInfo, splitEvent));
+ SplitSelectSource source = new SplitSelectSource(mOriginalView,
+ new BitmapDrawable(bitmap), intent, mPosition, mItemInfo, splitEvent);
+ if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ startSplitToHome(source);
+ } else {
+ RecentsView recentsView = mTarget.getOverviewPanel();
+ recentsView.initiateSplitSelect(source);
+ }
+ }
+
+ private void startSplitToHome(SplitSelectSource source) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ SplitSelectStateController controller = mTarget.getSplitSelectStateController();
+ controller.setInitialTaskSelect(source.intent, source.position.stagePosition,
+ source.itemInfo, source.splitEvent);
+
+ RecentsView recentsView = mTarget.getOverviewPanel();
+ recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
+ mSplitPlaceholderSize, mSplitPlaceholderInset, mTarget.getDeviceProfile(),
+ controller.getActiveSplitStagePosition(), mTempRect);
+
+ PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
+ RectF startingTaskRect = new RectF();
+ FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
+ source.view, null /* thumbnail */,
+ source.drawable, startingTaskRect);
+ floatingTaskView.setAlpha(1);
+ floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
+ controller.setFirstFloatingTaskView(floatingTaskView);
+ anim.buildAnim().start();
}
}
@@ -86,7 +132,7 @@
public final Drawable drawable;
public final Intent intent;
public final SplitPositionOption position;
- public final ItemInfo mItemInfo;
+ public final ItemInfo itemInfo;
public final StatsLogManager.EventEnum splitEvent;
public SplitSelectSource(View view, Drawable drawable, Intent intent,
@@ -96,7 +142,7 @@
this.drawable = drawable;
this.intent = intent;
this.position = position;
- this.mItemInfo = itemInfo;
+ this.itemInfo = itemInfo;
this.splitEvent = splitEvent;
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index f1e6747..df867cb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -21,6 +21,7 @@
import android.animation.Animator;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.fallback.RecentsState;
@@ -40,8 +41,7 @@
animateToRecentsState(toState);
// Handle tapping on live tile.
- RecentsView recentsView = mRecentsActivity.getOverviewPanel();
- recentsView.setTaskLaunchListener(toState == RecentsState.DEFAULT
+ getRecentsView().setTaskLaunchListener(toState == RecentsState.DEFAULT
? (() -> animateToRecentsState(RecentsState.BACKGROUND_APP)) : null);
}
};
@@ -70,12 +70,14 @@
* Currently this animation just force stashes the taskbar in Overview.
*/
public Animator createAnimToRecentsState(RecentsState toState, long duration) {
- boolean forceStashed = toState.hasOverviewActions();
+ boolean useStashedLauncherState = toState.hasOverviewActions();
+ boolean stashedLauncherState =
+ useStashedLauncherState && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
TaskbarStashController controller = mControllers.taskbarStashController;
// Set both FLAG_IN_STASHED_LAUNCHER_STATE and FLAG_IN_APP to ensure the state is respected.
// For all other states, just use the current stashed-in-app setting (e.g. if long clicked).
- controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, forceStashed);
- controller.updateStateForFlag(FLAG_IN_APP, !forceStashed);
+ controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, stashedLauncherState);
+ controller.updateStateForFlag(FLAG_IN_APP, !useStashedLauncherState);
return controller.applyStateWithoutStart(duration);
}
@@ -85,4 +87,9 @@
anim.start();
}
}
+
+ @Override
+ public RecentsView getRecentsView() {
+ return mRecentsActivity.getOverviewPanel();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 317f6a4..0945bf2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -17,6 +17,7 @@
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
+import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
@@ -26,7 +27,6 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
-import android.view.MotionEvent;
import android.view.TaskTransitionSpec;
import android.view.WindowManagerGlobal;
@@ -48,6 +48,7 @@
import com.android.launcher3.util.OnboardingPrefs;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
+import com.android.quickstep.views.RecentsView;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -157,9 +158,11 @@
isResumed,
fromInit,
/* startAnimation= */ true,
- !isResumed
- ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
- : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION);
+ DisplayController.isTransientTaskbar(mLauncher)
+ ? TRANSIENT_TASKBAR_TRANSITION_DURATION
+ : (!isResumed
+ ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
+ : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION));
}
@Nullable
@@ -193,16 +196,15 @@
*/
public Animator createAnimToLauncher(@NonNull LauncherState toState,
@NonNull RecentsAnimationCallbacks callbacks, long duration) {
- return mTaskbarLauncherStateController.createAnimToLauncher(toState, callbacks, duration);
- }
+ AnimatorSet set = new AnimatorSet();
+ Animator taskbarState = mTaskbarLauncherStateController
+ .createAnimToLauncher(toState, callbacks, duration);
+ long halfDuration = Math.round(duration * 0.5f);
+ Animator translation =
+ mControllers.taskbarTranslationController.createAnimToLauncher(halfDuration);
- /**
- * @param ev MotionEvent in screen coordinates.
- * @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
- */
- public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
- return mControllers.taskbarViewController.isEventOverAnyItem(ev)
- || mControllers.navbarButtonsViewController.isEventOverAnyItem(ev);
+ set.playTogether(taskbarState, translation);
+ return set;
}
public boolean isDraggingItem() {
@@ -393,4 +395,9 @@
mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
}
+
+ @Override
+ public RecentsView getRecentsView() {
+ return mLauncher.getOverviewPanel();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 12dbcb3..af46df4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -26,10 +26,11 @@
import android.view.ViewOutlineProvider;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
@@ -66,6 +67,7 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private int mTaskbarSize;
// The bounds we want to clip to in the settled state when showing the stashed handle.
private final Rect mStashedHandleBounds = new Rect();
@@ -79,7 +81,7 @@
public StashedHandleViewController(TaskbarActivityContext activity,
StashedHandleView stashedHandleView) {
mActivity = activity;
- mPrefs = Utilities.getPrefs(mActivity);
+ mPrefs = LauncherPrefs.getPrefs(mActivity);
mStashedHandleView = stashedHandleView;
mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, NUM_ALPHA_CHANNELS);
mTaskbarStashedHandleAlpha.setUpdateVisibility(true);
@@ -96,15 +98,18 @@
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
Resources resources = mActivity.getResources();
if (isPhoneGestureNavMode(mActivity.getDeviceProfile())) {
- mStashedHandleView.getLayoutParams().height =
- resources.getDimensionPixelSize(R.dimen.taskbar_size);
+ mTaskbarSize = resources.getDimensionPixelSize(R.dimen.taskbar_size);
mStashedHandleWidth =
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
} else {
- mStashedHandleView.getLayoutParams().height = deviceProfile.taskbarSize;
+ mTaskbarSize = deviceProfile.taskbarSize;
mStashedHandleWidth = resources
.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
}
+ int taskbarBottomMargin = DisplayController.isTransientTaskbar(mActivity)
+ ? resources.getDimensionPixelSize(R.dimen.transient_taskbar_margin)
+ : 0;
+ mStashedHandleView.getLayoutParams().height = mTaskbarSize + taskbarBottomMargin;
mTaskbarStashedHandleAlpha.get(ALPHA_INDEX_STASHED).setValue(
isPhoneGestureNavMode(deviceProfile) ? 1 : 0);
@@ -181,9 +186,17 @@
* morphs into the size of where the taskbar icons will be.
*/
public Animator createRevealAnimToIsStashed(boolean isStashed) {
+ Rect visualBounds = new Rect(mControllers.taskbarViewController.getIconLayoutBounds());
+
+ if (DisplayController.isTransientTaskbar(mActivity)) {
+ // Account for the full visual height of the transient taskbar.
+ int heightDiff = (mTaskbarSize - visualBounds.height()) / 2;
+ visualBounds.top -= heightDiff;
+ visualBounds.bottom += heightDiff;
+ }
+
final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
- mStashedHandleRadius, mStashedHandleRadius,
- mControllers.taskbarViewController.getIconLayoutBounds(), mStashedHandleBounds);
+ mStashedHandleRadius, mStashedHandleRadius, visualBounds, mStashedHandleBounds);
boolean isReversed = !isStashed;
boolean changingDirection = mWasLastRevealAnimReversed != isReversed;
@@ -220,6 +233,13 @@
}
/**
+ * Sets the translation of the stashed handle during the swipe up gesture.
+ */
+ protected void setTranslationYForSwipe(float transY) {
+ mStashedHandleView.setTranslationY(transY);
+ }
+
+ /**
* Should be called when the home button is disabled, so we can hide this handle as well.
*/
public void setIsHomeButtonDisabled(boolean homeDisabled) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index fad9ff4..13ca58d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
@@ -78,6 +79,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag;
+import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.launcher3.testing.TestLogging;
@@ -90,6 +92,7 @@
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -132,6 +135,7 @@
private final boolean mIsUserSetupComplete;
private final boolean mIsNavBarForceVisible;
private final boolean mIsNavBarKidsMode;
+
private boolean mIsDestroyed = false;
// The flag to know if the window is excluded from magnification region computation.
private boolean mIsExcludeFromMagnificationRegion = false;
@@ -223,6 +227,7 @@
new TaskbarAllAppsController(),
new TaskbarInsetsController(this),
new VoiceInteractionWindowController(this),
+ new TaskbarTranslationController(this),
isDesktopMode
? new DesktopTaskbarRecentAppsController(this)
: TaskbarRecentAppsController.DEFAULT);
@@ -304,7 +309,8 @@
int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
- if (DisplayController.isTransientTaskbar(this)) {
+ if (DisplayController.isTransientTaskbar(this)
+ && !IS_RUNNING_IN_TEST_HARNESS) {
windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
}
@@ -326,6 +332,10 @@
windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
windowLayoutParams.privateFlags =
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ windowLayoutParams.accessibilityTitle = getString(
+ TaskbarManager.isPhoneMode(mDeviceProfile)
+ ? R.string.taskbar_phone_a11y_title
+ : R.string.taskbar_a11y_title);
return windowLayoutParams;
}
@@ -752,45 +762,64 @@
});
} else if (tag instanceof WorkspaceItemInfo) {
WorkspaceItemInfo info = (WorkspaceItemInfo) tag;
- if (info.isDisabled()) {
- ItemClickHandler.handleDisabledItemClicked(info, this);
- } else {
- Intent intent = new Intent(info.getIntent())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
- Toast.makeText(this, R.string.safemode_shortcut_error,
- Toast.LENGTH_SHORT).show();
- } else if (info.isPromise()) {
- TestLogging.recordEvent(
- TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
- intent = new PackageManagerHelper(this)
- .getMarketIntent(info.getTargetPackage())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ if (!info.isDisabled() || !ItemClickHandler.handleDisabledItemClicked(info, this)) {
+ TaskbarUIController taskbarUIController = mControllers.uiController;
+ RecentsView recents = taskbarUIController.getRecentsView();
+ if (recents != null
+ && taskbarUIController.getRecentsView().isSplitSelectionActive()) {
+ // If we are selecting a second app for split, launch the split tasks
+ taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
+ } else {
+ // Else launch the selected task
+ Intent intent = new Intent(info.getIntent())
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
+ Toast.makeText(this, R.string.safemode_shortcut_error,
+ Toast.LENGTH_SHORT).show();
+ } else if (info.isPromise()) {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
+ intent = new PackageManagerHelper(this)
+ .getMarketIntent(info.getTargetPackage())
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
- } else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- TestLogging.recordEvent(
- TestProtocol.SEQUENCE_MAIN, "start: taskbarDeepShortcut");
- String id = info.getDeepShortcutId();
- String packageName = intent.getPackage();
- getSystemService(LauncherApps.class)
- .startShortcut(packageName, id, null, null, info.user);
- } else {
- startItemInfoActivity(info);
+ } else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN, "start: taskbarDeepShortcut");
+ String id = info.getDeepShortcutId();
+ String packageName = intent.getPackage();
+ getSystemService(LauncherApps.class)
+ .startShortcut(packageName, id, null, null, info.user);
+ } else {
+ startItemInfoActivity(info);
+ }
+
+ mControllers.uiController.onTaskbarIconLaunched(info);
+ } catch (NullPointerException
+ | ActivityNotFoundException
+ | SecurityException e) {
+ Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
+ .show();
+ Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
}
-
- mControllers.uiController.onTaskbarIconLaunched(info);
- mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
- } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
- Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
- .show();
- Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
}
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
}
} else if (tag instanceof AppInfo) {
- startItemInfoActivity((AppInfo) tag);
- mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag);
+ AppInfo info = (AppInfo) tag;
+ TaskbarUIController taskbarUIController = mControllers.uiController;
+ RecentsView recents = taskbarUIController.getRecentsView();
+ if (recents != null
+ && taskbarUIController.getRecentsView().isSplitSelectionActive()) {
+ // If we are selecting a second app for split, launch the split tasks
+ taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
+ } else {
+ // Else launch the selected task
+ startItemInfoActivity((AppInfo) tag);
+ mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag);
+ }
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
} else {
Log.e(TAG, "Unknown type clicked: " + tag);
@@ -834,6 +863,20 @@
}
/**
+ * Called to start the taskbar translation spring to its settled translation (0).
+ */
+ public void startTranslationSpring() {
+ mControllers.taskbarTranslationController.startSpring();
+ }
+
+ /**
+ * Returns a callback to help monitor the swipe gesture.
+ */
+ public TransitionCallback getTranslationCallbacks() {
+ return mControllers.taskbarTranslationController.getTransitionCallback();
+ }
+
+ /**
* Called when a transient Autohide flag suspend status changes.
*/
public void onTransientAutohideSuspendFlagChanged(boolean isSuspended) {
@@ -858,12 +901,25 @@
}
/**
+ * Enables the auto timeout for taskbar stashing. This method should only be used for taskbar
+ * testing.
+ */
+ @VisibleForTesting
+ public void enableBlockingTimeoutDuringTests(boolean enableBlockingTimeout) {
+ mControllers.taskbarStashController.enableBlockingTimeoutDuringTests(enableBlockingTimeout);
+ }
+
+ /**
* Unstashes the Taskbar if it is stashed. This method should only be used to unstash the
* taskbar at the end of a test.
*/
@VisibleForTesting
public void unstashTaskbarIfStashed() {
- mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
+ if (DisplayController.isTransientTaskbar(this)) {
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
+ } else {
+ mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
+ }
}
protected boolean isUserSetupComplete() {
@@ -904,12 +960,13 @@
}
mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
- if (!FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
+ View allAppsButton = mControllers.taskbarViewController.getAllAppsButtonView();
+ if (allAppsButton != null && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
ValueAnimator alphaOverride = ValueAnimator.ofFloat(0, 1);
alphaOverride.setDuration(duration);
alphaOverride.addUpdateListener(a -> {
// Override the alpha updates in the icon alignment animation.
- mControllers.taskbarViewController.getAllAppsButtonView().setAlpha(0);
+ allAppsButton.setAlpha(0);
});
fullAnimation.play(alphaOverride);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index abd467d..ff7e8e9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -34,6 +34,7 @@
val paint: Paint = Paint()
var backgroundHeight = context.deviceProfile.taskbarSize.toFloat()
+ var translationYForSwipe = 0f
private var maxBackgroundHeight = context.deviceProfile.taskbarSize.toFloat()
private val transientBackgroundBounds = context.transientTaskbarBounds
@@ -44,8 +45,12 @@
private var keyShadowDistance = 0f
private var bottomMargin = 0
- private val leftCornerRadius = context.leftCornerRadius.toFloat()
- private val rightCornerRadius = context.rightCornerRadius.toFloat()
+ private val fullLeftCornerRadius = context.leftCornerRadius.toFloat()
+ private val fullRightCornerRadius = context.rightCornerRadius.toFloat()
+ private var leftCornerRadius = fullLeftCornerRadius
+ private var rightCornerRadius = fullRightCornerRadius
+ private val square: Path = Path()
+ private val circle: Path = Path()
private val invertedLeftCornerPath: Path = Path()
private val invertedRightCornerPath: Path = Path()
@@ -63,13 +68,29 @@
keyShadowDistance = res.getDimension(R.dimen.transient_taskbar_key_shadow_distance)
}
+ setCornerRoundness(DEFAULT_ROUNDNESS)
+ }
+
+ /**
+ * Sets the roundness of the round corner above Taskbar. No effect on transient Taskkbar.
+ * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
+ */
+ fun setCornerRoundness(cornerRoundness: Float) {
+ if (isTransientTaskbar && !transientBackgroundBounds.isEmpty) {
+ return
+ }
+
+ leftCornerRadius = fullLeftCornerRadius * cornerRoundness
+ rightCornerRadius = fullRightCornerRadius * cornerRoundness
+
// Create the paths for the inverted rounded corners above the taskbar. Start with a filled
// square, and then subtract out a circle from the appropriate corner.
- val square = Path()
+ square.reset()
square.addRect(0f, 0f, leftCornerRadius, leftCornerRadius, Path.Direction.CW)
- val circle = Path()
+ circle.reset()
circle.addCircle(leftCornerRadius, 0f, leftCornerRadius, Path.Direction.CW)
invertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE)
+
square.reset()
square.addRect(0f, 0f, rightCornerRadius, rightCornerRadius, Path.Direction.CW)
circle.reset()
@@ -94,11 +115,13 @@
canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
canvas.drawPath(invertedRightCornerPath, paint)
} else {
+ // Approximates the stash/unstash animation to transform the background.
val scaleFactor = backgroundHeight / maxBackgroundHeight
val width = transientBackgroundBounds.width()
val widthScale = mapToRange(scaleFactor, 0f, 1f, 0.4f, 1f, Interpolators.LINEAR)
val newWidth = widthScale * width
val delta = width - newWidth
+ canvas.translate(0f, bottomMargin * ((1f - scaleFactor) / 2f))
// Draw shadow.
val shadowAlpha = mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, 25f,
@@ -112,13 +135,17 @@
canvas.drawRoundRect(
transientBackgroundBounds.left + (delta / 2f),
- 0f,
+ translationYForSwipe,
transientBackgroundBounds.right - (delta / 2f),
- backgroundHeight,
+ backgroundHeight + translationYForSwipe,
radius, radius, paint
)
}
canvas.restore()
}
+
+ companion object {
+ const val DEFAULT_ROUNDNESS = 1f
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 9c2d21e..0328df9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -23,6 +23,7 @@
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
+import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.rotation.RotationButtonController;
import java.io.PrintWriter;
@@ -55,9 +56,11 @@
public final TaskbarInsetsController taskbarInsetsController;
public final VoiceInteractionWindowController voiceInteractionWindowController;
public final TaskbarRecentAppsController taskbarRecentAppsController;
+ public final TaskbarTranslationController taskbarTranslationController;
public final TaskbarOverlayController taskbarOverlayController;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
+ @Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
/** Do not store this controller, as it may change at runtime. */
@NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
@@ -67,6 +70,9 @@
@Nullable private TaskbarSharedState mSharedState = null;
+ // Roundness property for round corner above taskbar .
+ private final AnimatedFloat mCornerRoundness = new AnimatedFloat(this::updateCornerRoundness);
+
public TaskbarControllers(TaskbarActivityContext taskbarActivityContext,
TaskbarDragController taskbarDragController,
TaskbarNavButtonController navButtonController,
@@ -87,6 +93,7 @@
TaskbarAllAppsController taskbarAllAppsController,
TaskbarInsetsController taskbarInsetsController,
VoiceInteractionWindowController voiceInteractionWindowController,
+ TaskbarTranslationController taskbarTranslationController,
TaskbarRecentAppsController taskbarRecentAppsController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
@@ -108,6 +115,7 @@
this.taskbarAllAppsController = taskbarAllAppsController;
this.taskbarInsetsController = taskbarInsetsController;
this.voiceInteractionWindowController = voiceInteractionWindowController;
+ this.taskbarTranslationController = taskbarTranslationController;
this.taskbarRecentAppsController = taskbarRecentAppsController;
}
@@ -139,6 +147,7 @@
taskbarInsetsController.init(this);
voiceInteractionWindowController.init(this);
taskbarRecentAppsController.init(this);
+ taskbarTranslationController.init(this);
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -146,8 +155,13 @@
taskbarUnfoldAnimationController, taskbarKeyguardController,
stashedHandleViewController, taskbarStashController, taskbarEduController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
+ voiceInteractionWindowController, taskbarTranslationController
+ };
+ mBackgroundRendererControllers = new BackgroundRendererController[] {
+ taskbarDragLayerController, taskbarScrimViewController,
voiceInteractionWindowController
};
+ mCornerRoundness.updateValue(TaskbarBackgroundRenderer.DEFAULT_ROUNDNESS);
mAreAllControllersInitialized = true;
for (Runnable postInitCallback : mPostInitCallbacks) {
@@ -164,6 +178,7 @@
public void onConfigurationChanged(@Config int configChanges) {
navbarButtonsViewController.onConfigurationChanged(configChanges);
+ taskbarDragLayerController.onConfigurationChanged();
}
/**
@@ -191,6 +206,7 @@
taskbarRecentAppsController.onDestroy();
mControllersToLog = null;
+ mBackgroundRendererControllers = null;
}
/**
@@ -224,6 +240,23 @@
rotationButtonController.dumpLogs(prefix + "\t", pw);
}
+ /**
+ * Returns a float property that animates roundness of the round corner above Taskbar.
+ */
+ public AnimatedFloat getTaskbarCornerRoundness() {
+ return mCornerRoundness;
+ }
+
+ private void updateCornerRoundness() {
+ if (mBackgroundRendererControllers == null) {
+ return;
+ }
+
+ for (BackgroundRendererController controller : mBackgroundRendererControllers) {
+ controller.setCornerRoundness(mCornerRoundness.value);
+ }
+ }
+
@VisibleForTesting
TaskbarActivityContext getTaskbarActivityContext() {
// Used to mock
@@ -233,4 +266,12 @@
protected interface LoggableTaskbarController {
void dumpLogs(String prefix, PrintWriter pw);
}
+
+ protected interface BackgroundRendererController {
+ /**
+ * Sets the roundness of the round corner above Taskbar.
+ * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
+ */
+ void setCornerRoundness(float cornerRoundness);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index d7bb16e..d1fea7b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
@@ -206,8 +207,13 @@
if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()
&& !shouldStartDrag(0)) {
- // Immediately close the popup menu.
- mDragView.setOnAnimationEndCallback(() -> callOnDragStart());
+ mDragView.setOnAnimationEndCallback(() -> {
+ // Drag might be cancelled during the DragView animation, so check
+ // mIsPreDrag again.
+ if (mIsInPreDrag) {
+ callOnDragStart();
+ }
+ });
}
}
@@ -301,7 +307,15 @@
protected void callOnDragStart() {
super.callOnDragStart();
// Pre-drag has ended, start the global system drag.
- AbstractFloatingView.closeAllOpenViews(mActivity);
+ if (mDisallowGlobalDrag) {
+ AbstractFloatingView.closeAllOpenViewsExcept(mActivity, TYPE_TASKBAR_ALL_APPS);
+ } else {
+ // stash the transient taskbar
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
+
+ AbstractFloatingView.closeAllOpenViews(mActivity);
+ }
+
startSystemDrag((BubbleTextView) mDragObject.originalView);
}
@@ -407,9 +421,14 @@
if (dragEvent.getResult()) {
maybeOnDragEnd();
} else {
+ // un-stash the transient taskbar in case drag and drop was canceled
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
+
// This will take care of calling maybeOnDragEnd() after the animation
animateGlobalDragViewToOriginalPosition(btv, dragEvent);
}
+ mActivity.getDragLayer().setOnDragListener(null);
+
return true;
}
return false;
@@ -536,10 +555,15 @@
private View findTaskbarTargetForIconView(@NonNull View iconView) {
Object tag = iconView.getTag();
+ TaskbarViewController taskbarViewController = mControllers.taskbarViewController;
+
if (tag instanceof ItemInfo) {
ItemInfo item = (ItemInfo) tag;
- TaskbarViewController taskbarViewController = mControllers.taskbarViewController;
if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) {
+ if (mDisallowGlobalDrag) {
+ // We're dragging in taskbarAllApps, we don't have folders or shortcuts
+ return iconView;
+ }
// Since all apps closes when the drag starts, target the all apps button instead.
return taskbarViewController.getAllAppsButtonView();
} else if (item.container >= 0) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 7c9a13c..d0059f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -116,9 +116,17 @@
}
@Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mControllerCallbacks != null) {
+ mControllerCallbacks.tryStashBasedOnMotionEvent(ev);
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mControllerCallbacks != null && ev.getAction() == MotionEvent.ACTION_OUTSIDE) {
- mControllerCallbacks.onActionOutsideEvent();
+ if (mControllerCallbacks != null) {
+ mControllerCallbacks.tryStashBasedOnMotionEvent(ev);
}
return super.onTouchEvent(ev);
}
@@ -158,6 +166,23 @@
invalidate();
}
+ /**
+ * Sets the roundness of the round corner above Taskbar.
+ * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
+ */
+ protected void setCornerRoundness(float cornerRoundness) {
+ mBackgroundRenderer.setCornerRoundness(cornerRoundness);
+ invalidate();
+ }
+
+ /*
+ * Sets the translation of the background during the swipe up gesture.
+ */
+ protected void setBackgroundTranslationYForSwipe(float translationY) {
+ mBackgroundRenderer.setTranslationYForSwipe(translationY);
+ invalidate();
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 13ecf81..e54fc00 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -18,10 +18,12 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.DimensionUtils;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
@@ -32,11 +34,13 @@
/**
* Handles properties/data collection, then passes the results to TaskbarDragLayer to render.
*/
-public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController {
+public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController,
+ TaskbarControllers.BackgroundRendererController {
private final TaskbarActivityContext mActivity;
private final TaskbarDragLayer mTaskbarDragLayer;
private final int mFolderMargin;
+ private float mGestureHeightYThreshold;
// Alpha properties for taskbar background.
private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
@@ -63,6 +67,7 @@
mTaskbarDragLayer = taskbarDragLayer;
final Resources resources = mTaskbarDragLayer.getResources();
mFolderMargin = resources.getDimensionPixelSize(R.dimen.taskbar_folder_margin);
+ updateGestureHeight();
}
public void init(TaskbarControllers controllers) {
@@ -122,6 +127,19 @@
return mBgOffset;
}
+ private void updateGestureHeight() {
+ int gestureHeight = ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+ mActivity.getResources());
+ mGestureHeightYThreshold = mActivity.getDeviceProfile().heightPx - gestureHeight;
+ }
+
+ /**
+ * Make updates when configuration changes.
+ */
+ public void onConfigurationChanged() {
+ updateGestureHeight();
+ }
+
private void updateBackgroundAlpha() {
final float bgNavbar = mBgNavbar.value;
final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value
@@ -132,12 +150,24 @@
updateNavBarDarkIntensityMultiplier();
}
+ /**
+ * Sets the translation of the background during the swipe up gesture.
+ */
+ public void setTranslationYForSwipe(float transY) {
+ mTaskbarDragLayer.setBackgroundTranslationYForSwipe(transY);
+ }
+
private void updateBackgroundOffset() {
mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
updateNavBarDarkIntensityMultiplier();
}
+ @Override
+ public void setCornerRoundness(float cornerRoundness) {
+ mTaskbarDragLayer.setCornerRoundness(cornerRoundness);
+ }
+
private void updateNavBarDarkIntensityMultiplier() {
// Zero out the app-requested dark intensity when we're drawing our own background.
float effectiveBgAlpha = mLastSetBackgroundAlpha * (1 - mBgOffset.value);
@@ -158,6 +188,8 @@
*/
public class TaskbarDragLayerCallbacks {
+ private final int[] mTempOutLocation = new int[2];
+
/**
* Called to update the touchable insets.
* @see ViewTreeObserver.InternalInsetsInfo#setTouchableInsets(int)
@@ -167,9 +199,9 @@
}
/**
- * Called whenever TaskbarDragLayer receives an ACTION_OUTSIDE event.
+ * Listens to TaskbarDragLayer touch events and responds accordingly.
*/
- public void onActionOutsideEvent() {
+ public void tryStashBasedOnMotionEvent(MotionEvent ev) {
if (!DisplayController.isTransientTaskbar(mActivity)) {
return;
}
@@ -177,7 +209,24 @@
return;
}
- mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
+ boolean stashTaskbar = false;
+
+ MotionEvent screenCoordinates = MotionEvent.obtain(ev);
+ if (ev.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ stashTaskbar = true;
+ } else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mTaskbarDragLayer.getLocationOnScreen(mTempOutLocation);
+ screenCoordinates.offsetLocation(mTempOutLocation[0], mTempOutLocation[1]);
+
+ if (!mControllers.taskbarViewController.isEventOverAnyItem(screenCoordinates)
+ && screenCoordinates.getY() < mGestureHeightYThreshold) {
+ stashTaskbar = true;
+ }
+ }
+
+ if (stashTaskbar) {
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 723e214..d790b4b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -73,6 +73,7 @@
private TaskbarControllers mControllers;
private AnimatedFloat mTaskbarBackgroundAlpha;
+ private AnimatedFloat mTaskbarCornerRoundness;
private MultiProperty mIconAlphaForHome;
private QuickstepLauncher mLauncher;
@@ -118,10 +119,13 @@
mLauncherState = finalState;
updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false);
applyState();
- mControllers.taskbarDragController.setDisallowGlobalDrag(
- (finalState instanceof OverviewState));
- mControllers.taskbarDragController.setDisallowLongClick(
- finalState == LauncherState.OVERVIEW_SPLIT_SELECT);
+ boolean disallowGlobalDrag = finalState instanceof OverviewState;
+ boolean disallowLongClick = finalState == LauncherState.OVERVIEW_SPLIT_SELECT;
+ mControllers.taskbarDragController.setDisallowGlobalDrag(disallowGlobalDrag);
+ mControllers.taskbarDragController.setDisallowLongClick(disallowLongClick);
+ mControllers.taskbarAllAppsController.setDisallowGlobalDrag(disallowGlobalDrag);
+ mControllers.taskbarAllAppsController.setDisallowLongClick(disallowLongClick);
+ mControllers.taskbarPopupController.setHideSplitOptions(disallowGlobalDrag);
}
};
@@ -133,6 +137,7 @@
mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
.getTaskbarBackgroundAlpha();
+ mTaskbarCornerRoundness = mControllers.getTaskbarCornerRoundness();
mIconAlphaForHome = mControllers.taskbarViewController
.getTaskbarIconAlpha().get(ALPHA_INDEX_HOME);
@@ -181,6 +186,10 @@
animatorSet.play(stashController.applyStateWithoutStart(duration));
animatorSet.play(applyState(duration, false));
+ if (mTaskBarRecentsAnimationListener != null) {
+ mTaskBarRecentsAnimationListener.endGestureStateOverride(
+ !mLauncher.isInState(LauncherState.OVERVIEW));
+ }
mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
callbacks.addListener(mTaskBarRecentsAnimationListener);
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(() ->
@@ -316,6 +325,19 @@
.setDuration(duration));
}
+ float cornerRoundness = goingToLauncher ? 0 : 1;
+ // Don't animate if corner roundness has reached desired value.
+ if (mTaskbarCornerRoundness.isAnimating()
+ || mTaskbarCornerRoundness.value != cornerRoundness) {
+ mTaskbarCornerRoundness.cancelAnimation();
+ if (DEBUG) {
+ Log.d(TAG, "onStateChangeApplied - taskbarCornerRoundness - "
+ + mTaskbarCornerRoundness.value
+ + " -> " + cornerRoundness + ": " + duration);
+ }
+ animatorSet.play(mTaskbarCornerRoundness.animateToValue(cornerRoundness));
+ }
+
if (mIconAlignment.isAnimatingToValue(toAlignment)
|| mIconAlignment.isSettledOnValue(toAlignment)) {
// Already at desired value, but make sure we run the callback at the end.
@@ -333,6 +355,7 @@
}
animatorSet.play(iconAlignAnim);
}
+
animatorSet.setInterpolator(EMPHASIZED);
if (start) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index da6dab1..9b27c9d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -75,6 +75,7 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private boolean mHideSplitOptions;
public TaskbarPopupController(TaskbarActivityContext context) {
mContext = context;
@@ -100,6 +101,10 @@
mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
}
+ public void setHideSplitOptions(boolean hideSplitOptions) {
+ mHideSplitOptions = hideSplitOptions;
+ }
+
private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
final PackageUserKey packageUserKey = new PackageUserKey(null, null);
Predicate<ItemInfo> matcher = info -> !packageUserKey.updateFromItemInfo(info)
@@ -186,11 +191,16 @@
// TODO(b/227800345): Add "Split bottom" option when tablet is in portrait mode.
private Stream<SystemShortcut.Factory> getSystemShortcuts() {
// concat a Stream of split options with a Stream of APP_INFO
+ Stream<SystemShortcut.Factory> appInfo = Stream.of(APP_INFO);
+ if (mHideSplitOptions) {
+ return appInfo;
+ }
+
return Stream.concat(
Utilities.getSplitPositionOptions(mContext.getDeviceProfile())
.stream()
.map(this::createSplitShortcutFactory),
- Stream.of(APP_INFO)
+ appInfo
);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
index 1d3757f..cdc6d59 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -69,4 +69,13 @@
mRenderer.getPaint().setAlpha((int) (alpha * 255));
invalidate();
}
+
+ /**
+ * Sets the roundness of the round corner above Taskbar.
+ * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
+ */
+ protected void setCornerRoundness(float cornerRoundness) {
+ mRenderer.setCornerRoundness(cornerRoundness);
+ invalidate();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index c3b0f57..ce191b7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -30,7 +30,8 @@
/**
* Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
*/
-public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController {
+public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController,
+ TaskbarControllers.BackgroundRendererController {
private static final float SCRIM_ALPHA = 0.6f;
@@ -95,6 +96,11 @@
}
@Override
+ public void setCornerRoundness(float cornerRoundness) {
+ mScrimView.setCornerRoundness(cornerRoundness);
+ }
+
+ @Override
public void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarScrimViewController:");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 72ae1d1..6274ec0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -37,10 +37,12 @@
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.launcher3.Alarm;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
@@ -169,6 +171,7 @@
private boolean mEnableManualStashingDuringTests = false;
private final Alarm mTimeoutAlarm = new Alarm();
+ private boolean mEnableBlockingTimeoutDuringTests = false;
// Evaluate whether the handle should be stashed
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
@@ -185,7 +188,7 @@
public TaskbarStashController(TaskbarActivityContext activity) {
mActivity = activity;
- mPrefs = Utilities.getPrefs(mActivity);
+ mPrefs = LauncherPrefs.getPrefs(mActivity);
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
if (isPhoneMode()) {
// DeviceProfile's taskbar vars aren't initialized w/ the flag off
@@ -267,11 +270,21 @@
* Enables support for manual stashing. This should only be used to add this functionality
* to Launcher specific tests.
*/
+ @VisibleForTesting
public void enableManualStashingDuringTests(boolean enableManualStashing) {
mEnableManualStashingDuringTests = enableManualStashing;
}
/**
+ * Enables the auto timeout for taskbar stashing. This method should only be used for taskbar
+ * testing.
+ */
+ @VisibleForTesting
+ public void enableBlockingTimeoutDuringTests(boolean enableBlockingTimeout) {
+ mEnableBlockingTimeoutDuringTests = enableBlockingTimeout;
+ }
+
+ /**
* Sets the flag indicating setup UI is visible
*/
protected void setSetupUIVisible(boolean isVisible) {
@@ -758,8 +771,12 @@
* * in small screen AND
* * 3 button nav AND
* * landscape (or seascape)
+ * We do not stash if taskbar is transient
*/
private boolean shouldStashForIme() {
+ if (DisplayController.isTransientTaskbar(mActivity)) {
+ return false;
+ }
return (mIsImeShowing || mIsImeSwitcherShowing) &&
!(isPhoneMode() && mActivity.isThreeButtonNav()
&& mActivity.getDeviceProfile().isLandscape);
@@ -846,12 +863,12 @@
* Attempts to start timer to auto hide the taskbar based on time.
*/
public void tryStartTaskbarTimeout() {
- if (!DisplayController.isTransientTaskbar(mActivity)) {
+ if (!DisplayController.isTransientTaskbar(mActivity)
+ || mIsStashed
+ || mEnableBlockingTimeoutDuringTests) {
return;
}
- if (mIsStashed) {
- return;
- }
+
cancelTimeoutIfExists();
mTimeoutAlarm.setOnAlarmListener(this::onTaskbarTimeout);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
new file mode 100644
index 0000000..1a7ec13
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.quickstep.AnimatedFloat.VALUE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.AnimatedFloat;
+
+import java.io.PrintWriter;
+
+/**
+ * Class responsible for translating the transient taskbar UI during a swipe gesture.
+ *
+ * The translation is controlled, in priority order:
+ * - animation to home
+ * - a spring animation
+ * - controlled by user
+ *
+ * The spring animation will play start once the user lets go or when user pauses to go to overview.
+ * When the user goes home, the stash animation will play.
+ */
+public class TaskbarTranslationController implements TaskbarControllers.LoggableTaskbarController {
+
+ private final TaskbarActivityContext mContext;
+ private TaskbarControllers mControllers;
+ private final AnimatedFloat mTranslationYForSwipe = new AnimatedFloat(
+ this::updateTranslationYForSwipe);
+
+ private boolean mHasSprungOnceThisGesture;
+ private @Nullable ValueAnimator mSpringBounce;
+ private boolean mGestureEnded;
+ private boolean mAnimationToHomeRunning;
+
+ private final boolean mIsTransientTaskbar;
+
+ private final TransitionCallback mCallback;
+
+ public TaskbarTranslationController(TaskbarActivityContext context) {
+ mContext = context;
+ mIsTransientTaskbar = DisplayController.isTransientTaskbar(mContext);
+ mCallback = new TransitionCallback();
+ }
+
+ /**
+ * Initialization method.
+ */
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ }
+
+ /**
+ * Called to cancel any existing animations.
+ */
+ public void cancelAnimationIfExists() {
+ if (mSpringBounce != null) {
+ mSpringBounce.cancel();
+ mSpringBounce = null;
+ }
+ reset();
+ }
+
+ private void updateTranslationYForSwipe() {
+ if (!mIsTransientTaskbar) {
+ return;
+ }
+
+ float transY = mTranslationYForSwipe.value;
+ mControllers.stashedHandleViewController.setTranslationYForSwipe(transY);
+ mControllers.taskbarViewController.setTranslationYForSwipe(transY);
+ mControllers.taskbarDragLayerController.setTranslationYForSwipe(transY);
+ }
+
+ /**
+ * Starts a spring aniamtion to set the views back to the resting state.
+ */
+ public void startSpring() {
+ if (mHasSprungOnceThisGesture || mAnimationToHomeRunning) {
+ return;
+ }
+ mSpringBounce = new SpringAnimationBuilder(mContext)
+ .setStartValue(mTranslationYForSwipe.value)
+ .setEndValue(0)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)
+ .setStiffness(SpringForce.STIFFNESS_LOW)
+ .build(mTranslationYForSwipe, VALUE);
+ mSpringBounce.addListener(forEndCallback(() -> {
+ if (mGestureEnded) {
+ reset();
+ }
+ }));
+ mSpringBounce.start();
+ mHasSprungOnceThisGesture = true;
+ }
+
+ private void reset() {
+ mGestureEnded = false;
+ mHasSprungOnceThisGesture = false;
+ }
+
+ /**
+ * Returns a callback to help monitor the swipe gesture.
+ */
+ public TransitionCallback getTransitionCallback() {
+ return mCallback;
+ }
+
+ /**
+ * Returns an animation to reset the taskbar translation for animation back to launcher.
+ */
+ public ObjectAnimator createAnimToLauncher(long duration) {
+ ObjectAnimator animator = ObjectAnimator.ofFloat(mTranslationYForSwipe, VALUE, 0);
+ animator.setInterpolator(Interpolators.LINEAR);
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ cancelAnimationIfExists();
+ mAnimationToHomeRunning = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimationToHomeRunning = false;
+ reset();
+ }
+ });
+ return animator;
+ }
+
+ /**
+ * Helper class to communicate to/from the input consumer.
+ */
+ public class TransitionCallback {
+
+ /**
+ * Called when there is movement to move the taskbar.
+ */
+ public void onActionMove(float dY) {
+ if (mAnimationToHomeRunning
+ || (mHasSprungOnceThisGesture && !mGestureEnded)) {
+ return;
+ }
+
+ mTranslationYForSwipe.updateValue(dY);
+ }
+
+ /**
+ * Called when swipe gesture has ended.
+ */
+ public void onActionEnd() {
+ if (mHasSprungOnceThisGesture) {
+ reset();
+ } else {
+ mGestureEnded = true;
+ startSpring();
+ }
+ }
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarTranslationController:");
+
+ pw.println(prefix + "\tmTranslationYForSwipe=" + mTranslationYForSwipe.value);
+ pw.println(prefix + "\tmHasSprungOnceThisGesture=" + mHasSprungOnceThisGesture);
+ pw.println(prefix + "\tmAnimationToHomeRunning=" + mAnimationToHomeRunning);
+ pw.println(prefix + "\tmGestureEnded=" + mGestureEnded);
+ pw.println(prefix + "\tmSpringBounce is running=" + (mSpringBounce != null
+ && mSpringBounce.isRunning()));
+ }
+}
+
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 1152126..4ec9b41 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -15,13 +15,18 @@
*/
package com.android.launcher3.taskbar;
+import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.CallSuper;
+import androidx.annotation.Nullable;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
import java.io.PrintWriter;
import java.util.stream.Stream;
@@ -105,6 +110,13 @@
return mControllers.taskbarStashController.isStashed();
}
+ /**
+ * Called at the end of the swipe gesture on Transient taskbar.
+ */
+ public void startTranslationSpring() {
+ mControllers.taskbarActivityContext.startTranslationSpring();
+ }
+
/*
* @param ev MotionEvent in screen coordinates.
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
@@ -128,4 +140,38 @@
prefix,
getClass().getSimpleName()));
}
+
+ /**
+ * Returns RecentsView. Overwritten in LauncherTaskbarUIController and
+ * FallbackTaskbarUIController with Launcher-specific implementations. Returns null for other
+ * UI controllers (like DesktopTaskbarUIController) that don't have a RecentsView.
+ */
+ public @Nullable RecentsView getRecentsView() {
+ return null;
+ }
+
+ /**
+ * Uses the clicked Taskbar icon to launch a second app for splitscreen.
+ */
+ public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) {
+ RecentsView recents = getRecentsView();
+ TaskView foundTaskView = recents.getTaskViewByComponentName(info.getTargetComponent());
+ if (foundTaskView != null) {
+ recents.confirmSplitSelect(
+ foundTaskView,
+ foundTaskView.getTask(),
+ foundTaskView.getIconView().getDrawable(),
+ foundTaskView.getThumbnail(),
+ foundTaskView.getThumbnail().getThumbnail(),
+ /* intent */ null);
+ } else {
+ recents.confirmSplitSelect(
+ /* containerTaskView */ null,
+ /* task */ null,
+ new BitmapDrawable(info.bitmap.icon),
+ startingView,
+ /* thumbnail */ null,
+ intent);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index fe38bb1..c4eeca7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -422,6 +422,7 @@
/**
* Returns the all apps button in the taskbar.
*/
+ @Nullable
public View getAllAppsButtonView() {
return mAllAppsButton;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index a73528b..9936d27 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -91,6 +91,7 @@
this::updateTranslationY);
private AnimatedFloat mTaskbarNavButtonTranslationY;
private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay;
+ private float mTaskbarIconTranslationYForSwipe;
private final int mTaskbarBottomMargin;
@@ -239,6 +240,7 @@
return mTaskbarView.getIconViews();
}
+ @Nullable
public View getAllAppsButtonView() {
return mTaskbarView.getAllAppsButtonView();
}
@@ -260,9 +262,18 @@
mTaskbarView.setScaleY(scale);
}
+ /**
+ * Sets the translation of the TaskbarView during the swipe up gesture.
+ */
+ public void setTranslationYForSwipe(float transY) {
+ mTaskbarIconTranslationYForSwipe = transY;
+ updateTranslationY();
+ }
+
private void updateTranslationY() {
mTaskbarView.setTranslationY(mTaskbarIconTranslationYForHome.value
- + mTaskbarIconTranslationYForStash.value);
+ + mTaskbarIconTranslationYForStash.value
+ + mTaskbarIconTranslationYForSwipe);
}
private void updateIconsBackground() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 837af58..a033507 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -14,7 +14,8 @@
* Controls Taskbar behavior while Voice Interaction Window (assistant) is showing.
*/
class VoiceInteractionWindowController(val context: TaskbarActivityContext)
- : TaskbarControllers.LoggableTaskbarController {
+ : TaskbarControllers.LoggableTaskbarController,
+ TaskbarControllers.BackgroundRendererController {
private val taskbarBackgroundRenderer = TaskbarBackgroundRenderer(context)
@@ -111,6 +112,11 @@
}
}
+ override fun setCornerRoundness(cornerRoundness: Float) {
+ taskbarBackgroundRenderer.setCornerRoundness(cornerRoundness)
+ separateWindowForTaskbarBackground.invalidate()
+ }
+
override fun dumpLogs(prefix: String, pw: PrintWriter) {
pw.println(prefix + "VoiceInteractionWindowController:")
pw.println("$prefix\tisVoiceInteractionWindowVisible=$isVoiceInteractionWindowVisible")
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 85c6318..4dc8d47 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -48,6 +48,8 @@
private AppInfo[] mApps;
private int mAppsModelFlags;
private List<ItemInfo> mPredictedApps;
+ private boolean mDisallowGlobalDrag;
+ private boolean mDisallowLongClick;
/** Initialize the controller. */
public void init(TaskbarControllers controllers, boolean allAppsVisible) {
@@ -78,6 +80,14 @@
}
}
+ public void setDisallowGlobalDrag(boolean disableDragForOverviewState) {
+ mDisallowGlobalDrag = disableDragForOverviewState;
+ }
+
+ public void setDisallowLongClick(boolean disallowLongClick) {
+ mDisallowLongClick = disallowLongClick;
+ }
+
/** Updates the current predictions. */
public void setPredictedApps(List<ItemInfo> predictedApps) {
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
@@ -123,6 +133,12 @@
mAppsView.getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(mPredictedApps);
+ // 1 alternative that would be more work:
+ // Create a shared drag layer between taskbar and taskbarAllApps so that when dragging
+ // starts and taskbarAllApps can close, but the drag layer that the view is being dragged in
+ // doesn't also close
+ overlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
+ overlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index 7e3163d..ebaf60a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -19,8 +19,8 @@
import android.view.View;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
@@ -62,7 +62,7 @@
mOverlayController = controllers.taskbarOverlayController;
mDragController = new TaskbarDragController(this);
mDragController.init(controllers);
- mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
+ mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
mDragLayer = new TaskbarOverlayDragLayer(this);
TaskbarStashController taskbarStashController = controllers.taskbarStashController;
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index 6c7bdbf..019e5a6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -61,6 +61,11 @@
public void onTaskStackChanged() {
mProxyView.close(false);
}
+
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ mProxyView.close(false);
+ }
};
private DeviceProfile mLauncherDeviceProfile;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index 729eea9..379a6cd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -24,7 +24,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.Utilities;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherWidgetHolder;
/**
* A wrapper for the hidden API calls
@@ -44,7 +44,7 @@
* @param handler InteractionHandler for the views in the host
*/
public static void setHostInteractionHandler(@NonNull AppWidgetHost host,
- @Nullable LauncherAppWidgetHost.LauncherWidgetInteractionHandler handler) {
+ @Nullable LauncherWidgetHolder.LauncherWidgetInteractionHandler handler) {
host.setInteractionHandler(handler::onInteraction);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 2dde6b6..353d817 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -33,12 +33,12 @@
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ActivityOptionsWrapper;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherWidgetHolder;
/** Provides a Quickstep specific animation when launching an activity from an app widget. */
-class QuickstepInteractionHandler implements
- LauncherAppWidgetHost.LauncherWidgetInteractionHandler {
+class QuickstepInteractionHandler
+ implements LauncherWidgetHolder.LauncherWidgetInteractionHandler {
private static final String TAG = "QuickstepInteractionHandler";
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 9813c8a..36d9686 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -78,7 +78,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherWidgetHolder;
import com.android.launcher3.QuickstepAccessibilityDelegate;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
@@ -96,6 +95,7 @@
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.WellbeingModel;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
@@ -125,6 +125,7 @@
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.TouchController;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SystemUiProxy;
@@ -136,6 +137,7 @@
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
+import com.android.quickstep.util.SplitToWorkspaceController;
import com.android.quickstep.util.SplitWithKeyboardShortcutController;
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.OverviewActionsView;
@@ -182,7 +184,10 @@
private @Nullable RotationChangeProvider mRotationChangeProvider;
private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
+ private SplitSelectStateController mSplitSelectStateController;
private SplitWithKeyboardShortcutController mSplitWithKeyboardShortcutController;
+ private SplitToWorkspaceController mSplitToWorkspaceController;
+
/**
* If Launcher restarted while in the middle of an Overview split select, it needs this data to
* recover. In all other cases this will remain null.
@@ -199,12 +204,14 @@
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = getOverviewPanel();
- SplitSelectStateController controller =
+ mSplitSelectStateController =
new SplitSelectStateController(this, mHandler, getStateManager(),
getDepthController(), getStatsLogManager());
- overviewPanel.init(mActionsView, controller);
+ overviewPanel.init(mActionsView, mSplitSelectStateController);
mSplitWithKeyboardShortcutController = new SplitWithKeyboardShortcutController(this,
- controller);
+ mSplitSelectStateController);
+ mSplitToWorkspaceController = new SplitToWorkspaceController(this,
+ mSplitSelectStateController);
mActionsView.updateDimension(getDeviceProfile(), overviewPanel.getLastComputedTaskSize());
mActionsView.updateVerticalMargin(DisplayController.getNavigationMode(this));
@@ -330,7 +337,7 @@
}
protected void onItemClicked(View view) {
- if (!mSplitWithKeyboardShortcutController.handleSecondAppSelectionForSplit(view)) {
+ if (!mSplitToWorkspaceController.handleSecondAppSelectionForSplit(view)) {
QuickstepLauncher.super.getItemOnClickListener().onClick(view);
}
}
@@ -724,6 +731,10 @@
return mTaskbarUIController;
}
+ public SplitSelectStateController getSplitSelectStateController() {
+ return mSplitSelectStateController;
+ }
+
public <T extends OverviewActionsView> T getActionsView() {
return (T) mActionsView;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
index 5afeca7..faa900b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
@@ -18,11 +18,11 @@
import android.content.Context;
import android.content.SharedPreferences;
-import com.android.launcher3.Utilities;
-import com.android.systemui.shared.plugins.PluginEnabler;
-
import androidx.preference.PreferenceDataStore;
+import com.android.launcher3.LauncherPrefs;
+import com.android.systemui.shared.plugins.PluginEnabler;
+
public class PluginEnablerImpl extends PreferenceDataStore implements PluginEnabler {
private static final String PREFIX_PLUGIN_ENABLED = "PLUGIN_ENABLED_";
@@ -30,7 +30,7 @@
final private SharedPreferences mSharedPrefs;
public PluginEnablerImpl(Context context) {
- mSharedPrefs = Utilities.getDevicePrefs(context);
+ mSharedPrefs = LauncherPrefs.getDevicePrefs(context);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index fe0bca6..e3d386c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -28,9 +28,9 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginActionManager;
import com.android.systemui.shared.plugins.PluginInstance;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.plugins.PluginPrefs;
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 918b3c1..f343f52 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -26,6 +26,7 @@
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.ObjectAnimator;
@@ -86,6 +87,11 @@
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
+ boolean isOneHandedModeActive = (SystemUiProxy.INSTANCE.get(mLauncher)
+ .getLastSystemUiStateFlags() & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0;
+ // Reset touch slop multiplier to default 1.0f if one-handed-mode is not active
+ mDetector.setTouchSlopMultiplier(
+ isOneHandedModeActive ? ONE_HANDED_ACTIVATED_SLOP_MULTIPLIER : 1f /* default */);
return super.canInterceptTouch(ev) && !mLauncher.isInState(HINT_STATE);
}
@@ -277,14 +283,4 @@
private float dpiFromPx(float pixels) {
return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics().densityDpi);
}
-
- @Override
- public void onOneHandedModeStateChanged(boolean activated) {
- if (activated) {
- mDetector.setTouchSlopMultiplier(ONE_HANDED_ACTIVATED_SLOP_MULTIPLIER);
- } else {
- // Reset touch slop multiplier to default 1.0f
- mDetector.setTouchSlopMultiplier(1f /* default */);
- }
- }
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 7e4c2f6..9aedbf8 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_REVISED_THRESHOLDS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -95,10 +96,12 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.tracing.InputConsumerProto;
import com.android.launcher3.tracing.SwipeHandlerProto;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
@@ -286,11 +289,10 @@
private AnimatorControllerWithResistance mLauncherTransitionController;
private boolean mHasEndedLauncherTransition;
- private AnimationFactory mAnimationFactory = (t, s) -> { };
+ private AnimationFactory mAnimationFactory = (t) -> { };
private boolean mWasLauncherAlreadyVisible;
- private boolean mPassedOverviewThreshold;
private boolean mGestureStarted;
private boolean mLogDirectionUpOrLeft = true;
private PointF mDownPos;
@@ -316,6 +318,9 @@
private final int mTaskbarAppWindowThreshold;
private final int mTaskbarCatchUpThreshold;
private boolean mTaskbarAlreadyOpen;
+ private final boolean mIsTransientTaskbar;
+ // May be set to false when mIsTransientTaskbar is true.
+ private boolean mCanSlowSwipeGoHome = true;
public AbsSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
@@ -340,8 +345,11 @@
Resources res = context.getResources();
mTaskbarAppWindowThreshold = res
- .getDimensionPixelSize(R.dimen.taskbar_app_window_threshold);
+ .getDimensionPixelSize(ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
+ ? R.dimen.taskbar_app_window_threshold_v2
+ : R.dimen.taskbar_app_window_threshold);
mTaskbarCatchUpThreshold = res.getDimensionPixelSize(R.dimen.taskbar_catch_up_threshold);
+ mIsTransientTaskbar = DisplayController.isTransientTaskbar(mActivity);
mQuickSwitchScaleScrollThreshold = res
.getDimension(R.dimen.quick_switch_scaling_scroll_threshold);
@@ -530,9 +538,7 @@
Runnable initAnimFactory = () -> {
mAnimationFactory = mActivityInterface.prepareRecentsUI(mDeviceState,
mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated);
- maybeUpdateRecentsAttachedState(
- false /* animate */,
- new ActiveGestureLog.CompoundString("on Launcher start (animate=false)"));
+ maybeUpdateRecentsAttachedState(false /* animate */);
if (mGestureState.getEndTarget() != null) {
// Update the end target in case the gesture ended before we init.
mAnimationFactory.setEndTarget(mGestureState.getEndTarget());
@@ -637,8 +643,7 @@
}
private void initializeLauncherAnimationController() {
- buildAnimationController(new ActiveGestureLog.CompoundString(
- "initializing launcher animation controller"));
+ buildAnimationController();
Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents",
TraceHelper.FLAG_IGNORE_BINDERS);
@@ -657,11 +662,9 @@
@Override
public void onMotionPauseDetected() {
mHasMotionEverBeenPaused = true;
- maybeUpdateRecentsAttachedState(
- true/* animate */,
- true/* moveFocusedTask */,
- new ActiveGestureLog.CompoundString(
- "motion pause detected (animate=true)"));
+ maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */);
+ Optional.ofNullable(mActivityInterface.getTaskbarController())
+ .ifPresent(TaskbarUIController::startTranslationSpring);
performHapticFeedback();
}
@@ -672,13 +675,12 @@
};
}
- private void maybeUpdateRecentsAttachedState(ActiveGestureLog.CompoundString reason) {
- maybeUpdateRecentsAttachedState(true /* animate */, reason.append(" (animate=true)"));
+ private void maybeUpdateRecentsAttachedState() {
+ maybeUpdateRecentsAttachedState(true /* animate */);
}
- private void maybeUpdateRecentsAttachedState(
- boolean animate, ActiveGestureLog.CompoundString reason) {
- maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */, reason);
+ private void maybeUpdateRecentsAttachedState(boolean animate) {
+ maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */);
}
/**
@@ -690,8 +692,7 @@
* @param animate whether to animate when attaching RecentsView
* @param moveFocusedTask whether to move focused task to front when attaching
*/
- private void maybeUpdateRecentsAttachedState(
- boolean animate, boolean moveFocusedTask, ActiveGestureLog.CompoundString reason) {
+ private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) {
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
@@ -701,25 +702,14 @@
final boolean recentsAttachedToAppWindow;
if (mGestureState.getEndTarget() != null) {
recentsAttachedToAppWindow = mGestureState.getEndTarget().recentsAttachedToAppWindow;
- reason.append("; gesture state end target != null (attached=")
- .append(Boolean.toString(recentsAttachedToAppWindow))
- .append(")");
} else if (mContinuingLastGesture
&& mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) {
recentsAttachedToAppWindow = true;
- reason.append("; continuing last gesture (attached=true)");
} else if (runningTaskTarget != null && isNotInRecents(runningTaskTarget)) {
// The window is going away so make sure recents is always visible in this case.
recentsAttachedToAppWindow = true;
- reason.append("; make sure recents is always visible (attached=true)");
} else {
recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
- reason.append(mHasMotionEverBeenPaused
- ? "; motion has been paused"
- : "; gesture is likely to start a new task")
- .append(" (attached=")
- .append(Boolean.toString(recentsAttachedToAppWindow))
- .append(")");
}
if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
&& recentsAttachedToAppWindow) {
@@ -727,8 +717,7 @@
// TaskView jumping to new position as we move the tasks.
mRecentsView.moveFocusedTaskToFront();
}
- mAnimationFactory.setRecentsAttachedToAppWindow(
- recentsAttachedToAppWindow, animate, reason);
+ mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
// Reapply window transform throughout the attach animation, as the animation affects how
// much the window is bound by overscroll (vs moving freely).
@@ -747,30 +736,38 @@
}
}
- public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
- setIsLikelyToStartNewTask(
- isLikelyToStartNewTask,
- true /* animate */,
- new ActiveGestureLog.CompoundString(
- "setting gesture likely to start (animate=true)"));
+ /**
+ * Sets whether or not we should clamp the scroll offset.
+ * This is used to avoid x-axis movement when swiping up transient taskbar.
+ * @param clampScrollOffset When true, we clamp the scroll to 0 before the clamp threshold is
+ * met.
+ */
+ public void setClampScrollOffset(boolean clampScrollOffset) {
+ if (mRecentsView == null) {
+ mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT,
+ () -> mRecentsView.setClampScrollOffset(clampScrollOffset));
+ return;
+ }
+ mRecentsView.setClampScrollOffset(clampScrollOffset);
}
- private void setIsLikelyToStartNewTask(
- boolean isLikelyToStartNewTask,
- boolean animate,
- ActiveGestureLog.CompoundString reason) {
+ public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
+ setIsLikelyToStartNewTask(isLikelyToStartNewTask, true /* animate */);
+ }
+
+ private void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask, boolean animate) {
if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
mIsLikelyToStartNewTask = isLikelyToStartNewTask;
- maybeUpdateRecentsAttachedState(animate, reason);
+ maybeUpdateRecentsAttachedState(animate);
}
}
- private void buildAnimationController(ActiveGestureLog.CompoundString reason) {
+ private void buildAnimationController() {
if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
initTransitionEndpoints(mActivity.getDeviceProfile());
- mAnimationFactory.createActivityInterface(mTransitionDragLength, reason);
+ mAnimationFactory.createActivityInterface(mTransitionDragLength);
}
/**
@@ -785,7 +782,7 @@
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
WindowInsets result = view.onApplyWindowInsets(windowInsets);
- buildAnimationController(new ActiveGestureLog.CompoundString("applying window insets"));
+ buildAnimationController();
// Reapply the current shift to ensure it takes new insets into account, e.g. when long
// pressing to stash taskbar without moving the finger.
updateFinalShift();
@@ -816,14 +813,6 @@
@UiThread
@Override
public void updateFinalShift() {
- final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
- if (passed != mPassedOverviewThreshold) {
- mPassedOverviewThreshold = passed;
- if (mDeviceState.isTwoButtonNavMode() && !mGestureState.isHandlingAtomicEvent()) {
- performHapticFeedback();
- }
- }
-
updateSysUiFlags(mCurrentShift.value);
applyScrollAndTransform();
@@ -836,7 +825,7 @@
return;
}
mLauncherTransitionController.setProgress(
- Math.max(getTaskbarProgress(), getScaleProgressDueToScroll()), mDragLengthFactor);
+ Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor);
}
/**
@@ -908,8 +897,6 @@
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
this::startInterceptingTouchesForGesture);
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
-
- mPassedOverviewThreshold = false;
}
@Override
@@ -951,16 +938,15 @@
InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH, 2000 /* ms timeout */);
InteractionJankMonitorWrapper.begin(mRecentsView,
InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
+ InteractionJankMonitorWrapper.begin(mRecentsView,
+ InteractionJankMonitorWrapper.CUJ_APP_SWIPE_TO_RECENTS);
rv.post(() -> rv.getViewTreeObserver().removeOnDrawListener(this));
}
});
}
notifyGestureStartedAsync();
- setIsLikelyToStartNewTask(
- isLikelyToStartNewTask,
- false /* animate */,
- new ActiveGestureLog.CompoundString("on gesture started (animate=false)"));
+ setIsLikelyToStartNewTask(isLikelyToStartNewTask, false /* animate */);
mStateCallback.setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
}
@@ -1041,8 +1027,7 @@
private void onSettledOnEndTarget() {
// Fast-finish the attaching animation if it's still running.
- maybeUpdateRecentsAttachedState(false, new ActiveGestureLog.CompoundString(
- "on settled on end target (animate=false)"));
+ maybeUpdateRecentsAttachedState(false);
final GestureEndTarget endTarget = mGestureState.getEndTarget();
// Wait until the given View (if supplied) draws before resuming the last task.
View postResumeLastTask = mActivityInterface.onSettledOnEndTarget(endTarget);
@@ -1055,6 +1040,10 @@
InteractionJankMonitorWrapper.cancel(
InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
}
+ if (endTarget != RECENTS) {
+ InteractionJankMonitorWrapper.cancel(
+ InteractionJankMonitorWrapper.CUJ_APP_SWIPE_TO_RECENTS);
+ }
switch (endTarget) {
case HOME:
@@ -1135,20 +1124,11 @@
return willGoToNewTask || isCenteredOnNewTask ? NEW_TASK : LAST_TASK;
}
- if (!mDeviceState.isFullyGesturalNavMode()) {
- return (!hasReachedOverviewThreshold() && willGoToNewTask) ? NEW_TASK : RECENTS;
- }
return willGoToNewTask ? NEW_TASK : HOME;
}
private GestureEndTarget calculateEndTargetForNonFling(PointF velocity) {
final boolean isScrollingToNewTask = isScrollingToNewTask();
- final boolean reachedOverviewThreshold = hasReachedOverviewThreshold();
- if (!mDeviceState.isFullyGesturalNavMode()) {
- return reachedOverviewThreshold && mGestureStarted
- ? RECENTS
- : (isScrollingToNewTask ? NEW_TASK : LAST_TASK);
- }
// Fully gestural mode.
final boolean isFlingX = Math.abs(velocity.x) > mContext.getResources()
@@ -1161,10 +1141,8 @@
return RECENTS;
} else if (isScrollingToNewTask) {
return NEW_TASK;
- } else if (reachedOverviewThreshold) {
- return HOME;
}
- return LAST_TASK;
+ return velocity.y < 0 && mCanSlowSwipeGoHome ? HOME : LAST_TASK;
}
private boolean isScrollingToNewTask() {
@@ -1180,8 +1158,16 @@
return runningTaskIndex >= 0 && mRecentsView.getNextPage() != runningTaskIndex;
}
- private boolean hasReachedOverviewThreshold() {
- return getTaskbarProgress() > MIN_PROGRESS_FOR_OVERVIEW;
+ /**
+ * Sets whether a slow swipe can go to the HOME end target when the user lets go. A slow swipe
+ * for this purpose must meet two criteria:
+ * 1) y-velocity is less than quickstep_fling_threshold_speed
+ * AND
+ * 2) motion pause has not been detected (possibly because
+ * {@link MotionPauseDetector#setDisallowPause} has been called with disallowPause == true)
+ */
+ public void setCanSlowSwipeGoHome(boolean canSlowSwipeGoHome) {
+ mCanSlowSwipeGoHome = canSlowSwipeGoHome;
}
@UiThread
@@ -1348,12 +1334,15 @@
@UiThread
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
- maybeUpdateRecentsAttachedState(new ActiveGestureLog.CompoundString(
- "animate to progress internal"));
+ maybeUpdateRecentsAttachedState();
// If we are transitioning to launcher, then listen for the activity to be restarted while
// the transition is in progress
if (mGestureState.getEndTarget().isLauncher) {
+ // This is also called when the launcher is resumed, in order to clear the pending
+ // widgets that have yet to be configured.
+ DragView.removeAllViews(mActivity);
+
TaskStackChangeListeners.getInstance().registerTaskStackListener(
mActivityRestartListener);
@@ -1668,9 +1657,7 @@
mRecentsView.post(mRecentsView::resetTaskVisuals);
}
// Make sure recents is in its final state
- maybeUpdateRecentsAttachedState(
- false, new ActiveGestureLog.CompoundString(
- "setting up window animation (animate=false)"));
+ maybeUpdateRecentsAttachedState(false);
mActivityInterface.onSwipeUpToHomeComplete(mDeviceState);
}
});
@@ -2200,7 +2187,7 @@
AnimatorControllerWithResistance playbackController =
remoteHandle.getPlaybackController();
if (playbackController != null) {
- playbackController.setProgress(Math.max(getTaskbarProgress(),
+ playbackController.setProgress(Math.max(mCurrentShift.value,
getScaleProgressDueToScroll()), mDragLengthFactor);
}
@@ -2252,31 +2239,32 @@
}
/**
- * Overrides the current shift progress to keep the app window at the bottom of the screen
- * while the transient taskbar is being swiped in.
+ * Overrides the gesture displacement to keep the app window at the bottom of the screen while
+ * the transient taskbar is being swiped in.
*
* There is also a catch up period so that the window can start moving 1:1 with the swipe.
*/
- private float getTaskbarProgress() {
- if (!DisplayController.isTransientTaskbar(mContext)) {
- return mCurrentShift.value;
+ @Override
+ protected float overrideDisplacementForTransientTaskbar(float displacement) {
+ if (!mIsTransientTaskbar) {
+ return displacement;
}
if (mTaskbarAlreadyOpen) {
- return mCurrentShift.value;
+ return displacement;
}
- if (mCurrentDisplacement < mTaskbarAppWindowThreshold) {
+ if (displacement < mTaskbarAppWindowThreshold) {
return 0;
}
- // "Catch up" with `mCurrentShift.value`.
- if (mCurrentDisplacement < mTaskbarCatchUpThreshold) {
- return Utilities.mapToRange(mCurrentDisplacement, mTaskbarAppWindowThreshold,
- mTaskbarCatchUpThreshold, 0, mCurrentShift.value, ACCEL_DEACCEL);
+ // "Catch up" with the displacement at mTaskbarCatchUpThreshold.
+ if (displacement < mTaskbarCatchUpThreshold) {
+ return Utilities.mapToRange(displacement, mTaskbarAppWindowThreshold,
+ mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCEL_DEACCEL);
}
- return mCurrentShift.value;
+ return displacement;
}
private void setDividerShown(boolean shown, boolean immediate) {
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index de150e1..274b686 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -30,6 +30,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
@@ -59,7 +60,6 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.views.ScrimView;
-import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.views.RecentsView;
@@ -120,9 +120,6 @@
public abstract void onAssistantVisibilityChanged(float visibility);
- /** Called when one handed mode activated or deactivated. */
- public abstract void onOneHandedModeStateChanged(boolean activated);
-
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
@@ -401,16 +398,14 @@
public interface AnimationFactory {
- void createActivityInterface(long transitionLength, ActiveGestureLog.CompoundString reason);
+ void createActivityInterface(long transitionLength);
/**
* @param attached Whether to show RecentsView alongside the app window. If false, recents
* will be hidden by some property we can animate, e.g. alpha.
* @param animate Whether to animate recents to/from its new attached state.
- * @param reason Explanation for why this method is being called with the given param values
*/
- default void setRecentsAttachedToAppWindow(
- boolean attached, boolean animate, ActiveGestureLog.CompoundString reason) { }
+ default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
default boolean isRecentsAttachedToAppWindow() {
return false;
@@ -452,8 +447,7 @@
}
@Override
- public void createActivityInterface(
- long transitionLength, ActiveGestureLog.CompoundString reason) {
+ public void createActivityInterface(long transitionLength) {
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
createBackgroundToOverviewAnim(mActivity, pa);
AnimatorPlaybackController controller = pa.createPlaybackController();
@@ -476,70 +470,47 @@
// (because we set the animation as the current state animation), so we reapply the
// attached state here as well to ensure recents is shown/hidden appropriately.
if (DisplayController.getNavigationMode(mActivity) == NavigationMode.NO_BUTTON) {
- setRecentsAttachedToAppWindow(
- mIsAttachedToWindow,
- false,
- reason.append("; reapplying the attached state (attached=")
- .append(Boolean.toString(mIsAttachedToWindow))
- .append(", animate=false)"));
+ setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
}
}
@Override
- public void setRecentsAttachedToAppWindow(
- boolean attached, boolean animate, ActiveGestureLog.CompoundString reason) {
- // TODO(b/244593270): remove these logs; too verbose
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("setRecentsAttachedToAppWindow: attached=")
- .append(Boolean.toString(attached))
- .append(", animate=")
- .append(Boolean.toString(animate))
- .append(", reason=")
- .append(reason));
+ public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
if (mIsAttachedToWindow == attached && animate) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "setRecentsAttachedToAppWindow: exiting early"));
return;
}
- mIsAttachedToWindow = attached;
- RecentsView recentsView = mActivity.getOverviewPanel();
- if (attached) {
- mHasEverAttachedToWindow = true;
- }
- Animator fadeAnim = mActivity.getStateManager()
- .createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
-
- float fromTranslation = attached ? 1 : 0;
- float toTranslation = attached ? 0 : 1;
+ mActivity.getStateManager()
+ .cancelStateElementAnimation(INDEX_RECENTS_FADE_ANIM);
mActivity.getStateManager()
.cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
- if (!recentsView.isShown() && animate) {
- ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, fromTranslation);
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "setRecentsAttachedToAppWindow: recents view not shown, setting ")
- .append("ADJACENT_PAGE_HORIZONTAL_OFFSET to ")
- .append(Float.toString(fromTranslation)));
- } else {
- fromTranslation = ADJACENT_PAGE_HORIZONTAL_OFFSET.get(recentsView);
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "setRecentsAttachedToAppWindow: updating fromTranslation to ")
- .append(Float.toString(fromTranslation)));
- }
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "setRecentsAttachedToAppWindow: fromTranslation=")
- .append(Float.toString(fromTranslation))
- .append(", toTranslation=")
- .append(Float.toString(toTranslation)));
- if (!animate) {
- ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, toTranslation);
- } else {
- mActivity.getStateManager().createStateElementAnimation(
- INDEX_RECENTS_TRANSLATE_X_ANIM,
- fromTranslation, toTranslation).start();
- }
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mIsAttachedToWindow = attached;
+ if (attached) {
+ mHasEverAttachedToWindow = true;
+ }
+ }});
+
+ long animationDuration = animate ? RECENTS_ATTACH_DURATION : 0;
+ Animator fadeAnim = mActivity.getStateManager()
+ .createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
- fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
+ fadeAnim.setDuration(animationDuration);
+ animatorSet.play(fadeAnim);
+
+ float fromTranslation = ADJACENT_PAGE_HORIZONTAL_OFFSET.get(
+ mActivity.getOverviewPanel());
+ float toTranslation = attached ? 0 : 1;
+
+ Animator translationAnimator = mActivity.getStateManager().createStateElementAnimation(
+ INDEX_RECENTS_TRANSLATE_X_ANIM, fromTranslation, toTranslation);
+ translationAnimator.setDuration(animationDuration);
+ animatorSet.play(translationAnimator);
+ animatorSet.start();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index c62220f..ae9fb0b 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -77,11 +77,6 @@
// set to zero prior to this class becoming active.
}
- @Override
- public void onOneHandedModeStateChanged(boolean activated) {
- // Do nothing for FallbackActivityInterface
- }
-
/** 6 */
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index ecb3747..9ff9416 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -109,15 +109,6 @@
}
@Override
- public void onOneHandedModeStateChanged(boolean activated) {
- Launcher launcher = getCreatedActivity();
- if (launcher == null) {
- return;
- }
- launcher.onOneHandedStateChanged(activated);
- }
-
- @Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 875b72c..5a09e02 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -116,7 +116,7 @@
*/
@BinderThread
public void addCommand(int type) {
- if (mPendingCommands.size() > MAX_QUEUE_SIZE) {
+ if (mPendingCommands.size() >= MAX_QUEUE_SIZE) {
return;
}
CommandInfo cmd = new CommandInfo(type);
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 9e3173c..8e07376 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -115,11 +115,6 @@
if (mDeviceState.isHomeDisabled() != mIsHomeDisabled) {
updateOverviewTargets();
}
-
- // Notify ALL_APPS touch controller when one handed mode state activated or deactivated
- if (mDeviceState.isOneHandedModeEnabled()) {
- mActivityInterface.onOneHandedModeStateChanged(mDeviceState.isOneHandedModeActive());
- }
}
private void updateOverviewTargets(Intent unused) {
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 9621ce6..54e4a0d 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -1,5 +1,6 @@
package com.android.quickstep;
+import static com.android.launcher3.testing.shared.TestProtocol.NPE_TRANSIENT_TASKBAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.Activity;
@@ -7,13 +8,16 @@
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Bundle;
+import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.TISBindHelper;
@@ -120,6 +124,26 @@
.getCurrentActivityContext()
.getTaskbarAllAppsTopPadding());
}
+
+ case TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT:
+ runOnTISBinder(tisBinder -> {
+ enableBlockingTimeout(tisBinder, true);
+ });
+ return response;
+
+ case TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT:
+ runOnTISBinder(tisBinder -> {
+ enableBlockingTimeout(tisBinder, false);
+ });
+ return response;
+
+ case TestProtocol.REQUEST_ENABLE_TRANSIENT_TASKBAR:
+ enableTransientTaskbar(true);
+ return response;
+
+ case TestProtocol.REQUEST_DISABLE_TRANSIENT_TASKBAR:
+ enableTransientTaskbar(false);
+ return response;
}
return super.call(method, arg, extras);
@@ -149,6 +173,23 @@
enable);
}
+ private void enableBlockingTimeout(
+ TouchInteractionService.TISBinder tisBinder, boolean enable) {
+ TaskbarActivityContext context = tisBinder.getTaskbarManager().getCurrentActivityContext();
+ if (context == null) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(NPE_TRANSIENT_TASKBAR, "enableBlockingTimeout: enable=" + enable,
+ new Exception());
+ }
+ } else {
+ context.enableBlockingTimeoutDuringTests(enable);
+ }
+ }
+
+ private void enableTransientTaskbar(boolean enable) {
+ DisplayController.INSTANCE.get(mContext).enableTransientTaskbarForTests(enable);
+ }
+
/**
* Runs the given command on the UI thread, after ensuring we are connected to
* TouchInteractionService.
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index cf1c137..4adfae5 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -170,6 +170,8 @@
mController.finish(toRecents, sendUserLeaveHint);
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
+ InteractionJankMonitorWrapper.end(
+ InteractionJankMonitorWrapper.CUJ_APP_SWIPE_TO_RECENTS);
MAIN_EXECUTOR.execute(mPendingFinishCallbacks::executeAllAndDestroy);
});
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index e87fdad..9e25555 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -46,10 +46,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import android.app.ActivityTaskManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.graphics.Region;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
@@ -63,12 +60,12 @@
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
-import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -114,15 +111,12 @@
private boolean mIsUserUnlocked;
private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
- private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_USER_UNLOCKED.equals(intent.getAction())) {
- mIsUserUnlocked = true;
- notifyUserUnlocked();
- }
+ private final SimpleBroadcastReceiver mUserUnlockedReceiver = new SimpleBroadcastReceiver(i -> {
+ if (ACTION_USER_UNLOCKED.equals(i.getAction())) {
+ mIsUserUnlocked = true;
+ notifyUserUnlocked();
}
- };
+ });
private int mGestureBlockingTaskId = -1;
private @NonNull Region mExclusionRegion = new Region();
@@ -153,10 +147,9 @@
mIsUserUnlocked = context.getSystemService(UserManager.class)
.isUserUnlocked(Process.myUserHandle());
if (!mIsUserUnlocked) {
- mContext.registerReceiver(mUserUnlockedReceiver,
- new IntentFilter(ACTION_USER_UNLOCKED));
+ mUserUnlockedReceiver.register(mContext, ACTION_USER_UNLOCKED);
}
- runOnDestroy(() -> Utilities.unregisterReceiverSafely(mContext, mUserUnlockedReceiver));
+ runOnDestroy(() -> mUserUnlockedReceiver.unregisterReceiverSafely(mContext));
// Register for exclusion updates
mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
@@ -347,7 +340,7 @@
action.run();
}
mUserUnlockedActions.clear();
- Utilities.unregisterReceiverSafely(mContext, mUserUnlockedReceiver);
+ mUserUnlockedReceiver.unregisterReceiverSafely(mContext);
}
/**
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index ddb06ce..fdde45a 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -116,7 +116,7 @@
@UiThread
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
- displacement = -displacement;
+ displacement = overrideDisplacementForTransientTaskbar(-displacement);
mCurrentDisplacement = displacement;
float shift;
@@ -131,6 +131,17 @@
}
/**
+ * When Transient Taskbar is enabled, subclasses can override the displacement to keep the app
+ * window at the bottom of the screen while taskbar is being swiped in.
+ * @param displacement The distance the user has swiped up from the bottom of the screen. This
+ * value will be positive unless the user swipe downwards.
+ * @return the overridden displacement.
+ */
+ protected float overrideDisplacementForTransientTaskbar(float displacement) {
+ return displacement;
+ }
+
+ /**
* Called when the value of {@link #mCurrentShift} changes
*/
@UiThread
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index acf597b..bb97334 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -548,21 +548,33 @@
}
}
- public void startIntentAndTask(PendingIntent pendingIntent, Intent fillInIntent,
- Bundle options1, int taskId, Bundle options2,
- @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
- RemoteTransition remoteTransition, InstanceId instanceId) {
+ public void startIntentAndTask(PendingIntent pendingIntent, Bundle options1, int taskId,
+ Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
+ float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
- mSplitScreen.startIntentAndTask(pendingIntent, fillInIntent, options1,
- taskId, options2, splitPosition, splitRatio,
- remoteTransition, instanceId);
+ mSplitScreen.startIntentAndTask(pendingIntent, options1, taskId, options2,
+ splitPosition, splitRatio, remoteTransition, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startIntentAndTask");
}
}
}
+ public void startIntents(PendingIntent pendingIntent1, Bundle options1,
+ PendingIntent pendingIntent2, Bundle options2,
+ @SplitConfigurationOptions.StagePosition int splitPosition,
+ float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSplitScreen.startIntents(pendingIntent1, options1, pendingIntent2, options2,
+ splitPosition, splitRatio, remoteTransition, instanceId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call startIntents");
+ }
+ }
+ }
+
public void startShortcutAndTask(ShortcutInfo shortcutInfo, Bundle options1, int taskId,
Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
@@ -593,13 +605,13 @@
}
public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent,
- Intent fillInIntent, Bundle options1, int taskId, Bundle options2,
+ Bundle options1, int taskId, Bundle options2,
@SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
- mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, fillInIntent,
- options1, taskId, options2, splitPosition, splitRatio, adapter, instanceId);
+ mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, options1, taskId,
+ options2, splitPosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
Log.w(TAG, "Failed call startIntentAndTaskWithLegacyTransition");
}
@@ -619,6 +631,20 @@
}
}
+ public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, Bundle options1,
+ PendingIntent pendingIntent2, Bundle options2,
+ @SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
+ RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSplitScreen.startIntentsWithLegacyTransition(pendingIntent1, options1,
+ pendingIntent2, options2, sidePosition, splitRatio, adapter, instanceId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call startIntentsWithLegacyTransition");
+ }
+ }
+ }
+
public void startShortcut(String packageName, String shortcutId, int position,
Bundle options, UserHandle user, InstanceId instanceId) {
if (mSplitScreen != null) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 450774b..af6a45a 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -31,6 +31,7 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
@@ -69,6 +70,7 @@
import com.android.app.viewcapture.ViewCapture;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
@@ -479,7 +481,7 @@
}
// Reset home bounce seen on quick step enabled for first time
- SharedPreferences sharedPrefs = Utilities.getPrefs(this);
+ SharedPreferences sharedPrefs = LauncherPrefs.getPrefs(this);
if (!sharedPrefs.getBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)) {
sharedPrefs.edit()
.putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
@@ -533,9 +535,10 @@
}
}
- boolean wasExpanded = (lastSysUIFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
- boolean isExpanded =
- (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+ int isShadeExpandedFlag =
+ SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
+ boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
+ boolean isExpanded = (systemUiStateFlags & isShadeExpandedFlag) != 0;
if (wasExpanded != isExpanded && isExpanded) {
// End live tile when expanding the notification panel for the first time from
// overview.
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 8410149..db7e087 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -53,6 +53,7 @@
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.RecentsAnimationTargets;
+import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
import com.android.quickstep.util.TransformParams;
@@ -226,6 +227,10 @@
mStateCallback.setState(STATE_HANDLER_INVALIDATED);
}
});
+ RemoteAnimationTargets targets = mTransformParams.getTargetSet();
+ if (targets != null) {
+ targets.addReleaseCheck(new DeviceLockedReleaseCheck(animator));
+ }
animator.start();
} else {
mStateCallback.setState(STATE_HANDLER_INVALIDATED);
@@ -304,4 +309,27 @@
public boolean allowInterceptByParent() {
return !mThresholdCrossed;
}
+
+ private static final class DeviceLockedReleaseCheck extends
+ RemoteAnimationTargets.ReleaseCheck {
+
+ private DeviceLockedReleaseCheck(Animator animator) {
+ setCanRelease(true);
+
+ animator.addListener(new AnimatorListenerAdapter() {
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ setCanRelease(false);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ setCanRelease(true);
+ }
+ });
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index b3d3c3d..bf666ea 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.PagedView.DEBUG_FAILED_QUICKSWITCH;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_REVISED_THRESHOLDS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
@@ -36,7 +37,6 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.PointF;
import android.os.Build;
import android.util.Log;
@@ -151,10 +151,6 @@
mHandlerFactory = handlerFactory;
mActivityInterface = mGestureState.getActivityInterface();
- Resources res = base.getResources();
- mTaskbarHomeOverviewThreshold = res
- .getDimensionPixelSize(R.dimen.taskbar_home_overview_threshold);
-
mMotionPauseDetector = new MotionPauseDetector(base, false,
mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge()
? MotionEvent.AXIS_X : MotionEvent.AXIS_Y);
@@ -168,6 +164,10 @@
TaskbarUIController controller = mActivityInterface.getTaskbarController();
mTaskbarAlreadyOpen = controller != null && !controller.isTaskbarStashed();
mIsTransientTaskbar = DisplayController.isTransientTaskbar(base);
+ mTaskbarHomeOverviewThreshold = base.getResources()
+ .getDimensionPixelSize(ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
+ ? R.dimen.taskbar_home_overview_threshold_v2
+ : R.dimen.taskbar_home_overview_threshold);
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
@@ -340,13 +340,12 @@
}
if (mDeviceState.isFullyGesturalNavMode()) {
- float minDisplacement = mMotionPauseMinDisplacement;
-
- if (mIsTransientTaskbar && !mTaskbarAlreadyOpen) {
- minDisplacement += mTaskbarHomeOverviewThreshold;
+ boolean minSwipeMet = upDist >= mMotionPauseMinDisplacement;
+ if (mIsTransientTaskbar) {
+ minSwipeMet = upDist >= mTaskbarHomeOverviewThreshold;
}
-
- mMotionPauseDetector.setDisallowPause(upDist < minDisplacement
+ mInteractionHandler.setCanSlowSwipeGoHome(minSwipeMet);
+ mMotionPauseDetector.setDisallowPause(!minSwipeMet
|| isLikelyToStartNewTask);
mMotionPauseDetector.addPosition(ev);
mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
@@ -382,6 +381,9 @@
mInteractionHandler.onGestureStarted(isLikelyToStartNewTask);
mInteractionHandler.setTaskbarAlreadyOpen(mTaskbarAlreadyOpen);
+ if (mIsTransientTaskbar && !mTaskbarAlreadyOpen && !isLikelyToStartNewTask) {
+ mInteractionHandler.setClampScrollOffset(true);
+ }
}
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
@@ -477,6 +479,9 @@
@UiThread
private void onInteractionGestureFinished() {
Preconditions.assertUIThread();
+ if (mInteractionHandler != null) {
+ mInteractionHandler.setClampScrollOffset(false);
+ }
removeListener();
mInteractionHandler = null;
cleanupAfterGesture();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index 1430492..3a09490 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -18,6 +18,7 @@
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_REVISED_THRESHOLDS;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
import android.content.Context;
@@ -27,9 +28,13 @@
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
+import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.InputConsumer;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -48,7 +53,7 @@
private final float mUnstashArea;
private final float mScreenWidth;
- private final int mTaskbarThreshold;
+ private final int mTaskbarThresholdY;
private boolean mHasPassedTaskbarThreshold;
private final PointF mDownPos = new PointF();
@@ -57,6 +62,8 @@
private final boolean mIsTransientTaskbar;
+ private final @Nullable TransitionCallback mTransitionCallback;
+
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
super(delegate, inputMonitor);
@@ -66,7 +73,11 @@
Resources res = context.getResources();
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
- mTaskbarThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
+ int taskbarThreshold = res.getDimensionPixelSize(ENABLE_TASKBAR_REVISED_THRESHOLDS.get()
+ ? R.dimen.taskbar_nav_threshold_v2
+ : R.dimen.taskbar_nav_threshold);
+ int screenHeight = taskbarActivityContext.getDeviceProfile().heightPx;
+ mTaskbarThresholdY = screenHeight - taskbarThreshold;
mIsTransientTaskbar = DisplayController.isTransientTaskbar(context);
@@ -76,6 +87,10 @@
onLongPressDetected(motionEvent);
}
});
+
+ mTransitionCallback = mIsTransientTaskbar
+ ? taskbarActivityContext.getTranslationCallbacks()
+ : null;
}
@Override
@@ -138,16 +153,25 @@
break;
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
- float displacementY = mLastPos.y - mDownPos.y;
- float verticalDist = Math.abs(displacementY);
- boolean passedTaskbarThreshold = verticalDist >= mTaskbarThreshold;
- if (!mHasPassedTaskbarThreshold
- && passedTaskbarThreshold
- && mIsTransientTaskbar) {
- mHasPassedTaskbarThreshold = true;
+ if (mIsTransientTaskbar) {
+ float dY = mLastPos.y - mDownPos.y;
+ boolean passedTaskbarThreshold = dY < 0
+ && mLastPos.y < mTaskbarThresholdY;
- mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ if (!mHasPassedTaskbarThreshold
+ && passedTaskbarThreshold) {
+ mHasPassedTaskbarThreshold = true;
+
+ mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ }
+
+ if (dY < 0) {
+ dY = -OverScroll.dampedScroll(-dY, mTaskbarThresholdY);
+ if (mTransitionCallback != null) {
+ mTransitionCallback.onActionMove(dY);
+ }
+ }
}
break;
case MotionEvent.ACTION_UP:
@@ -158,6 +182,9 @@
}
mTaskbarActivityContext.setAutohideSuspendFlag(
FLAG_AUTOHIDE_SUSPEND_TOUCHING, false);
+ if (mTransitionCallback != null) {
+ mTransitionCallback.onActionEnd();
+ }
mHasPassedTaskbarThreshold = false;
break;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 8986c05..52f1867 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -42,6 +42,7 @@
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.AccessibilityDelegate;
@@ -53,6 +54,7 @@
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -78,6 +80,7 @@
"#Intent;action=com.android.settings.SEARCH_RESULT_TRAMPOLINE;S.:settings:fragment_args_key=gesture_system_navigation_input_summary;S.:settings:show_fragment=com.android.settings.gestures.SystemNavigationGestureSettings;end";
private static final String EXTRA_ACCENT_COLOR_DARK_MODE = "suwColorAccentDark";
private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "suwColorAccentLight";
+ private static final String EXTRA_DEVICE_NAME = "suwDeviceName";
private static final float HINT_BOTTOM_FACTOR = 1 - .94f;
@@ -109,7 +112,8 @@
int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
- int accentColor = getIntent().getIntExtra(
+ Intent intent = getIntent();
+ int accentColor = intent.getIntExtra(
isDarkTheme ? EXTRA_ACCENT_COLOR_DARK_MODE : EXTRA_ACCENT_COLOR_LIGHT_MODE,
isDarkTheme ? Color.WHITE : Color.BLACK);
@@ -120,11 +124,12 @@
mContentView = findViewById(R.id.content_view);
mSwipeUpShift = getResources().getDimension(R.dimen.allset_swipe_up_shift);
- boolean isTablet = InvariantDeviceProfile.INSTANCE.get(getApplicationContext())
- .getDeviceProfile(this).isTablet;
TextView subtitle = findViewById(R.id.subtitle);
- subtitle.setText(isTablet
- ? R.string.allset_description_tablet : R.string.allset_description);
+ String suwDeviceName = intent.getStringExtra(EXTRA_DEVICE_NAME);
+ subtitle.setText(getString(
+ R.string.allset_description_generic,
+ !TextUtils.isEmpty(suwDeviceName)
+ ? suwDeviceName : getString(R.string.default_device_name)));
TextView tv = findViewById(R.id.navigation_settings);
tv.setTextColor(accentColor);
@@ -137,7 +142,12 @@
}
});
- findViewById(R.id.hint).setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+ TextView hintTextView = findViewById(R.id.hint);
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
+ if (!dp.isGestureMode) {
+ hintTextView.setText(R.string.allset_button_hint);
+ }
+ hintTextView.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
mVibrator = getSystemService(Vibrator.class);
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index bf7023c..4a70120 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -28,8 +28,8 @@
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.TouchInteractionService.TISBinder;
import com.android.quickstep.interaction.TutorialController.TutorialType;
@@ -63,7 +63,7 @@
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gesture_tutorial_activity);
- mSharedPrefs = Utilities.getPrefs(this);
+ mSharedPrefs = LauncherPrefs.getPrefs(this);
mStatsLogManager = StatsLogManager.newInstance(getApplicationContext());
Bundle args = savedInstanceState == null ? getIntent().getExtras() : savedInstanceState;
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 2ccdfa3..5efc45e 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -16,8 +16,8 @@
package com.android.quickstep.logging;
-import static com.android.launcher3.Utilities.getDevicePrefs;
-import static com.android.launcher3.Utilities.getPrefs;
+import static com.android.launcher3.LauncherPrefs.getDevicePrefs;
+import static com.android.launcher3.LauncherPrefs.getPrefs;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_DISABLED;
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index dac5a31..0ef4597 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -62,11 +62,14 @@
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.LogConfig;
import com.android.launcher3.views.ActivityContext;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.SysUiStatsLog;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -85,6 +88,7 @@
private static final String TAG = "StatsLog";
private static final String LATENCY_TAG = "StatsLatencyLog";
+ private static final String IMPRESSION_TAG = "StatsImpressionLog";
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG);
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
// LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates
@@ -119,7 +123,12 @@
@Override
protected StatsLatencyLogger createLatencyLogger() {
- return new StatsCompatLatencyLogger(mContext, mActivityContext);
+ return new StatsCompatLatencyLogger();
+ }
+
+ @Override
+ protected StatsImpressionLogger createImpressionLogger() {
+ return new StatsCompatImpressionLogger();
}
/**
@@ -466,8 +475,6 @@
* Helps to construct and log statsd compatible latency events.
*/
private static class StatsCompatLatencyLogger implements StatsLatencyLogger {
- private final Context mContext;
- private final Optional<ActivityContext> mActivityContext;
private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
private LatencyType mType = LatencyType.UNKNOWN;
private int mPackageId = 0;
@@ -475,11 +482,6 @@
private int mQueryLength = -1;
private int mSubEventType = 0;
- StatsCompatLatencyLogger(Context context, ActivityContext activityContext) {
- mContext = context;
- mActivityContext = Optional.ofNullable(activityContext);
- }
-
@Override
public StatsLatencyLogger withInstanceId(InstanceId instanceId) {
this.mInstanceId = instanceId;
@@ -539,6 +541,96 @@
}
}
+ /**
+ * Helps to construct and log statsd compatible impression events.
+ */
+ private static class StatsCompatImpressionLogger implements StatsImpressionLogger {
+ private final IntArray mResultTypeList = new IntArray();
+ private final IntArray mResultCountList = new IntArray();
+ private final List<Boolean> mAboveKeyboardList = new ArrayList<>();
+ private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
+ private State mLauncherState = State.UNKNOWN;
+ private int mQueryLength = -1;
+
+ @Override
+ public StatsImpressionLogger withInstanceId(InstanceId instanceId) {
+ this.mInstanceId = instanceId;
+ return this;
+ }
+
+ @Override
+ public StatsImpressionLogger withState(State state) {
+ this.mLauncherState = state;
+ return this;
+ }
+
+ @Override
+ public StatsImpressionLogger withQueryLength(int queryLength) {
+ this.mQueryLength = queryLength;
+ return this;
+ }
+
+ @Override
+ public StatsImpressionLogger withResultType(IntArray resultType) {
+ this.mResultTypeList.clear();
+ this.mResultTypeList.addAll(resultType);
+ return this;
+ }
+
+ @Override
+ public StatsImpressionLogger withResultCount(IntArray resultCount) {
+ this.mResultCountList.clear();
+ this.mResultCountList.addAll(resultCount);
+ return this;
+ }
+
+ @Override
+ public StatsImpressionLogger withAboveKeyboard(List<Boolean> aboveKeyboard) {
+ this.mAboveKeyboardList.clear();
+ this.mAboveKeyboardList.addAll(aboveKeyboard);
+ return this;
+ }
+
+ @Override
+ public void log(EventEnum event) {
+ boolean [] mAboveKeyboard = new boolean[mAboveKeyboardList.size()];
+ for (int i = 0; i < mAboveKeyboardList.size(); i++) {
+ mAboveKeyboard[i] = mAboveKeyboardList.get(i);
+ }
+ if (IS_VERBOSE) {
+ String name = (event instanceof Enum) ? ((Enum) event).name() :
+ event.getId() + "";
+ StringBuilder logStringBuilder = new StringBuilder("\n");
+ logStringBuilder.append(String.format("InstanceId:%s ", mInstanceId));
+ logStringBuilder.append(String.format("ImpressionEvent:%s ", name));
+ logStringBuilder.append(String.format("LauncherState = %s ", mLauncherState));
+ logStringBuilder.append(String.format("QueryLength = %s ", mQueryLength));
+ for (int i = 0; i < mResultTypeList.size(); i++) {
+ logStringBuilder.append(String.format(
+ "\n ResultType = %s with ResultCount = %s with is_above_keyboard = %s",
+ mResultTypeList.get(i), mResultCountList.get(i),
+ mAboveKeyboard[i]));
+ }
+ Log.d(IMPRESSION_TAG, logStringBuilder.toString());
+ }
+
+
+
+ SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_IMPRESSION_EVENT,
+ event.getId(), // event_id
+ mInstanceId.getId(), // instance_id
+ mLauncherState.getLauncherState(), // state
+ mQueryLength, // query_length
+ //result type list
+ mResultTypeList.toArray(),
+ // result count list
+ mResultCountList.toArray(),
+ // above keyboard list
+ mAboveKeyboard
+ );
+ }
+ }
+
private static int getCardinality(LauncherAtom.ItemInfo info) {
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
return 0;
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index f12074b..170c622 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION;
import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
-import static com.android.launcher3.Utilities.comp;
import android.annotation.Nullable;
import android.util.FloatProperty;
@@ -135,7 +134,7 @@
@Override
public void onTransitionProgress(float progress) {
if (mQsbInsettable != null) {
- float insetPercentage = comp(progress) * MAX_WIDTH_INSET_FRACTION;
+ float insetPercentage = (1 - progress) * MAX_WIDTH_INSET_FRACTION;
mQsbInsettable.setHorizontalInsets(insetPercentage);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index c459f30..db8c7f2 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -45,7 +45,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DisplayController;
@@ -139,7 +139,7 @@
public RecentsOrientedState(Context context, BaseActivityInterface sizeStrategy,
IntConsumer rotationChangeListener) {
mContext = context;
- mSharedPrefs = Utilities.getPrefs(context);
+ mSharedPrefs = LauncherPrefs.getPrefs(context);
mOrientationListener = new OrientationEventListener(context) {
@Override
public void onOrientationChanged(int degrees) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
index 2966fbb..7dc1b32 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -25,7 +25,7 @@
*/
public interface SplitAnimationTimings {
int TABLET_ENTER_DURATION = 866;
- int TABLET_CONFIRM_DURATION = 383;
+ int TABLET_CONFIRM_DURATION = 500;
int PHONE_ENTER_DURATION = 517;
int PHONE_CONFIRM_DURATION = 333;
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 08f9fa6..c263fe8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -88,10 +88,8 @@
private ItemInfo mItemInfo;
private Intent mInitialTaskIntent;
private int mInitialTaskId = INVALID_TASK_ID;
- private String mInitialTaskPackageName;
private Intent mSecondTaskIntent;
private int mSecondTaskId = INVALID_TASK_ID;
- private String mSecondTaskPackageName;
private boolean mRecentsAnimationRunning;
@Nullable
private UserHandle mUser;
@@ -119,7 +117,6 @@
public void setInitialTaskSelect(Task task, @StagePosition int stagePosition,
StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
mInitialTaskId = task.key.id;
- mInitialTaskPackageName = task.getTopComponent().getPackageName();
setInitialData(stagePosition, splitEvent, itemInfo);
}
@@ -131,7 +128,6 @@
mInitialTaskIntent = intent;
mUser = itemInfo.user;
mItemInfo = itemInfo;
- mInitialTaskPackageName = intent.getComponent().getPackageName();
setInitialData(stagePosition, splitEvent, itemInfo);
}
@@ -143,7 +139,6 @@
@StagePosition int stagePosition, @NonNull ItemInfo itemInfo,
StatsLogManager.EventEnum splitEvent) {
mInitialTaskId = info.taskId;
- mInitialTaskPackageName = info.topActivity.getPackageName();
setInitialData(stagePosition, splitEvent, itemInfo);
}
@@ -161,9 +156,9 @@
public void launchSplitTasks(Consumer<Boolean> callback) {
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
- launchTasks(mInitialTaskId, mInitialTaskIntent, mInitialTaskPackageName, mSecondTaskId,
- mSecondTaskIntent, mSecondTaskPackageName, mStagePosition, callback,
- false /* freezeTaskList */, DEFAULT_SPLIT_RATIO, instanceIds.first);
+ launchTasks(mInitialTaskId, mInitialTaskIntent, mSecondTaskId, mSecondTaskIntent,
+ mStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
+ instanceIds.first);
mStatsLogManager.logger()
.withItemInfo(mItemInfo)
@@ -177,12 +172,10 @@
*/
public void setSecondTask(Task task) {
mSecondTaskId = task.key.id;
- mSecondTaskPackageName = task.getTopComponent().getPackageName();
}
public void setSecondTask(Intent intent) {
mSecondTaskIntent = intent;
- mSecondTaskPackageName = intent.getComponent().getPackageName();
}
/**
@@ -205,9 +198,8 @@
*/
public void launchTasks(int taskId1, int taskId2, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
- launchTasks(taskId1, null /* intent1 */, null /* packageName1 */, taskId2,
- null /* intent2 */, null /* packageName2 */, stagePosition, callback,
- freezeTaskList, splitRatio, null);
+ launchTasks(taskId1, null /* intent1 */, taskId2, null /* intent2 */, stagePosition,
+ callback, freezeTaskList, splitRatio, null);
}
/**
@@ -216,12 +208,12 @@
* fill in intent with a taskId2 are set.
* @param intent1 is null when split is initiated from Overview
* @param stagePosition representing location of task1
- * @param shellInstanceId loggingId to be used by shell, will be non-null for actions that create
- * a split instance, null for cases that bring existing instaces to the
+ * @param shellInstanceId loggingId to be used by shell, will be non-null for actions that
+ * create a split instance, null for cases that bring existing instaces to the
* foreground (quickswitch, launching previous pairs from overview)
*/
- public void launchTasks(int taskId1, @Nullable Intent intent1, String packageName1, int taskId2,
- @Nullable Intent intent2, String packageName2, @StagePosition int stagePosition,
+ public void launchTasks(int taskId1, @Nullable Intent intent1, int taskId2,
+ @Nullable Intent intent2, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio,
@Nullable InstanceId shellInstanceId) {
TestLogging.recordEvent(
@@ -240,14 +232,16 @@
null /* options2 */, stagePosition, splitRatio, remoteTransition,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcut(intent1, packageName2, options1, taskId2, stagePosition,
- splitRatio, remoteTransition, shellInstanceId);
+ launchIntentOrShortcut(intent1, options1, taskId2, stagePosition, splitRatio,
+ remoteTransition, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcut(intent2, packageName1, options1, taskId1,
+ launchIntentOrShortcut(intent2, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
shellInstanceId);
} else {
- // TODO: the case when both split apps are started from an intent.
+ mSystemUiProxy.startIntents(getPendingIntent(intent1), options1.toBundle(),
+ getPendingIntent(intent2), null /* options2 */, stagePosition,
+ splitRatio, remoteTransition, shellInstanceId);
}
} else {
final RemoteSplitLaunchAnimationRunner animationRunner =
@@ -261,21 +255,22 @@
taskId2, null /* options2 */, stagePosition, splitRatio, adapter,
shellInstanceId);
} else if (intent2 == null) {
- launchIntentOrShortcutLegacy(intent1, packageName2, options1, taskId2,
- stagePosition, splitRatio, adapter, shellInstanceId);
+ launchIntentOrShortcutLegacy(intent1, options1, taskId2, stagePosition, splitRatio,
+ adapter, shellInstanceId);
} else if (intent1 == null) {
- launchIntentOrShortcutLegacy(intent2, packageName1, options1, taskId1,
+ launchIntentOrShortcutLegacy(intent2, options1, taskId1,
getOppositeStagePosition(stagePosition), splitRatio, adapter,
shellInstanceId);
} else {
- // TODO: the case when both split apps are started from an intent.
+ mSystemUiProxy.startIntentsWithLegacyTransition(getPendingIntent(intent1),
+ options1.toBundle(), getPendingIntent(intent2), null /* options2 */,
+ stagePosition, splitRatio, adapter, shellInstanceId);
}
}
}
- private void launchIntentOrShortcut(Intent intent, String otherTaskPackageName,
- ActivityOptions options1, int taskId, @StagePosition int stagePosition,
- float splitRatio, RemoteTransition remoteTransition,
+ private void launchIntentOrShortcut(Intent intent, ActivityOptions options1, int taskId,
+ @StagePosition int stagePosition, float splitRatio, RemoteTransition remoteTransition,
@Nullable InstanceId shellInstanceId) {
PendingIntent pendingIntent = getPendingIntent(intent);
final ShortcutInfo shortcutInfo = getShortcutInfo(intent,
@@ -285,16 +280,14 @@
options1.toBundle(), taskId, null /* options2 */, stagePosition,
splitRatio, remoteTransition, shellInstanceId);
} else {
- mSystemUiProxy.startIntentAndTask(pendingIntent,
- getFillInIntent(intent, otherTaskPackageName), options1.toBundle(), taskId,
+ mSystemUiProxy.startIntentAndTask(pendingIntent, options1.toBundle(), taskId,
null /* options2 */, stagePosition, splitRatio, remoteTransition,
shellInstanceId);
}
}
- private void launchIntentOrShortcutLegacy(Intent intent, String otherTaskPackageName,
- ActivityOptions options1, int taskId, @StagePosition int stagePosition,
- float splitRatio, RemoteAnimationAdapter adapter,
+ private void launchIntentOrShortcutLegacy(Intent intent, ActivityOptions options1, int taskId,
+ @StagePosition int stagePosition, float splitRatio, RemoteAnimationAdapter adapter,
@Nullable InstanceId shellInstanceId) {
PendingIntent pendingIntent = getPendingIntent(intent);
final ShortcutInfo shortcutInfo = getShortcutInfo(intent,
@@ -305,9 +298,8 @@
splitRatio, adapter, shellInstanceId);
} else {
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(pendingIntent,
- getFillInIntent(intent, otherTaskPackageName), options1.toBundle(), taskId,
- null /* options2 */, stagePosition, splitRatio, adapter,
- shellInstanceId);
+ options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
+ adapter, shellInstanceId);
}
}
@@ -318,19 +310,6 @@
: PendingIntent.getActivity(mContext, 0, intent, FLAG_MUTABLE));
}
- private Intent getFillInIntent(Intent intent, String otherTaskPackageName) {
- if (intent == null) {
- return null;
- }
-
- Intent fillInIntent = new Intent();
- if (TextUtils.equals(intent.getComponent().getPackageName(), otherTaskPackageName)) {
- fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- }
- return fillInIntent;
- }
-
-
public @StagePosition int getActiveSplitStagePosition() {
return mStagePosition;
}
@@ -464,10 +443,8 @@
public void resetState() {
mInitialTaskId = INVALID_TASK_ID;
mInitialTaskIntent = null;
- mInitialTaskPackageName = null;
mSecondTaskId = INVALID_TASK_ID;
mSecondTaskIntent = null;
- mSecondTaskPackageName = null;
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
new file mode 100644
index 0000000..e8a4b0a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
+
+import android.content.Intent;
+import android.view.View;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+
+/** Handles when the stage split lands on the home screen. */
+public class SplitToWorkspaceController {
+
+ private final Launcher mLauncher;
+ private final SplitSelectStateController mController;
+
+ public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) {
+ mLauncher = launcher;
+ mController = controller;
+ }
+
+ /**
+ * Handles second app selection from stage split. If the item can't be opened in split or
+ * it's not in stage split state, we pass it onto Launcher's default item click handler.
+ */
+ public boolean handleSecondAppSelectionForSplit(View view) {
+ if ((!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
+ && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get())
+ || !mController.isSplitSelectActive()) {
+ return false;
+ }
+ Object tag = view.getTag();
+ Intent intent;
+ if (tag instanceof WorkspaceItemInfo) {
+ final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
+ intent = workspaceItemInfo.intent;
+ } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
+ final com.android.launcher3.model.data.AppInfo appInfo =
+ (com.android.launcher3.model.data.AppInfo) tag;
+ intent = appInfo.intent;
+ } else {
+ return false;
+ }
+ mController.setSecondTask(intent);
+ mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
+ mController.getFirstFloatingTaskView()));
+ return true;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
index 3587bd1..24d8326 100644
--- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
@@ -101,33 +101,6 @@
});
}
- /**
- * Handles second app selection from stage split. If the item can't be opened in split or
- * it's not in stage split state, we pass it onto Launcher's default item click handler.
- */
- public boolean handleSecondAppSelectionForSplit(View view) {
- if (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
- || !mController.isSplitSelectActive()) {
- return false;
- }
- Object tag = view.getTag();
- Intent intent;
- if (tag instanceof WorkspaceItemInfo) {
- final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
- intent = workspaceItemInfo.intent;
- } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
- final com.android.launcher3.model.data.AppInfo appInfo =
- (com.android.launcher3.model.data.AppInfo) tag;
- intent = appInfo.intent;
- } else {
- return false;
- }
- mController.setSecondTask(intent);
- mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
- mController.getFirstFloatingTaskView()));
- return true;
- }
-
public void onDestroy() {
mOverviewComponentObserver.onDestroy();
}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 5c37da1..b476c12 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -322,7 +322,7 @@
boolean isRtlEnabled = !mIsRecentsRtl;
mPositionHelper.updateThumbnailMatrix(
mThumbnailPosition, mThumbnailData, mTaskRect.width(), mTaskRect.height(),
- mDp.widthPx, mDp.taskbarSize, mDp.isTablet,
+ mDp.widthPx, mDp.heightPx, mDp.taskbarSize, mDp.isTablet,
mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
if (DEBUG) {
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 2abd715..8c43fd1 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -288,7 +288,7 @@
public RunnableList launchTasks() {
SystemUiProxy.INSTANCE.get(getContext()).showDesktopApps();
getRecentsView().startHome();
- return new RunnableList();
+ return null;
}
@Nullable
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 35414a6..5a26f32 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -41,6 +41,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCH_FROM_STAGED_APP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -74,9 +75,12 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.WindowConfiguration;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.LocusId;
import android.content.res.Configuration;
+import android.graphics.Bitmap;
import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -494,6 +498,9 @@
private boolean mOverviewFullscreenEnabled;
private boolean mOverviewSelectEnabled;
+ private boolean mShouldClampScrollOffset;
+ private int mClampedScrollOffsetBound;
+
private float mAdjacentPageHorizontalOffset = 0;
protected float mTaskViewsSecondaryTranslation = 0;
protected float mTaskViewsPrimarySplitTranslation = 0;
@@ -661,8 +668,6 @@
private TaskView mSecondSplitHiddenView;
@Nullable
private SplitBounds mSplitBoundsConfig;
- private final Toast mSplitToast = Toast.makeText(getContext(),
- R.string.toast_split_select_app, Toast.LENGTH_SHORT);
private final Toast mSplitUnsupportedToast = Toast.makeText(getContext(),
R.string.toast_split_app_unsupported, Toast.LENGTH_SHORT);
@@ -750,6 +755,8 @@
mSplitPlaceholderInset = getResources().getDimensionPixelSize(
R.dimen.split_placeholder_inset);
mSquaredTouchSlop = squaredTouchSlop(context);
+ mClampedScrollOffsetBound = getResources().getDimensionPixelSize(
+ R.dimen.transient_taskbar_clamped_offset_bound);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
mEmptyIcon.setCallback(this);
@@ -1212,6 +1219,21 @@
return null;
}
+ /**
+ * Returns a {@link TaskView} that has ComponentName matching {@code componentName} or null if
+ * no match.
+ */
+ @Nullable
+ public TaskView getTaskViewByComponentName(ComponentName componentName) {
+ for (int i = 0; i < getTaskViewCount(); i++) {
+ TaskView taskView = requireTaskViewAt(i);
+ if (taskView.getTask().key.sourceComponent.equals(componentName)) {
+ return taskView;
+ }
+ }
+ return null;
+ }
+
public void setOverviewStateEnabled(boolean enabled) {
mOverviewStateEnabled = enabled;
updateTaskStackListenerState();
@@ -2241,8 +2263,14 @@
for (int i = 0; i < getTaskViewCount(); i++) {
requireTaskViewAt(i).setOrientationState(mOrientationState);
}
+ boolean shouldRotateMenuForFakeRotation =
+ !mOrientationState.isRecentsActivityRotationAllowed();
+ if (!shouldRotateMenuForFakeRotation) {
+ return;
+ }
TaskMenuView tv = (TaskMenuView) getTopOpenViewWithType(mActivity, TYPE_TASK_MENU);
if (tv != null) {
+ // Rotation is supported on phone (details at b/254198019#comment4)
tv.onRotationChanged();
}
}
@@ -2880,6 +2908,11 @@
false /* fadeWithThumbnail */, true /* isStagedTask */);
}
+ // TODO (b/257513449): Launch animation not fully complete. OK to remove flag once it is.
+ if (ENABLE_LAUNCH_FROM_STAGED_APP.get()) {
+ mFirstFloatingTaskView.setOnClickListener(this::animateToFullscreen);
+ }
+
// SplitInstructionsView: animate in
safeRemoveDragLayerView(mSplitInstructionsView);
mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
@@ -2923,6 +2956,34 @@
});
}
+ private void animateToFullscreen(View view) {
+ FloatingTaskView stagedTaskView = (FloatingTaskView) view;
+
+ boolean isTablet = mActivity.getDeviceProfile().isTablet;
+ int duration = isTablet
+ ? SplitAnimationTimings.TABLET_CONFIRM_DURATION
+ : SplitAnimationTimings.PHONE_CONFIRM_DURATION;
+
+ PendingAnimation pendingAnimation = new PendingAnimation(duration);
+
+ Rect firstTaskStartingBounds = new Rect();
+ Rect firstTaskEndingBounds = new Rect();
+
+ stagedTaskView.getBoundsOnScreen(firstTaskStartingBounds);
+ mActivity.getDragLayer().getBoundsOnScreen(firstTaskEndingBounds);
+
+ stagedTaskView.addConfirmAnimation(
+ pendingAnimation,
+ new RectF(firstTaskStartingBounds),
+ firstTaskEndingBounds,
+ false /* fadeWithThumbnail */,
+ true /* isStagedTask */);
+
+ pendingAnimation.addEndListener(success -> launchStagedTask());
+
+ pendingAnimation.buildAnim().start();
+ }
+
/**
* Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
* @param dismissedTaskView the {@link TaskView} to be dismissed
@@ -3521,7 +3582,8 @@
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
!mActivity.getDeviceProfile().isTablet);
- mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, getTaskViewCount() <= 1);
+ mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK,
+ !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get() && getTaskViewCount() <= 1);
}
/**
@@ -4208,7 +4270,7 @@
public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
mSplitSelectSource = splitSelectSource;
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
- splitSelectSource.position.stagePosition, splitSelectSource.mItemInfo,
+ splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
splitSelectSource.splitEvent);
}
@@ -4230,24 +4292,39 @@
* Confirms the selection of the next split task. The extra data is passed through because the
* user may be selecting a subtask in a group.
*
+ * @param containerTaskView If our second selected app is currently running in Recents, this is
+ * the "container" TaskView from Recents. If we are starting a fresh
+ * instance of the app from an Intent, this will be null.
+ * @param task The Task corresponding to our second selected app. If we are starting a fresh
+ * instance of the app from an Intent, this will be null.
+ * @param drawable The Drawable corresponding to our second selected app's icon.
+ * @param secondView The View representing the current space on the screen where the second app
+ * is (either the ThumbnailView or the tapped icon).
+ * @param intent If we are launching a fresh instance of the app, this is the Intent for it. If
+ * the second app is already running in Recents, this will be null.
* @return true if waiting for confirmation of second app or if split animations are running,
* false otherwise
*/
- public boolean confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
- TaskThumbnailView thumbnailView) {
+ public boolean confirmSplitSelect(TaskView containerTaskView, Task task, Drawable drawable,
+ View secondView, @Nullable Bitmap thumbnail, Intent intent) {
if (canLaunchFullscreenTask()) {
return false;
}
if (mSplitSelectStateController.isBothSplitAppsConfirmed()) {
return true;
}
- mSplitToast.cancel();
- if (!task.isDockable) {
- // Task not split screen supported
- mSplitUnsupportedToast.show();
- return true;
+ // Second task is selected either as an already-running Task or an Intent
+ if (task != null) {
+ if (!task.isDockable) {
+ // Task does not support split screen
+ mSplitUnsupportedToast.show();
+ return true;
+ }
+ mSplitSelectStateController.setSecondTask(task);
+ } else {
+ mSplitSelectStateController.setSecondTask(intent);
}
- mSplitSelectStateController.setSecondTask(task);
+
RectF secondTaskStartingBounds = new RectF();
Rect secondTaskEndingBounds = new Rect();
// TODO(194414938) starting bounds seem slightly off, investigate
@@ -4255,11 +4332,8 @@
Rect firstTaskEndingBounds = mTempRect;
boolean isTablet = mActivity.getDeviceProfile().isTablet;
- int duration = isTablet
- ? SplitAnimationTimings.TABLET_CONFIRM_DURATION
- : SplitAnimationTimings.PHONE_CONFIRM_DURATION;
- PendingAnimation pendingAnimation = new PendingAnimation(duration);
SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
+ PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
@@ -4274,9 +4348,9 @@
false /* fadeWithThumbnail */, true /* isStagedTask */);
safeRemoveDragLayerView(mSecondFloatingTaskView);
- mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
- thumbnailView, thumbnailView.getThumbnail(),
- iconView.getDrawable(), secondTaskStartingBounds);
+
+ mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity, secondView,
+ thumbnail, drawable, secondTaskStartingBounds);
mSecondFloatingTaskView.setAlpha(1);
mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
@@ -4292,7 +4366,9 @@
});
mSecondSplitHiddenView = containerTaskView;
- mSecondSplitHiddenView.setThumbnailVisibility(INVISIBLE);
+ if (mSecondSplitHiddenView != null) {
+ mSecondSplitHiddenView.setThumbnailVisibility(INVISIBLE);
+ }
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Second tile selected");
@@ -4609,6 +4685,16 @@
return mPendingAnimation;
}
+ protected void launchStagedTask() {
+ if (mSplitHiddenTaskView != null) {
+ // Split staging was started from an existing running task (in Overview)
+ mSplitHiddenTaskView.launchTask(success -> resetFromSplitSelectionState());
+ } else {
+ // Split staging was started from a new intent (from app menu in Home/AllApps)
+ mActivity.startActivity(mSplitSelectSource.intent);
+ }
+ }
+
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
resetTaskVisuals();
@@ -4974,9 +5060,35 @@
}
/**
+ * Sets whether or not we should clamp the scroll offset.
+ * This is used to avoid x-axis movement when swiping up transient taskbar.
+ * Should only be set at the beginning and end of the gesture, otherwise a jump may occur.
+ * @param clampScrollOffset When true, we clamp the scroll to 0 before the clamp threshold is
+ * met.
+ */
+ public void setClampScrollOffset(boolean clampScrollOffset) {
+ mShouldClampScrollOffset = clampScrollOffset;
+ }
+
+ /**
* Returns how many pixels the page is offset on the currently laid out dominant axis.
*/
public int getScrollOffset(int pageIndex) {
+ int unboundedOffset = getUnclampedScrollOffset(pageIndex);
+ if (!mShouldClampScrollOffset) {
+ return unboundedOffset;
+ }
+ if (Math.abs(unboundedOffset) < mClampedScrollOffsetBound) {
+ return 0;
+ }
+ return unboundedOffset
+ - Math.round(Math.signum(unboundedOffset) * mClampedScrollOffsetBound);
+ }
+
+ /**
+ * Returns how many pixels the page is offset on the currently laid out dominant axis.
+ */
+ private int getUnclampedScrollOffset(int pageIndex) {
if (pageIndex == -1) {
return 0;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 6792dc5..904c944 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -473,8 +473,8 @@
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
DeviceProfile dp = mActivity.getDeviceProfile();
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
- getMeasuredWidth(), getMeasuredHeight(), dp.widthPx, dp.taskbarSize,
- dp.isTablet, currentRotation, isRtl);
+ getMeasuredWidth(), getMeasuredHeight(), dp.widthPx, dp.heightPx,
+ dp.taskbarSize, dp.isTablet, currentRotation, isRtl);
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.getMatrix());
mPaint.setShader(mBitmapShader);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 527a0d1..4de69cd 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -20,7 +20,6 @@
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
@@ -501,7 +500,7 @@
return;
}
mModalness = modalness;
- mIconView.setAlpha(comp(modalness));
+ mIconView.setAlpha(1 - modalness);
mDigitalWellBeingToast.updateBannerOffset(modalness,
mCurrentFullscreenParams.mCurrentDrawnInsets.top
+ mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
@@ -621,7 +620,8 @@
TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
if (container != null) {
return getRecentsView().confirmSplitSelect(this, container.getTask(),
- container.getIconView(), container.getThumbnailView());
+ container.getIconView().getDrawable(), container.getThumbnailView(),
+ container.getThumbnailView().getThumbnail(), /* intent */ null);
}
return false;
}
@@ -725,13 +725,14 @@
/**
* Launch of the current task (both live and inactive tasks) with an animation.
*/
+ @Nullable
public RunnableList launchTasks() {
RecentsView recentsView = getRecentsView();
RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
- RunnableList runnableList = new RunnableList();
if (isRunningTask() && remoteTargetHandles != null) {
if (!mIsClickableAsLiveTile) {
- return runnableList;
+ Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.");
+ return null;
}
mIsClickableAsLiveTile = false;
@@ -756,11 +757,16 @@
if (targets == null) {
// If the recents animation is cancelled somehow between the parent if block and
// here, try to launch the task as a non live tile task.
- launchTaskAnimated();
+ RunnableList runnableList = launchTaskAnimated();
+ if (runnableList == null) {
+ Log.e(TAG, "Recents animation cancelled and cannot launch task as non-live tile"
+ + "; returning to home");
+ }
mIsClickableAsLiveTile = true;
return runnableList;
}
+ RunnableList runnableList = new RunnableList();
AnimatorSet anim = new AnimatorSet();
TaskViewUtils.composeRecentsLaunchAnimator(
anim, this, targets.apps,
@@ -797,10 +803,10 @@
});
anim.start();
recentsView.onTaskLaunchedInLiveTileMode();
+ return runnableList;
} else {
return launchTaskAnimated();
}
- return runnableList;
}
/**
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index e2774c0..2c5825f 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -39,6 +39,7 @@
protected TestRule getRulesInsideActivityMonitor() {
return RuleChain.
outerRule(new NavigationModeSwitchRule(mLauncher)).
+ around(new TaskbarModeSwitchRule(mLauncher)).
around(super.getRulesInsideActivityMonitor());
}
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index 4785350..0c96539 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -20,14 +20,17 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.DeviceProfileBaseTest
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
import com.android.quickstep.views.TaskView.FullscreenDrawParams
import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
+import com.android.wm.shell.util.SplitBounds
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
+import kotlin.math.roundToInt
/**
* Test for FullscreenDrawParams class.
@@ -36,6 +39,7 @@
@RunWith(AndroidJUnit4::class)
class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
+ private val TASK_SCALE = 0.7f
private var mThumbnailData: ThumbnailData = mock(ThumbnailData::class.java)
private val mPreviewPositionHelper = PreviewPositionHelper()
@@ -51,34 +55,93 @@
initializeVarsForTablet()
val dp = newDP()
val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = dp.widthPx / 2
- val canvasHeight = dp.heightPx / 2
+ val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
+ val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
val currentRotation = 0
val isRtl = false
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
- canvasHeight, dp.widthPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
isRtl)
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
- val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize / 2f)
+ val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize * TASK_SCALE)
assertThat(params.mCurrentDrawnInsets)
.isEqualTo(expectedClippedInsets)
}
@Test
+ fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets_splitPortrait() {
+ initializeVarsForTablet()
+ val dp = newDP()
+ val previewRect = Rect(0, 0, 100, 100)
+ val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
+ val canvasHeight = (dp.heightPx * TASK_SCALE / 2).roundToInt()
+ val currentRotation = 0
+ val isRtl = false
+ // portrait/vertical split apps
+ val dividerSize = 10
+ val splitBounds = SplitBounds(
+ Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
+ Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
+ 0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
+ mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
+
+ mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
+ canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ isRtl)
+ params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+
+ // Probably unhelpful, but also unclear how to test otherwise ¯\_(ツ)_/¯
+ val fullscreenTaskHeight = (dp.heightPx - dp.taskbarSize) *
+ (1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
+ val canvasScreenRatio = canvasHeight / fullscreenTaskHeight
+ val expectedBottomHint = dp.taskbarSize * canvasScreenRatio
+ assertThat(params.mCurrentDrawnInsets.bottom)
+ .isWithin(1f).of(expectedBottomHint)
+ }
+
+ @Test
+ fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets_splitLandscape() {
+ initializeVarsForTablet(isLandscape = true)
+ val dp = newDP()
+ val previewRect = Rect(0, 0, 100, 100)
+ val canvasWidth = (dp.widthPx * TASK_SCALE / 2).roundToInt()
+ val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
+ val currentRotation = 0
+ val isRtl = false
+ // portrait/vertical split apps
+ val dividerSize = 10
+ val splitBounds = SplitBounds(
+ Rect(0, 0, (dp.widthPx - dividerSize) / 2, dp.heightPx),
+ Rect((dp.widthPx + dividerSize) / 2, 0, dp.widthPx, dp.heightPx),
+ 0 /*lefTopTaskId*/, 0 /*rightBottomTaskId*/)
+ mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
+
+ mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
+ canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ isRtl)
+ params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
+
+ assertThat(params.mCurrentDrawnInsets.bottom)
+ .isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
+ }
+
+ @Test
fun setFullProgress_currentDrawnInsets_doNotClipTaskbarSizeFromBottomForPhones() {
initializeVarsForPhone()
val dp = newDP()
val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = dp.widthPx / 2
- val canvasHeight = dp.heightPx / 2
+ val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
+ val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
val currentRotation = 0
val isRtl = false
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
- canvasHeight, dp.widthPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ canvasHeight, dp.widthPx, dp.heightPx, dp.taskbarSize, dp.isTablet, currentRotation,
isRtl)
params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index e5e2cf3..eded1c9 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -51,7 +51,7 @@
/**
* Test rule that allows executing a test with Quickstep on and then Quickstep off.
- * The test should be annotated with @QuickstepOnOff.
+ * The test should be annotated with @NavigationModeSwitch.
*/
public class NavigationModeSwitchRule implements TestRule {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 9337cb5..0b8bc10 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -17,6 +17,8 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+
import static junit.framework.TestCase.assertEquals;
import android.content.Intent;
@@ -27,6 +29,7 @@
import com.android.launcher3.tapl.Taskbar;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import org.junit.After;
import org.junit.Assume;
@@ -53,21 +56,25 @@
TaplTestsLauncher3.initialize(this);
startAppFast(CALCULATOR_APP_PACKAGE);
+ mLauncher.enableBlockTimeout(true);
mLauncher.showTaskbarIfHidden();
}
@After
public void tearDown() {
mLauncher.useDefaultWorkspaceLayoutOnReload();
+ mLauncher.enableBlockTimeout(false);
}
@Test
+ @TaskbarModeSwitch(mode = PERSISTENT)
public void testHideShowTaskbar() {
getTaskbar().hide();
mLauncher.getLaunchedAppState().showTaskbar();
}
@Test
+ @TaskbarModeSwitch(mode = PERSISTENT)
public void testHideTaskbarPersistsOnRecreate() {
getTaskbar().hide();
mLauncher.recreateTaskbar();
@@ -75,16 +82,19 @@
}
@Test
+ @TaskbarModeSwitch
public void testLaunchApp() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
}
@Test
+ @TaskbarModeSwitch
public void testOpenMenu() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
}
@Test
+ @TaskbarModeSwitch
public void testLaunchShortcut() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME)
.openDeepShortcutMenu()
@@ -95,6 +105,7 @@
@Test
@ScreenRecord // b/231615831
@PortraitLandscape
+ @TaskbarModeSwitch
public void testLaunchAppInSplitscreen() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
@@ -103,6 +114,7 @@
@Test
@ScreenRecord // b/231615831
@PortraitLandscape
+ @TaskbarModeSwitch
public void testLaunchShortcutInSplitscreen() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME)
.openDeepShortcutMenu()
@@ -111,16 +123,19 @@
}
@Test
+ @TaskbarModeSwitch
public void testLaunchApp_FromTaskbarAllApps() throws Exception {
getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
}
@Test
+ @TaskbarModeSwitch
public void testOpenMenu_FromTaskbarAllApps() throws Exception {
getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
}
@Test
+ @TaskbarModeSwitch
public void testLaunchShortcut_FromTaskbarAllApps() throws Exception {
getTaskbar().openAllApps()
.getAppIcon(TEST_APP_NAME)
@@ -132,6 +147,7 @@
@Test
@ScreenRecord // b/231615831
@PortraitLandscape
+ @TaskbarModeSwitch
public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
getTaskbar().openAllApps()
.getAppIcon(TEST_APP_NAME)
@@ -141,6 +157,7 @@
@Test
@ScreenRecord // b/231615831
@PortraitLandscape
+ @TaskbarModeSwitch
public void testLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
getTaskbar().openAllApps()
.getAppIcon(TEST_APP_NAME)
diff --git a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
new file mode 100644
index 0000000..9e41f74
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.ALL;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.rule.FailureWatcher;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Test rule that allows executing a test multiple times with different conditions
+ * ie. with transient taskbar enabled and disabled.
+ * The test should be annotated with @TaskbarModeSwitch.
+ */
+public class TaskbarModeSwitchRule implements TestRule {
+
+ static final String TAG = "TaskbarModeSwitchRule";
+
+ public static final int WAIT_TIME_MS = 10000;
+
+ public enum Mode {
+ TRANSIENT, PERSISTENT, ALL
+ }
+
+ // Annotation for tests that need to be run with quickstep enabled and disabled.
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public @interface TaskbarModeSwitch {
+ Mode mode() default ALL;
+ }
+
+ private final LauncherInstrumentation mLauncher;
+
+ public TaskbarModeSwitchRule(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ if (TestHelpers.isInLauncherProcess()
+ && description.getAnnotation(TaskbarModeSwitch.class) != null) {
+ Mode mode = description.getAnnotation(TaskbarModeSwitch.class).mode();
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ mLauncher.enableDebugTracing();
+ final boolean wasTransientTaskbarMode =
+ isTaskbarTransientMode(getInstrumentation().getTargetContext());
+ try {
+ if (mode == TRANSIENT || mode == ALL) {
+ evaluateWithTransientTaskbar();
+ }
+ if (mode == PERSISTENT || mode == ALL) {
+ evaluateWithPersistentTaskbar();
+ }
+ } catch (Throwable e) {
+ Log.e(TAG, "Error", e);
+ throw e;
+ } finally {
+ Log.d(TAG, "In Finally block");
+ setTaskbarMode(mLauncher, wasTransientTaskbarMode, description);
+ }
+ }
+
+ private void evaluateWithPersistentTaskbar() throws Throwable {
+ setTaskbarMode(mLauncher, false, description);
+ base.evaluate();
+ }
+
+ private void evaluateWithTransientTaskbar() throws Throwable {
+ setTaskbarMode(mLauncher, true, description);
+ base.evaluate();
+ }
+ };
+ } else {
+ return base;
+ }
+ }
+
+ private static boolean isTaskbarTransientMode(Context context) {
+ return DisplayController.isTransientTaskbar(context);
+ }
+
+ public static void setTaskbarMode(LauncherInstrumentation launcher,
+ boolean expectTransientTaskbar, Description description) throws Exception {
+ launcher.enableTransientTaskbar(expectTransientTaskbar);
+ launcher.recreateTaskbar();
+
+ Context context = getInstrumentation().getTargetContext();
+ assertTrue(launcher, "Couldn't set taskbar=" + expectTransientTaskbar,
+ isTaskbarTransientMode(context) == expectTransientTaskbar, description);
+
+ AbstractLauncherUiTest.checkDetectedLeaks(launcher);
+ }
+
+ private static void assertTrue(LauncherInstrumentation launcher, String message,
+ boolean condition, Description description) {
+ launcher.checkForAnomaly(true, true);
+ if (!condition) {
+ final AssertionError assertionError = new AssertionError(message);
+ if (description != null) {
+ FailureWatcher.onError(launcher, description, assertionError);
+ }
+ throw assertionError;
+ }
+ }
+}
diff --git a/res/color-night-v31/transient_taskbar_background.xml b/res/color-night-v31/transient_taskbar_background.xml
new file mode 100644
index 0000000..40f6494
--- /dev/null
+++ b/res/color-night-v31/transient_taskbar_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+</selector>
+
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 39f93d9..5518dc8 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -30,11 +30,11 @@
<LinearLayout
android:id="@+id/folder_footer"
android:layout_width="match_parent"
- android:layout_height="@dimen/folder_label_height"
+ android:layout_height="@dimen/folder_footer_height_default"
android:clipChildren="false"
android:orientation="horizontal"
- android:paddingLeft="12dp"
- android:paddingRight="12dp">
+ android:paddingLeft="@dimen/folder_footer_horiz_padding"
+ android:paddingRight="@dimen/folder_footer_horiz_padding">
<com.android.launcher3.folder.FolderNameEditText
android:id="@+id/folder_name"
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 4f15eb5..aa29d8d 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -32,12 +32,12 @@
<string name="split_screen_position_left" msgid="7537793098851830883">"Split left"</string>
<string name="split_screen_position_right" msgid="1569377524925193369">"Split right"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
- <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
+ <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch & hold to move a widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap & hold to move a widget or use custom actions."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch and hold the widget to move it around the home screen"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch & hold the widget to move it around the home screen"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
@@ -54,18 +54,18 @@
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
<string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
- <string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
+ <string name="widget_education_close_button" msgid="8676165703104836580">"Got it"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
<string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Search apps"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Loading apps…"</string>
- <string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="label_application" msgid="8531721983832654978">"App"</string>
<string name="all_apps_label" msgid="5015784846527570951">"All apps"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
<string name="out_of_space" msgid="6455557115204099579">"No room on this home screen"</string>
- <string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
+ <string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favorites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Personal apps list"</string>
@@ -75,13 +75,13 @@
<string name="app_info_drop_target_label" msgid="692894985365717661">"App info"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Install"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Don\'t suggest app"</string>
- <string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
+ <string name="pin_prediction" msgid="4196423321649756498">"Pin Prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="5136500343007704955">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="4820028712156303762">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -101,7 +101,7 @@
<string name="folder_name_format_exact" msgid="8626242716117004803">"Folder: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> items"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Folder: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> or more items"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
@@ -113,7 +113,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="developer_options_title" msgid="700788437593726194">"Developer options"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer Options"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
@@ -125,7 +125,7 @@
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
<string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
- <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon."</string>
<string name="dialog_update" msgid="2178028071796141234">"Update"</string>
<string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
@@ -138,7 +138,7 @@
<string name="action_move" msgid="4339390619886385032">"Move item"</string>
<string name="move_to_empty_cell_description" msgid="5254852678218206889">"Move to row <xliff:g id="NUMBER_0">%1$s</xliff:g> column <xliff:g id="NUMBER_1">%2$s</xliff:g> in <xliff:g id="STRING">%3$s</xliff:g>"</string>
<string name="move_to_position" msgid="6750008980455459790">"Move to position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
- <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favourites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Move to favorites position <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
<string name="item_moved" msgid="4606538322571412879">"Item moved"</string>
<string name="add_to_folder" msgid="9040534766770853243">"Add to folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="add_to_folder_with_app" msgid="4534929978967147231">"Add to folder with <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -146,13 +146,13 @@
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
<string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
- <string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Resize"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
<string name="action_decrease_width" msgid="1374549771083094654">"Decrease width"</string>
<string name="action_decrease_height" msgid="282377193880900022">"Decrease height"</string>
- <string name="widget_resized" msgid="9130327887929620">"Widget re-sized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
- <string name="action_deep_shortcut" msgid="2864038805849372848">"Short cuts"</string>
+ <string name="widget_resized" msgid="9130327887929620">"Widget resized to width <xliff:g id="NUMBER_0">%1$s</xliff:g> height <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="action_deep_shortcut" msgid="2864038805849372848">"Shortcuts"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Shortcuts and notifications"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"Dismiss"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Close"</string>
@@ -161,12 +161,12 @@
<string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Work profile"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Work apps are badged and visible to your IT admin"</string>
- <string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
+ <string name="work_profile_edu_accept" msgid="6069788082535149071">"Got it"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
- <string name="work_apps_paused_body" msgid="261634750995824906">"Your work apps can’t send you notifications, use your battery or access your location"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery or access your location"</string>
+ <string name="work_apps_paused_body" msgid="261634750995824906">"Your work apps can’t send you notifications, use your battery, or access your location"</string>
+ <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery, or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
- <string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
+ <string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Got it"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 9e2d9a4..8b944fe 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -124,7 +124,7 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> instalatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> deskargatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> instalatzeko zain"</string>
- <string name="dialog_update_title" msgid="114234265740994042">"Aplikazioa eguneratu behar da"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Aplikazioa eguneratu egin behar da"</string>
<string name="dialog_update_message" msgid="4176784553982226114">"Ikonoaren aplikazioa ez dago eguneratuta. Lasterbidea berriro gaitzeko, eskuz egunera dezakezu aplikazioa. Bestela, kendu ikonoa."</string>
<string name="dialog_update" msgid="2178028071796141234">"Eguneratu"</string>
<string name="dialog_remove" msgid="6510806469849709407">"Kendu"</string>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 7b2ed8b..09b2d6f 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -43,4 +43,7 @@
<!-- Bottom sheet-->
<dimen name="bottom_sheet_extra_top_padding">300dp</dimen>
+
+ <!-- Folder spaces -->
+ <dimen name="folder_footer_horiz_padding">24dp</dimen>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 283c793..f270b10 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -141,9 +141,12 @@
<attr name="numColumns" format="integer" />
<!-- numSearchContainerColumns defaults to numColumns, if not specified -->
<attr name="numSearchContainerColumns" format="integer" />
+
<!-- numFolderRows & numFolderColumns defaults to numRows & numColumns, if not specified -->
<attr name="numFolderRows" format="integer" />
<attr name="numFolderColumns" format="integer" />
+ <attr name="folderStyle" format="reference" />
+
<!-- numAllAppsColumns defaults to numColumns, if not specified -->
<attr name="numAllAppsColumns" format="integer" />
<!-- Number of columns to use when extending the all-apps size,
@@ -333,19 +336,6 @@
if not specified -->
<attr name="allAppsBorderSpaceTwoPanelLandscapeVertical" format="float" />
- <!-- defaults to minCellHeight if not specified
- when GridDisplayOption#isScalable is true. -->
- <attr name="folderCellHeight" format="float" />
- <!-- defaults to minCellWidth, if not specified -->
- <attr name="folderCellWidth" format="float" />
-
- <!-- defaults to borderSpace, if not specified -->
- <!-- space to be used horizontally and vertically -->
- <attr name="folderBorderSpace" format="float" />
-
- <!-- defaults to folderBorderSpace vertical, if not specified -->
- <attr name="folderTopPadding" format="float" />
-
<!-- defaults to res.hotseat_bar_bottom_space_default, if not specified -->
<attr name="hotseatBarBottomSpace" format="float" />
<!-- defaults to hotseatBarBottomSpace, if not specified -->
@@ -394,6 +384,22 @@
</declare-styleable>
+ <declare-styleable name="FolderDisplayStyle">
+ <!-- defaults to minCellHeight if not specified
+ when GridDisplayOption#isScalable is true. -->
+ <attr name="folderCellHeight" format="dimension" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="folderCellWidth" format="dimension" />
+ <!-- space to be used horizontally and vertically between icons,
+ and to the left and right of folder -->
+ <attr name="folderBorderSpace" format="dimension" />
+ <!-- height of the footer of the folder -->
+ <attr name="folderFooterHeight" format="dimension" />
+ <!-- padding on top of the folder -->
+ <attr name="folderTopPadding" format="dimension" />
+ </declare-styleable>
+
+
<declare-styleable name="CellLayout">
<attr name="containerType" format="integer">
<enum name="workspace" value="0" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8f48ec8..db604f2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -255,7 +255,7 @@
<dimen name="folder_cell_y_padding">6dp</dimen>
<!-- label text size = workspace text size multiplied by this scale -->
<dimen name="folder_label_text_scale">1.14</dimen>
- <dimen name="folder_label_height">56dp</dimen>
+ <dimen name="folder_footer_height_default">56dp</dimen>
<dimen name="folder_content_padding_left_right">8dp</dimen>
<dimen name="folder_content_padding_top">16dp</dimen>
@@ -333,7 +333,7 @@
<!-- Snackbar -->
<dimen name="snackbar_height">48dp</dimen>
- <dimen name="snackbar_content_height">32dp</dimen>
+ <dimen name="snackbar_content_height">48dp</dimen>
<dimen name="snackbar_padding">8dp</dimen>
<dimen name="snackbar_min_margin_left_right">6dp</dimen>
<dimen name="snackbar_max_margin_left_right">72dp</dimen>
@@ -368,6 +368,7 @@
<dimen name="transient_taskbar_shadow_blur">0dp</dimen>
<dimen name="transient_taskbar_key_shadow_distance">0dp</dimen>
<dimen name="transient_taskbar_stashed_size">0dp</dimen>
+ <dimen name="transient_taskbar_clamped_offset_bound">0dp</dimen>
<!-- Note that this applies to both sides of all icons, so visible space is double this. -->
<dimen name="transient_taskbar_icon_spacing">0dp</dimen>
<!-- Note that this applies to both sides of all icons, so visible space is double this. -->
@@ -387,6 +388,9 @@
<dimen name="taskbar_app_window_threshold">0dp</dimen>
<dimen name="taskbar_home_overview_threshold">0dp</dimen>
<dimen name="taskbar_catch_up_threshold">0dp</dimen>
+ <dimen name="taskbar_nav_threshold_v2">0dp</dimen>
+ <dimen name="taskbar_app_window_threshold_v2">0dp</dimen>
+ <dimen name="taskbar_home_overview_threshold_v2">0dp</dimen>
<!-- Size of the maximum radius for the enforced rounded rectangles. -->
<dimen name="enforced_rounded_corner_max_radius">16dp</dimen>
@@ -441,4 +445,8 @@
<!-- State transition -->
<item name="workspace_content_scale" format="float" type="dimen">0.97</item>
+
+ <!-- Folder spaces -->
+ <dimen name="folder_top_padding_default">24dp</dimen>
+ <dimen name="folder_footer_horiz_padding">20dp</dimen>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index d0be420..9e75a31 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -309,4 +309,13 @@
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
+
+ <style name="FolderDefaultStyle">
+ <item name="folderTopPadding">24dp</item>
+ <item name="folderCellHeight">94dp</item>
+ <item name="folderCellWidth">80dp</item>
+ <item name="folderBorderSpace">16dp</item>
+ <item name="folderFooterHeight">56dp</item>
+ </style>
+
</resources>
diff --git a/res/xml/paddings_handhelds.xml b/res/xml/paddings_handhelds.xml
new file mode 100644
index 0000000..b9549a6
--- /dev/null
+++ b/res/xml/paddings_handhelds.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Putting in the test/xml folder gives an error that maxEmptySpace doesn't exist -->
+<device-paddings xmlns:launcher="http://schemas.android.com/apk/res-auto" >
+
+ <device-padding
+ launcher:maxEmptySpace="9999dp">
+ <workspaceTopPadding
+ launcher:a="0.48"
+ launcher:b="0"/>
+ <workspaceBottomPadding
+ launcher:a="0.52"
+ launcher:b="0"/>
+ <hotseatBottomPadding
+ launcher:a="0"
+ launcher:b="0"/>
+ </device-padding>
+</device-paddings>
\ No newline at end of file
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 73acd87..28d4a9f 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -102,13 +102,15 @@
| TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU
| TYPE_ICON_SURFACE | TYPE_DRAG_DROP_POPUP | TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP
| TYPE_WIDGETS_EDUCATION_DIALOG | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS
- | TYPE_OPTIONS_POPUP_DIALOG | TYPE_ADD_TO_HOME_CONFIRMATION;
+ | TYPE_OPTIONS_POPUP_DIALOG | TYPE_ADD_TO_HOME_CONFIRMATION
+ | TYPE_TASKBAR_OVERLAY_PROXY;
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
| TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE | TYPE_WIDGETS_EDUCATION_DIALOG
- | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS | TYPE_OPTIONS_POPUP_DIALOG;
+ | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS | TYPE_OPTIONS_POPUP_DIALOG
+ | TYPE_TASKBAR_OVERLAY_PROXY;
public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_LISTENER
& ~TYPE_ALL_APPS_EDU;
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 75e89b2..eb6d096 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -2,7 +2,6 @@
import static android.os.Process.myUserHandle;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
@@ -12,6 +11,7 @@
import android.database.Cursor;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -21,7 +21,7 @@
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.ContentWriter;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherWidgetHolder;
public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
@@ -32,7 +32,7 @@
if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) {
int hostId = intent.getIntExtra(AppWidgetManager.EXTRA_HOST_ID, 0);
Log.d(TAG, "Widget ID map received for host:" + hostId);
- if (hostId != LauncherAppWidgetHost.APPWIDGET_HOST_ID) {
+ if (hostId != LauncherWidgetHolder.APPWIDGET_HOST_ID) {
return;
}
@@ -50,11 +50,11 @@
* Updates the app widgets whose id has changed during the restore process.
*/
@WorkerThread
- public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
- AppWidgetHost appWidgetHost = new LauncherAppWidgetHost(context);
+ public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds,
+ @NonNull LauncherWidgetHolder holder) {
if (WidgetsModel.GO_DISABLE_WIDGETS) {
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
- appWidgetHost.deleteHost();
+ holder.deleteHost();
return;
}
if (!RestoreDbTask.isPending(context)) {
@@ -63,7 +63,7 @@
Log.e(TAG, "Skipping widget ID remap as DB already in use");
for (int widgetId : newWidgetIds) {
Log.d(TAG, "Deleting widgetId: " + widgetId);
- appWidgetHost.deleteAppWidgetId(widgetId);
+ holder.deleteAppWidgetId(widgetId);
}
return;
}
@@ -100,7 +100,7 @@
try {
if (!cursor.moveToFirst()) {
// The widget no long exists.
- appWidgetHost.deleteAppWidgetId(newWidgetIds[i]);
+ holder.deleteAppWidgetId(newWidgetIds[i]);
}
} finally {
cursor.close();
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 64666b0..efdd5e1 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import android.appwidget.AppWidgetHost;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@@ -48,6 +47,7 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -74,7 +74,7 @@
private static final String FORMATTED_LAYOUT_RES = "default_layout_%dx%d";
private static final String LAYOUT_RES = "default_layout";
- static AutoInstallsLayout get(Context context, AppWidgetHost appWidgetHost,
+ static AutoInstallsLayout get(Context context, LauncherWidgetHolder appWidgetHolder,
LayoutParserCallback callback) {
Pair<String, Resources> customizationApkInfo = PackageManagerHelper.findSystemApk(
ACTION_LAUNCHER_CUSTOMIZATION, context.getPackageManager());
@@ -109,7 +109,7 @@
Log.e(TAG, "Layout definition not found in package: " + pkg);
return null;
}
- return new AutoInstallsLayout(context, appWidgetHost, callback, targetRes, layoutId,
+ return new AutoInstallsLayout(context, appWidgetHolder, callback, targetRes, layoutId,
TAG_WORKSPACE);
}
@@ -156,7 +156,7 @@
@Thunk
final Context mContext;
@Thunk
- final AppWidgetHost mAppWidgetHost;
+ final LauncherWidgetHolder mAppWidgetHolder;
protected final LayoutParserCallback mCallback;
protected final PackageManager mPackageManager;
@@ -174,17 +174,17 @@
protected SQLiteDatabase mDb;
- public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
+ public AutoInstallsLayout(Context context, LauncherWidgetHolder appWidgetHolder,
LayoutParserCallback callback, Resources res,
int layoutId, String rootTag) {
- this(context, appWidgetHost, callback, res, () -> res.getXml(layoutId), rootTag);
+ this(context, appWidgetHolder, callback, res, () -> res.getXml(layoutId), rootTag);
}
- public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
+ public AutoInstallsLayout(Context context, LauncherWidgetHolder appWidgetHolder,
LayoutParserCallback callback, Resources res,
Supplier<XmlPullParser> initialLayoutSupplier, String rootTag) {
mContext = context;
- mAppWidgetHost = appWidgetHost;
+ mAppWidgetHolder = appWidgetHolder;
mCallback = callback;
mPackageManager = context.getPackageManager();
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index c0a00c2..9f54f09 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -607,15 +607,16 @@
* Get the icon bounds on the view depending on the layout type.
*/
public void getIconBounds(int iconSize, Rect outBounds) {
- Utilities.setRectToViewCenter(this, iconSize, outBounds);
+ outBounds.set(0, 0, iconSize, iconSize);
if (mLayoutHorizontal) {
+ int top = (getHeight() - iconSize) / 2;
if (mIsRtl) {
- outBounds.offsetTo(getWidth() - iconSize - getPaddingRight(), outBounds.top);
+ outBounds.offsetTo(getWidth() - iconSize - getPaddingRight(), top);
} else {
- outBounds.offsetTo(getPaddingLeft(), outBounds.top);
+ outBounds.offsetTo(getPaddingLeft(), top);
}
} else {
- outBounds.offsetTo(outBounds.left, getPaddingTop());
+ outBounds.offset((getWidth() - iconSize) / 2, getPaddingTop());
}
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 691184a..9c5e906 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -373,7 +373,8 @@
private void resetCellSizeInternal(DeviceProfile deviceProfile) {
switch (mContainerType) {
case FOLDER:
- mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
+ mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx,
+ deviceProfile.folderCellLayoutBorderSpacePx);
break;
case HOTSEAT:
mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index 4daca8b..af13bea 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -1,6 +1,5 @@
package com.android.launcher3;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
@@ -21,6 +20,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -55,9 +55,9 @@
private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
"com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
- public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
+ public DefaultLayoutParser(Context context, LauncherWidgetHolder appWidgetHolder,
LayoutParserCallback callback, Resources sourceRes, int layoutId) {
- super(context, appWidgetHost, callback, sourceRes, layoutId, TAG_FAVORITES);
+ super(context, appWidgetHolder, callback, sourceRes, layoutId, TAG_FAVORITES);
}
@Override
@@ -336,11 +336,11 @@
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
int insertedId = -1;
try {
- int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+ int appWidgetId = mAppWidgetHolder.allocateAppWidgetId();
if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
Log.e(TAG, "Unable to bind app widget id " + cn);
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ mAppWidgetHolder.deleteAppWidgetId(appWidgetId);
return -1;
}
@@ -349,7 +349,7 @@
mValues.put(Favorites._ID, mCallback.generateNewItemId());
insertedId = mCallback.insertAndCheck(mDb, mValues);
if (insertedId < 0) {
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ mAppWidgetHolder.deleteAppWidgetId(appWidgetId);
return insertedId;
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 2b9eb29..92530ea 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -25,12 +25,14 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
+import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -61,6 +63,7 @@
private static final int DEFAULT_DOT_SIZE = 100;
private static final float ALL_APPS_TABLET_MAX_ROWS = 5.5f;
+ private static final float MIN_FOLDER_TEXT_SIZE_SP = 16f;
public static final PointF DEFAULT_SCALE = new PointF(1.0f, 1.0f);
public static final ViewScaleProvider DEFAULT_PROVIDER = itemInfo -> DEFAULT_SCALE;
@@ -147,11 +150,12 @@
// Folder
public float folderLabelTextScale;
public int folderLabelTextSizePx;
+ public int folderFooterHeightPx;
public int folderIconSizePx;
public int folderIconOffsetYPx;
// Folder content
- public Point folderCellLayoutBorderSpacePx;
+ public int folderCellLayoutBorderSpacePx;
public int folderContentPaddingLeftRight;
public int folderContentPaddingTop;
@@ -251,6 +255,7 @@
public boolean isTaskbarPresentInApps;
public int taskbarSize;
public int stashedTaskbarSize;
+ public int transientTaskbarMargin;
// DragController
public int flingToDeleteThresholdVelocity;
@@ -316,6 +321,8 @@
taskbarSize = res.getDimensionPixelSize(R.dimen.transient_taskbar_size);
stashedTaskbarSize =
res.getDimensionPixelSize(R.dimen.transient_taskbar_stashed_size);
+ transientTaskbarMargin =
+ res.getDimensionPixelSize(R.dimen.transient_taskbar_margin);
} else {
taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
stashedTaskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
@@ -352,17 +359,34 @@
}
folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
- folderContentPaddingLeftRight =
- res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right);
- folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
+
+ if (inv.folderStyle != INVALID_RESOURCE_HANDLE) {
+ TypedArray folderStyle = context.obtainStyledAttributes(inv.folderStyle,
+ R.styleable.FolderDisplayStyle);
+ // These are re-set in #updateFolderCellSize if the grid is not scalable
+ folderCellHeightPx = folderStyle.getDimensionPixelSize(
+ R.styleable.FolderDisplayStyle_folderCellHeight, 0);
+ folderCellWidthPx = folderStyle.getDimensionPixelSize(
+ R.styleable.FolderDisplayStyle_folderCellWidth, 0);
+
+ folderContentPaddingTop = folderStyle.getDimensionPixelSize(
+ R.styleable.FolderDisplayStyle_folderTopPadding, 0);
+ folderCellLayoutBorderSpacePx = folderStyle.getDimensionPixelSize(
+ R.styleable.FolderDisplayStyle_folderBorderSpace, 0);
+ folderFooterHeightPx = folderStyle.getDimensionPixelSize(
+ R.styleable.FolderDisplayStyle_folderFooterHeight, 0);
+ folderStyle.recycle();
+ } else {
+ folderCellLayoutBorderSpacePx = 0;
+ folderFooterHeightPx = 0;
+ folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_top_padding_default);
+ }
cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv);
+ cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
allAppsBorderSpacePx = new Point(
pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics),
pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics));
- cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
- folderCellLayoutBorderSpacePx = new Point(pxFromDp(inv.folderBorderSpaces.x, mMetrics),
- pxFromDp(inv.folderBorderSpaces.y, mMetrics));
workspacePageIndicatorHeight = res.getDimensionPixelSize(
R.dimen.workspace_page_indicator_height);
@@ -474,10 +498,11 @@
extraSpace = updateAvailableDimensions(res);
// Now that we have all of the variables calculated, we can tune certain sizes.
- if (isScalableGrid && inv.devicePaddings != null) {
+ if (isScalableGrid && inv.devicePaddingId != INVALID_RESOURCE_HANDLE) {
// Paddings were created assuming no scaling, so we first unscale the extra space.
int unscaledExtraSpace = (int) (extraSpace / cellScaleToFit);
- DevicePadding padding = inv.devicePaddings.getDevicePadding(unscaledExtraSpace);
+ DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
+ DevicePadding padding = devicePaddings.getDevicePadding(unscaledExtraSpace);
int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
@@ -931,22 +956,20 @@
private void updateAvailableFolderCellDimensions(Resources res) {
updateFolderCellSize(1f, res);
- final int folderBottomPanelSize = res.getDimensionPixelSize(R.dimen.folder_label_height);
-
// Don't let the folder get too close to the edges of the screen.
int folderMargin = edgeMarginPx * 2;
Point totalWorkspacePadding = getTotalWorkspacePadding();
// Check if the icons fit within the available height.
float contentUsedHeight = folderCellHeightPx * inv.numFolderRows
- + ((inv.numFolderRows - 1) * folderCellLayoutBorderSpacePx.y);
- int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y - folderBottomPanelSize
+ + ((inv.numFolderRows - 1) * folderCellLayoutBorderSpacePx);
+ int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y - folderFooterHeightPx
- folderMargin - folderContentPaddingTop;
float scaleY = contentMaxHeight / contentUsedHeight;
// Check if the icons fit within the available width.
float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns
- + ((inv.numFolderColumns - 1) * folderCellLayoutBorderSpacePx.x);
+ + ((inv.numFolderColumns - 1) * folderCellLayoutBorderSpacePx);
int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin
- folderContentPaddingLeftRight * 2;
float scaleX = contentMaxWidth / contentUsedWidth;
@@ -964,19 +987,18 @@
folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
folderChildTextSizePx =
pxFromSp(inv.iconTextSize[INDEX_DEFAULT], mMetrics, scale);
- folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
+ folderLabelTextSizePx = Math.max(pxFromSp(MIN_FOLDER_TEXT_SIZE_SP, mMetrics),
+ (int) (folderChildTextSizePx * folderLabelTextScale));
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
if (isScalableGrid) {
- folderCellWidthPx = pxFromDp(inv.folderCellSize.x, mMetrics, scale);
- folderCellHeightPx = pxFromDp(inv.folderCellSize.y, mMetrics, scale);
+ if (inv.folderStyle == INVALID_RESOURCE_HANDLE) {
+ folderCellWidthPx = pxFromDp(getCellSize().x, mMetrics, scale);
+ folderCellHeightPx = pxFromDp(getCellSize().y, mMetrics, scale);
+ }
- folderCellLayoutBorderSpacePx = new Point(
- pxFromDp(inv.folderBorderSpaces.x, mMetrics, scale),
- pxFromDp(inv.folderBorderSpaces.y, mMetrics, scale));
- folderContentPaddingLeftRight = folderCellLayoutBorderSpacePx.x;
- folderContentPaddingTop = pxFromDp(inv.folderTopPadding, mMetrics, scale);
+ folderContentPaddingLeftRight = folderCellLayoutBorderSpacePx;
} else {
int cellPaddingX = (int) (res.getDimensionPixelSize(R.dimen.folder_cell_x_padding)
* scale);
@@ -985,6 +1007,10 @@
folderCellWidthPx = folderChildIconSizePx + 2 * cellPaddingX;
folderCellHeightPx = folderChildIconSizePx + 2 * cellPaddingY + textHeight;
+ folderContentPaddingLeftRight =
+ res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right);
+ folderFooterHeightPx =
+ res.getDimensionPixelSize(R.dimen.folder_footer_height_default);
}
folderChildDrawablePaddingPx = Math.max(0,
@@ -1283,15 +1309,15 @@
* Returns the number of pixels required below OverviewActions excluding insets.
*/
public int getOverviewActionsClaimedSpaceBelow() {
- if (isTaskbarPresent && !isGestureMode
- // If taskbar is in overview, overview action has dedicated space above nav buttons
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- // Align vertically to where nav buttons are.
- return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
- }
-
if (isTaskbarPresent) {
- return FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get() ? taskbarSize : stashedTaskbarSize;
+ if (FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
+ return taskbarSize + transientTaskbarMargin;
+ }
+
+ return isGestureMode
+ ? stashedTaskbarSize
+ // Align vertically to where nav buttons are.
+ : ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
}
return mInsets.bottom;
}
@@ -1468,13 +1494,12 @@
writer.println(prefix + pxToDpStr("folderChildTextSizePx", folderChildTextSizePx));
writer.println(prefix + pxToDpStr("folderChildDrawablePaddingPx",
folderChildDrawablePaddingPx));
- writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx Horizontal",
- folderCellLayoutBorderSpacePx.x));
- writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx Vertical",
- folderCellLayoutBorderSpacePx.y));
+ writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx",
+ folderCellLayoutBorderSpacePx));
writer.println(prefix + pxToDpStr("folderContentPaddingLeftRight",
folderContentPaddingLeftRight));
writer.println(prefix + pxToDpStr("folderTopPadding", folderContentPaddingTop));
+ writer.println(prefix + pxToDpStr("folderFooterHeight", folderFooterHeightPx));
writer.println(prefix + pxToDpStr("bottomSheetTopPadding", bottomSheetTopPadding));
writer.println(prefix + "\tbottomSheetOpenDuration: " + bottomSheetOpenDuration);
@@ -1541,10 +1566,11 @@
writer.println(prefix + pxToDpStr("extraSpace", extraSpace));
writer.println(prefix + pxToDpStr("unscaled extraSpace", extraSpace / iconScale));
- if (inv.devicePaddings != null) {
+ if (inv.devicePaddingId != INVALID_RESOURCE_HANDLE) {
int unscaledExtraSpace = (int) (extraSpace / iconScale);
+ DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
writer.println(prefix + pxToDpStr("maxEmptySpace",
- inv.devicePaddings.getDevicePadding(unscaledExtraSpace).getMaxEmptySpacePx()));
+ devicePaddings.getDevicePadding(unscaledExtraSpace).getMaxEmptySpacePx()));
}
writer.println(prefix + pxToDpStr("workspaceTopPadding", workspaceTopPadding));
writer.println(prefix + pxToDpStr("workspaceBottomPadding", workspaceBottomPadding));
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 635f400..1f97535 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -17,7 +17,9 @@
package com.android.launcher3;
import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_DEVICE_PROFILE_LOGGING;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME;
+import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
@@ -43,9 +45,11 @@
import android.util.Xml;
import android.view.Display;
+import androidx.annotation.DimenRes;
import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
+import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.XmlRes;
import androidx.core.content.res.ResourcesCompat;
import com.android.launcher3.icons.DotRenderer;
@@ -129,11 +133,9 @@
public PointF[] minCellSize;
public PointF[] borderSpaces;
- public int inlineNavButtonsEndSpacing;
+ public @DimenRes int inlineNavButtonsEndSpacing;
- public PointF folderBorderSpaces;
- public PointF folderCellSize;
- public float folderTopPadding;
+ public @StyleRes int folderStyle;
public float[] horizontalMargin;
@@ -170,7 +172,8 @@
* Do not query directly. see {@link DeviceProfile#isScalableGrid}.
*/
protected boolean isScalable;
- public int devicePaddingId;
+ @XmlRes
+ public int devicePaddingId = INVALID_RESOURCE_HANDLE;
public String dbFile;
public int defaultLayoutId;
@@ -182,9 +185,6 @@
*/
public List<DeviceProfile> supportedProfiles = Collections.EMPTY_LIST;
- @Nullable
- public DevicePaddings devicePaddings;
-
public Point defaultWallpaperSize;
public Rect defaultWidgetPadding;
@@ -198,7 +198,8 @@
String gridName = getCurrentGridName(context);
String newGridName = initGrid(context, gridName);
if (!newGridName.equals(gridName)) {
- Utilities.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName).apply();
+ LauncherPrefs.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName)
+ .apply();
}
new DeviceGridState(this).writeToPrefs(context);
@@ -306,8 +307,7 @@
}
public static String getCurrentGridName(Context context) {
- return Utilities.isGridOptionsEnabled(context)
- ? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null;
+ return LauncherPrefs.getPrefs(context).getString(KEY_IDP_GRID_NAME, null);
}
private String initGrid(Context context, String gridName) {
@@ -323,6 +323,11 @@
return displayOption.grid.name;
}
+ @VisibleForTesting
+ public static String getDefaultGridName(Context context) {
+ return new InvariantDeviceProfile().initGrid(context, null);
+ }
+
private void initGrid(Context context, Info displayInfo, DisplayOption displayOption,
@DeviceType int deviceType) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
@@ -333,8 +338,11 @@
dbFile = closestProfile.dbFile;
defaultLayoutId = closestProfile.defaultLayoutId;
demoModeLayoutId = closestProfile.demoModeLayoutId;
+
numFolderRows = closestProfile.numFolderRows;
numFolderColumns = closestProfile.numFolderColumns;
+ folderStyle = closestProfile.folderStyle;
+
isScalable = closestProfile.isScalable;
devicePaddingId = closestProfile.devicePaddingId;
this.deviceType = deviceType;
@@ -357,10 +365,6 @@
borderSpaces = displayOption.borderSpaces;
- folderBorderSpaces = displayOption.folderBorderSpaces;
- folderCellSize = displayOption.folderCellSize;
- folderTopPadding = displayOption.folderTopPadding;
-
horizontalMargin = displayOption.horizontalMargin;
numShownHotseatIcons = closestProfile.numHotseatIcons;
@@ -378,14 +382,6 @@
allAppsBorderSpaces = displayOption.allAppsBorderSpaces;
allAppsIconSize = displayOption.allAppsIconSizes;
allAppsIconTextSize = displayOption.allAppsIconTextSizes;
- if (!Utilities.isGridOptionsEnabled(context)) {
- allAppsIconSize = iconSize;
- allAppsIconTextSize = iconTextSize;
- }
-
- if (devicePaddingId != 0) {
- devicePaddings = new DevicePaddings(context, devicePaddingId);
- }
inlineQsb = closestProfile.inlineQsb;
@@ -435,7 +431,7 @@
public void setCurrentGrid(Context context, String gridName) {
Context appContext = context.getApplicationContext();
- Utilities.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
+ LauncherPrefs.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext));
}
@@ -643,7 +639,7 @@
float screenHeight = config.screenHeightDp * res.getDisplayMetrics().density;
int rotation = WindowManagerProxy.INSTANCE.get(context).getRotation(context);
- if (Utilities.IS_DEBUG_DEVICE) {
+ if (Utilities.IS_DEBUG_DEVICE && ENABLE_DEVICE_PROFILE_LOGGING.get()) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
DisplayController.INSTANCE.get(context).dump(printWriter);
@@ -749,6 +745,7 @@
private final int numFolderRows;
private final int numFolderColumns;
+ private final @StyleRes int folderStyle;
private final int numAllAppsColumns;
private final int numDatabaseAllAppsColumns;
@@ -759,7 +756,7 @@
private final boolean[] inlineQsb = new boolean[COUNT_SIZES];
- private int inlineNavButtonsEndSpacing;
+ private @DimenRes int inlineNavButtonsEndSpacing;
private final String dbFile;
private final int defaultLayoutId;
@@ -811,15 +808,19 @@
inlineNavButtonsEndSpacing =
a.getResourceId(R.styleable.GridDisplayOption_inlineNavButtonsEndSpacing,
R.dimen.taskbar_button_margin_default);
+
numFolderRows = a.getInt(
R.styleable.GridDisplayOption_numFolderRows, numRows);
numFolderColumns = a.getInt(
R.styleable.GridDisplayOption_numFolderColumns, numColumns);
+ folderStyle = a.getResourceId(R.styleable.GridDisplayOption_folderStyle,
+ INVALID_RESOURCE_HANDLE);
+
isScalable = a.getBoolean(
R.styleable.GridDisplayOption_isScalable, false);
devicePaddingId = a.getResourceId(
- R.styleable.GridDisplayOption_devicePaddingId, 0);
+ R.styleable.GridDisplayOption_devicePaddingId, INVALID_RESOURCE_HANDLE);
int deviceCategory = a.getInt(R.styleable.GridDisplayOption_deviceCategory,
DEVICE_CATEGORY_ALL);
@@ -860,10 +861,6 @@
private final PointF[] minCellSize = new PointF[COUNT_SIZES];
- private final PointF folderCellSize;
- private final PointF folderBorderSpaces;
- private float folderTopPadding;
-
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
private final float[] hotseatBarBottomSpace = new float[COUNT_SIZES];
@@ -946,21 +943,6 @@
borderSpaceTwoPanelLandscape);
borderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
- x = a.getFloat(R.styleable.ProfileDisplayOption_folderCellWidth,
- minCellSize[INDEX_DEFAULT].x);
- y = a.getFloat(R.styleable.ProfileDisplayOption_folderCellHeight,
- minCellSize[INDEX_DEFAULT].y);
- folderCellSize = new PointF(x, y);
-
- float folderBorderSpace = a.getFloat(R.styleable.ProfileDisplayOption_folderBorderSpace,
- borderSpace);
-
- x = y = folderBorderSpace;
- folderBorderSpaces = new PointF(x, y);
-
- folderTopPadding = a.getFloat(R.styleable.ProfileDisplayOption_folderTopPadding,
- folderBorderSpaces.y);
-
x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidth,
minCellSize[INDEX_DEFAULT].x);
y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeight,
@@ -1133,9 +1115,6 @@
allAppsIconTextSizes[i] = 0;
allAppsBorderSpaces[i] = new PointF();
}
- folderBorderSpaces = new PointF();
- folderCellSize = new PointF();
- folderTopPadding = 0f;
}
private DisplayOption multiply(float w) {
@@ -1156,11 +1135,6 @@
allAppsBorderSpaces[i].x *= w;
allAppsBorderSpaces[i].y *= w;
}
- folderBorderSpaces.x *= w;
- folderBorderSpaces.y *= w;
- folderCellSize.x *= w;
- folderCellSize.y *= w;
- folderTopPadding *= w;
return this;
}
@@ -1183,11 +1157,6 @@
allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
allAppsBorderSpaces[i].y += p.allAppsBorderSpaces[i].y;
}
- folderBorderSpaces.x += p.folderBorderSpaces.x;
- folderBorderSpaces.y += p.folderBorderSpaces.y;
- folderCellSize.x += p.folderCellSize.x;
- folderCellSize.y += p.folderCellSize.y;
- folderTopPadding += p.folderTopPadding;
return this;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c73e077..5cce407 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -210,6 +210,7 @@
import com.android.launcher3.views.ScrimView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.PendingAppWidgetHostView;
@@ -472,7 +473,7 @@
InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
initDeviceProfile(idp);
idp.addOnChangeListener(this);
- mSharedPrefs = Utilities.getPrefs(this);
+ mSharedPrefs = LauncherPrefs.getPrefs(this);
mIconCache = app.getIconCache();
mAccessibilityDelegate = createAccessibilityDelegate();
@@ -482,6 +483,9 @@
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs);
+ // TODO: move the SearchConfig to SearchState when new LauncherState is created.
+ mBaseSearchConfig = new BaseSearchConfig();
+
mAppWidgetManager = new WidgetManagerHelper(this);
mAppWidgetHolder = createAppWidgetHolder();
mAppWidgetHolder.startListening();
@@ -548,9 +552,6 @@
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
setTitle(R.string.home_screen);
-
- // TODO: move the SearchConfig to SearchState when new LauncherState is created.
- mBaseSearchConfig = new BaseSearchConfig();
}
protected LauncherOverlayManager getDefaultOverlay() {
@@ -648,14 +649,6 @@
}
/**
- * Called when one handed mode activated and deactivated.
- * @param activated true if one handed mode activated, false otherwise.
- */
- public void onOneHandedStateChanged(boolean activated) {
- mDragLayer.onOneHandedModeStateChanged(activated);
- }
-
- /**
* Returns {@code true} if a new DeviceProfile is initialized, and {@code false} otherwise.
*/
protected boolean initDeviceProfile(InvariantDeviceProfile idp) {
@@ -1570,7 +1563,7 @@
@Override
public SharedPreferences getDevicePrefs() {
- return Utilities.getDevicePrefs(this);
+ return LauncherPrefs.getDevicePrefs(this);
}
public int getOrientation() {
@@ -1598,7 +1591,6 @@
&& AbstractFloatingView.getTopOpenView(this) == null;
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
boolean internalStateHandled = ACTIVITY_TRACKER.handleNewIntent(this);
- hideKeyboard();
if (isActionMain) {
if (!internalStateHandled) {
@@ -1721,6 +1713,7 @@
} catch (NullPointerException ex) {
Log.w(TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex);
}
+ mAppWidgetHolder.destroy();
TextKeyListener.getInstance().release();
clearPendingBinds();
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index ea3f723..4965936 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -18,7 +18,7 @@
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
-import static com.android.launcher3.Utilities.getDevicePrefs;
+import static com.android.launcher3.LauncherPrefs.getDevicePrefs;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
@@ -117,7 +117,7 @@
observer, MODEL_EXECUTOR.getHandler());
mOnTerminateCallback.add(iconChangeTracker::close);
MODEL_EXECUTOR.execute(observer::verifyIconChanged);
- SharedPreferences prefs = Utilities.getPrefs(mContext);
+ SharedPreferences prefs = LauncherPrefs.getPrefs(mContext);
prefs.registerOnSharedPreferenceChangeListener(observer);
mOnTerminateCallback.add(
() -> prefs.unregisterOnSharedPreferenceChangeListener(observer));
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
new file mode 100644
index 0000000..23ff10a
--- /dev/null
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -0,0 +1,20 @@
+package com.android.launcher3
+
+import android.content.Context
+import android.content.SharedPreferences
+
+object LauncherPrefs {
+
+ @JvmStatic
+ fun getPrefs(context: Context): SharedPreferences {
+ // Use application context for shared preferences, so that we use a single cached instance
+ return context.applicationContext.getSharedPreferences(
+ LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
+ }
+
+ @JvmStatic
+ fun getDevicePrefs(context: Context): SharedPreferences {
+ // Use application context for shared preferences, so that we use a single cached instance
+ return context.applicationContext.getSharedPreferences(
+ LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE)
+ }}
\ No newline at end of file
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 58e85fe..d002c2b 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -22,7 +22,6 @@
import android.annotation.TargetApi;
import android.app.backup.BackupManager;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -55,6 +54,8 @@
import android.util.Log;
import android.util.Xml;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.config.FeatureFlags;
@@ -70,7 +71,7 @@
import com.android.launcher3.util.NoLocaleSQLiteHelper;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import org.xmlpull.v1.XmlPullParser;
@@ -255,17 +256,20 @@
values.getAsString(Favorites.APPWIDGET_PROVIDER));
if (cn != null) {
+ LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
try {
- AppWidgetHost widgetHost = mOpenHelper.newLauncherWidgetHost();
- int appWidgetId = widgetHost.allocateAppWidgetId();
+ int appWidgetId = widgetHolder.allocateAppWidgetId();
values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,cn)) {
- widgetHost.deleteAppWidgetId(appWidgetId);
+ widgetHolder.deleteAppWidgetId(appWidgetId);
return false;
}
} catch (RuntimeException e) {
Log.e(TAG, "Failed to initialize external widget", e);
return false;
+ } finally {
+ // Necessary to destroy the holder to free up possible activity context
+ widgetHolder.destroy();
}
} else {
return false;
@@ -370,7 +374,7 @@
case LauncherSettings.Settings.METHOD_WAS_EMPTY_DB_CREATED : {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- Utilities.getPrefs(getContext()).getBoolean(
+ LauncherPrefs.getPrefs(getContext()).getBoolean(
mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false));
return result;
}
@@ -516,7 +520,7 @@
}
private void clearFlagEmptyDbCreated() {
- Utilities.getPrefs(getContext()).edit()
+ LauncherPrefs.getPrefs(getContext()).edit()
.remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
}
@@ -528,15 +532,15 @@
* 4) The default configuration for the particular device
*/
synchronized private void loadDefaultFavoritesIfNecessary() {
- SharedPreferences sp = Utilities.getPrefs(getContext());
+ SharedPreferences sp = LauncherPrefs.getPrefs(getContext());
if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
Log.d(TAG, "loading default workspace");
- AppWidgetHost widgetHost = mOpenHelper.newLauncherWidgetHost();
- AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction(widgetHost);
+ LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
+ AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction(widgetHolder);
if (loader == null) {
- loader = AutoInstallsLayout.get(getContext(),widgetHost, mOpenHelper);
+ loader = AutoInstallsLayout.get(getContext(), widgetHolder, mOpenHelper);
}
if (loader == null) {
final Partner partner = Partner.get(getContext().getPackageManager());
@@ -545,7 +549,7 @@
int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
"xml", partner.getPackageName());
if (workspaceResId != 0) {
- loader = new DefaultLayoutParser(getContext(), widgetHost,
+ loader = new DefaultLayoutParser(getContext(), widgetHolder,
mOpenHelper, partnerRes, workspaceResId);
}
}
@@ -553,7 +557,7 @@
final boolean usingExternallyProvidedLayout = loader != null;
if (loader == null) {
- loader = getDefaultLayoutParser(widgetHost);
+ loader = getDefaultLayoutParser(widgetHolder);
}
// There might be some partially restored DB items, due to buggy restore logic in
@@ -565,9 +569,10 @@
// Unable to load external layout. Cleanup and load the internal layout.
mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(),
- getDefaultLayoutParser(widgetHost));
+ getDefaultLayoutParser(widgetHolder));
}
clearFlagEmptyDbCreated();
+ widgetHolder.destroy();
}
}
@@ -576,7 +581,8 @@
*
* @return the loader if the restrictions are set and the resource exists; null otherwise.
*/
- private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction(AppWidgetHost widgetHost) {
+ private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction(
+ LauncherWidgetHolder widgetHolder) {
Context ctx = getContext();
final String authority;
if (!TextUtils.isEmpty(mProviderAuthority)) {
@@ -602,7 +608,7 @@
parser.setInput(new StringReader(layout));
Log.d(TAG, "Loading layout from " + authority);
- return new AutoInstallsLayout(ctx, widgetHost, mOpenHelper,
+ return new AutoInstallsLayout(ctx, widgetHolder, mOpenHelper,
ctx.getPackageManager().getResourcesForApplication(pi.applicationInfo),
() -> parser, AutoInstallsLayout.TAG_WORKSPACE);
} catch (Exception e) {
@@ -621,7 +627,7 @@
.build();
}
- private DefaultLayoutParser getDefaultLayoutParser(AppWidgetHost widgetHost) {
+ private DefaultLayoutParser getDefaultLayoutParser(LauncherWidgetHolder widgetHolder) {
InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
int defaultLayout = mUseTestWorkspaceLayout
? TEST_WORKSPACE_LAYOUT_RES_XML : idp.defaultLayoutId;
@@ -631,7 +637,7 @@
defaultLayout = idp.demoModeLayoutId;
}
- return new DefaultLayoutParser(getContext(), widgetHost,
+ return new DefaultLayoutParser(getContext(), widgetHolder,
mOpenHelper, getContext().getResources(), defaultLayout);
}
@@ -732,7 +738,7 @@
*/
protected void onEmptyDbCreated() {
// Set the flag for empty DB
- Utilities.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
+ LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
.commit();
}
@@ -932,40 +938,46 @@
*/
public void removeGhostWidgets(SQLiteDatabase db) {
// Get all existing widget ids.
- final AppWidgetHost host = newLauncherWidgetHost();
- final int[] allWidgets;
+ final LauncherWidgetHolder holder = newLauncherWidgetHolder();
try {
- // Although the method was defined in O, it has existed since the beginning of time,
- // so it might work on older platforms as well.
- allWidgets = host.getAppWidgetIds();
- } catch (IncompatibleClassChangeError e) {
- Log.e(TAG, "getAppWidgetIds not supported", e);
- return;
- }
- final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(false, db,
- Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
- "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
- boolean isAnyWidgetRemoved = false;
- for (int widgetId : allWidgets) {
- if (!validWidgets.contains(widgetId)) {
- try {
- FileLog.d(TAG, "Deleting invalid widget " + widgetId);
- host.deleteAppWidgetId(widgetId);
- isAnyWidgetRemoved = true;
- } catch (RuntimeException e) {
- // Ignore
+ final int[] allWidgets;
+ try {
+ // Although the method was defined in O, it has existed since the beginning of
+ // time, so it might work on older platforms as well.
+ allWidgets = holder.getAppWidgetIds();
+ } catch (IncompatibleClassChangeError e) {
+ Log.e(TAG, "getAppWidgetIds not supported", e);
+ // Necessary to destroy the holder to free up possible activity context
+ holder.destroy();
+ return;
+ }
+ final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(false, db,
+ Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
+ "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
+ boolean isAnyWidgetRemoved = false;
+ for (int widgetId : allWidgets) {
+ if (!validWidgets.contains(widgetId)) {
+ try {
+ FileLog.d(TAG, "Deleting invalid widget " + widgetId);
+ holder.deleteAppWidgetId(widgetId);
+ isAnyWidgetRemoved = true;
+ } catch (RuntimeException e) {
+ // Ignore
+ }
}
}
- }
- if (isAnyWidgetRemoved) {
- final String allWidgetsIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
- .collect(Collectors.joining(",", "[", "]"));
- final String validWidgetsIds = Arrays.stream(
- validWidgets.getArray().toArray()).mapToObj(String::valueOf)
- .collect(Collectors.joining(",", "[", "]"));
- FileLog.d(TAG, "One or more widgets was removed. db_path=" + db.getPath()
- + " allWidgetsIds=" + allWidgetsIds
- + ", validWidgetsIds=" + validWidgetsIds);
+ if (isAnyWidgetRemoved) {
+ final String allWidgetsIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
+ .collect(Collectors.joining(",", "[", "]"));
+ final String validWidgetsIds = Arrays.stream(
+ validWidgets.getArray().toArray()).mapToObj(String::valueOf)
+ .collect(Collectors.joining(",", "[", "]"));
+ FileLog.d(TAG, "One or more widgets was removed. db_path=" + db.getPath()
+ + " allWidgetsIds=" + allWidgetsIds
+ + ", validWidgetsIds=" + validWidgetsIds);
+ }
+ } finally {
+ holder.destroy();
}
}
@@ -1066,8 +1078,12 @@
return mMaxItemId;
}
- public AppWidgetHost newLauncherWidgetHost() {
- return new LauncherAppWidgetHost(mContext);
+ /**
+ * @return A new {@link LauncherWidgetHolder} based on the current context
+ */
+ @NonNull
+ public LauncherWidgetHolder newLauncherWidgetHolder() {
+ return new LauncherWidgetHolder(mContext);
}
@Override
diff --git a/src/com/android/launcher3/LauncherWidgetHolder.java b/src/com/android/launcher3/LauncherWidgetHolder.java
deleted file mode 100644
index 5fcd46f..0000000
--- a/src/com/android/launcher3/LauncherWidgetHolder.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3;
-
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.uioverrides.ApiWrapper;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
-import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.widget.PendingAppWidgetHostView;
-
-import java.util.function.IntConsumer;
-
-/**
- * A wrapper for LauncherAppWidgetHost. This class is created so the AppWidgetHost could run in
- * background.
- */
-public class LauncherWidgetHolder {
- @NonNull
- private final LauncherAppWidgetHost mWidgetHost;
-
- public LauncherWidgetHolder(@NonNull Context context) {
- this(context, null);
- }
-
- public LauncherWidgetHolder(@NonNull Context context,
- @Nullable IntConsumer appWidgetRemovedCallback) {
- mWidgetHost = new LauncherAppWidgetHost(context, appWidgetRemovedCallback);
- }
-
- /**
- * Starts listening to the widget updates from the server side
- */
- public void startListening() {
- mWidgetHost.startListening();
- }
-
- /**
- * Set the STARTED state of the widget host
- * @param isStarted True if setting the host as started, false otherwise
- */
- public void setActivityStarted(boolean isStarted) {
- mWidgetHost.setActivityStarted(isStarted);
- }
-
- /**
- * Set the RESUMED state of the widget host
- * @param isResumed True if setting the host as resumed, false otherwise
- */
- public void setActivityResumed(boolean isResumed) {
- mWidgetHost.setActivityResumed(isResumed);
- }
-
- /**
- * Set the NORMAL state of the widget host
- * @param isNormal True if setting the host to be in normal state, false otherwise
- */
- public void setStateIsNormal(boolean isNormal) {
- mWidgetHost.setStateIsNormal(isNormal);
- }
-
- /**
- * Delete the specified app widget from the host
- * @param appWidgetId The ID of the app widget to be deleted
- */
- public void deleteAppWidgetId(int appWidgetId) {
- mWidgetHost.deleteAppWidgetId(appWidgetId);
- }
-
- /**
- * Add the pending view to the host for complete configuration in further steps
- * @param appWidgetId The ID of the specified app widget
- * @param view The {@link PendingAppWidgetHostView} of the app widget
- */
- public void addPendingView(int appWidgetId, @NonNull PendingAppWidgetHostView view) {
- mWidgetHost.addPendingView(appWidgetId, view);
- }
-
- /**
- * @return True if the host is listening to the widget updates, false otherwise
- */
- public boolean isListening() {
- return mWidgetHost.isListening();
- }
-
- /**
- * @return The allocated app widget id if allocation is successful, returns -1 otherwise
- */
- public int allocateAppWidgetId() {
- return mWidgetHost.allocateAppWidgetId();
- }
-
- /**
- * Add a listener that is triggered when the providers of the widgets are changed
- * @param listener The listener that notifies when the providers changed
- */
- public void addProviderChangeListener(
- @NonNull LauncherAppWidgetHost.ProviderChangedListener listener) {
- mWidgetHost.addProviderChangeListener(listener);
- }
-
- /**
- * Remove the specified listener from the host
- * @param listener The listener that is to be removed from the host
- */
- public void removeProviderChangeListener(
- LauncherAppWidgetHost.ProviderChangedListener listener) {
- mWidgetHost.removeProviderChangeListener(listener);
- }
-
- /**
- * Starts the configuration activity for the widget
- * @param activity The activity in which to start the configuration page
- * @param widgetId The ID of the widget
- * @param requestCode The request code
- */
- public void startConfigActivity(@NonNull BaseDraggingActivity activity, int widgetId,
- int requestCode) {
- mWidgetHost.startConfigActivity(activity, widgetId, requestCode);
- }
-
- /**
- * Starts the binding flow for the widget
- * @param activity The activity for which to bind the widget
- * @param appWidgetId The ID of the widget
- * @param info The {@link AppWidgetProviderInfo} of the widget
- * @param requestCode The request code
- */
- public void startBindFlow(@NonNull BaseActivity activity,
- int appWidgetId, @NonNull AppWidgetProviderInfo info, int requestCode) {
- mWidgetHost.startBindFlow(activity, appWidgetId, info, requestCode);
- }
-
- /**
- * Stop the host from listening to the widget updates
- */
- public void stopListening() {
- mWidgetHost.stopListening();
- }
-
- /**
- * Create a view for the specified app widget
- * @param context The activity context for which the view is created
- * @param appWidgetId The ID of the widget
- * @param info The {@link LauncherAppWidgetProviderInfo} of the widget
- * @return A view for the widget
- */
- @NonNull
- public AppWidgetHostView createView(@NonNull Context context, int appWidgetId,
- @NonNull LauncherAppWidgetProviderInfo info) {
- return mWidgetHost.createView(context, appWidgetId, info);
- }
-
- /**
- * Set the interaction handler for the widget host
- * @param handler The interaction handler
- */
- public void setInteractionHandler(
- @Nullable LauncherAppWidgetHost.LauncherWidgetInteractionHandler handler) {
- ApiWrapper.setHostInteractionHandler(mWidgetHost, handler);
- }
-
- /**
- * Clears all the views from the host
- */
- public void clearViews() {
- mWidgetHost.clearViews();
- }
-}
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index bcd4c3f..50ad2be 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -98,6 +98,6 @@
}
public static boolean isEnabled(Context context) {
- return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);
+ return LauncherPrefs.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);
}
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 8b342ea..7a74d7e 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -152,7 +152,7 @@
// No need to add padding when cell layout border spacing is present.
boolean noPaddingX =
(dp.cellLayoutBorderSpacePx.x > 0 && mContainerType == WORKSPACE)
- || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER)
+ || (dp.folderCellLayoutBorderSpacePx > 0 && mContainerType == FOLDER)
|| (dp.hotseatBorderSpace > 0 && mContainerType == HOTSEAT);
int cellPaddingX = noPaddingX
? 0
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index f70511a..ce009a1 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -26,20 +26,12 @@
import android.app.ActivityManager;
import android.app.Person;
import android.app.WallpaperManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
@@ -51,7 +43,6 @@
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.DeadObjectException;
@@ -71,15 +62,12 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
-import android.widget.LinearLayout;
import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
-import com.android.launcher3.graphics.GridCustomizationsProvider;
import com.android.launcher3.graphics.TintedDrawableSpan;
import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.ThemedIconDrawable;
@@ -91,7 +79,6 @@
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -100,10 +87,8 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Locale;
-import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -117,8 +102,6 @@
private static final Pattern sTrimPattern =
Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
- private static final int[] sLoc0 = new int[2];
- private static final int[] sLoc1 = new int[2];
private static final Matrix sMatrix = new Matrix();
private static final Matrix sInverseMatrix = new Matrix();
@@ -167,14 +150,6 @@
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
}
- // An intent extra to indicate the horizontal scroll of the wallpaper.
- public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
- public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
-
- // An intent extra to indicate the launch source by launcher.
- public static final String EXTRA_WALLPAPER_LAUNCH_SOURCE =
- "com.android.wallpaper.LAUNCH_SOURCE";
-
public static boolean IS_RUNNING_IN_TEST_HARNESS =
ActivityManager.isRunningInTestHarness();
@@ -186,12 +161,6 @@
return Log.isLoggable(propertyName, Log.VERBOSE);
}
- public static boolean existsStyleWallpapers(Context context) {
- ResolveInfo ri = context.getPackageManager().resolveActivity(
- PackageManagerHelper.getStyleWallpapersIntent(context), 0);
- return ri != null;
- }
-
/**
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
* coordinates.
@@ -305,9 +274,9 @@
* Sets {@param out} to be same as {@param in} by rounding individual values
*/
public static void roundArray(float[] in, int[] out) {
- for (int i = 0; i < in.length; i++) {
- out[i] = Math.round(in[i]);
- }
+ for (int i = 0; i < in.length; i++) {
+ out[i] = Math.round(in[i]);
+ }
}
public static void offsetPoints(float[] points, float offsetX, float offsetY) {
@@ -328,80 +297,8 @@
localY < (v.getHeight() + slop);
}
- public static int[] getCenterDeltaInScreenSpace(View v0, View v1) {
- v0.getLocationInWindow(sLoc0);
- v1.getLocationInWindow(sLoc1);
-
- sLoc0[0] += (v0.getMeasuredWidth() * v0.getScaleX()) / 2;
- sLoc0[1] += (v0.getMeasuredHeight() * v0.getScaleY()) / 2;
- sLoc1[0] += (v1.getMeasuredWidth() * v1.getScaleX()) / 2;
- sLoc1[1] += (v1.getMeasuredHeight() * v1.getScaleY()) / 2;
- return new int[] {sLoc1[0] - sLoc0[0], sLoc1[1] - sLoc0[1]};
- }
-
- /**
- * Helper method to set rectOut with rectFSrc.
- */
- public static void setRect(RectF rectFSrc, Rect rectOut) {
- rectOut.left = (int) rectFSrc.left;
- rectOut.top = (int) rectFSrc.top;
- rectOut.right = (int) rectFSrc.right;
- rectOut.bottom = (int) rectFSrc.bottom;
- }
-
public static void scaleRectFAboutCenter(RectF r, float scale) {
- scaleRectFAboutPivot(r, scale, r.centerX(), r.centerY());
- }
-
- public static void scaleRectFAboutPivot(RectF r, float scale, float px, float py) {
- if (scale != 1.0f) {
- r.offset(-px, -py);
- r.left = r.left * scale;
- r.top = r.top * scale ;
- r.right = r.right * scale;
- r.bottom = r.bottom * scale;
- r.offset(px, py);
- }
- }
-
- public static void scaleRectAboutCenter(Rect r, float scale) {
- if (scale != 1.0f) {
- int cx = r.centerX();
- int cy = r.centerY();
- r.offset(-cx, -cy);
- scaleRect(r, scale);
- r.offset(cx, cy);
- }
- }
-
- public static void scaleRect(Rect r, float scale) {
- if (scale != 1.0f) {
- r.left = (int) (r.left * scale + 0.5f);
- r.top = (int) (r.top * scale + 0.5f);
- r.right = (int) (r.right * scale + 0.5f);
- r.bottom = (int) (r.bottom * scale + 0.5f);
- }
- }
-
- public static void insetRect(Rect r, Rect insets) {
- r.left = Math.min(r.right, r.left + insets.left);
- r.top = Math.min(r.bottom, r.top + insets.top);
- r.right = Math.max(r.left, r.right - insets.right);
- r.bottom = Math.max(r.top, r.bottom - insets.bottom);
- }
-
- public static float shrinkRect(Rect r, float scaleX, float scaleY) {
- float scale = Math.min(Math.min(scaleX, scaleY), 1.0f);
- if (scale < 1.0f) {
- int deltaX = (int) (r.width() * (scaleX - scale) * 0.5f);
- r.left += deltaX;
- r.right -= deltaX;
-
- int deltaY = (int) (r.height() * (scaleY - scale) * 0.5f);
- r.top += deltaY;
- r.bottom -= deltaY;
- }
- return scale;
+ scaleRectFAboutCenter(r, scale, scale);
}
/**
@@ -419,6 +316,33 @@
r.offset(px, py);
}
+ public static void scaleRectAboutCenter(Rect r, float scale) {
+ if (scale != 1.0f) {
+ int cx = r.centerX();
+ int cy = r.centerY();
+ r.offset(-cx, -cy);
+ r.left = (int) (r.left * scale + 0.5f);
+ r.top = (int) (r.top * scale + 0.5f);
+ r.right = (int) (r.right * scale + 0.5f);
+ r.bottom = (int) (r.bottom * scale + 0.5f);
+ r.offset(cx, cy);
+ }
+ }
+
+ public static float shrinkRect(Rect r, float scaleX, float scaleY) {
+ float scale = Math.min(Math.min(scaleX, scaleY), 1.0f);
+ if (scale < 1.0f) {
+ int deltaX = (int) (r.width() * (scaleX - scale) * 0.5f);
+ r.left += deltaX;
+ r.right -= deltaX;
+
+ int deltaY = (int) (r.height() * (scaleY - scale) * 0.5f);
+ r.top += deltaY;
+ r.bottom -= deltaY;
+ }
+ return scale;
+ }
+
/**
* Maps t from one range to another range.
* @param t The value to map.
@@ -454,30 +378,6 @@
}
/**
- * Bounds parameter to the range [0, 1]
- */
- public static float saturate(float a) {
- return boundToRange(a, 0, 1.0f);
- }
-
- /**
- * Returns the compliment (1 - a) of the parameter.
- */
- public static float comp(float a) {
- return 1 - a;
- }
-
- /**
- * Returns the "probabilistic or" of a and b. (a + b - ab).
- * Useful beyond probability, can be used to combine two unit progresses for example.
- */
- public static float or(float a, float b) {
- float satA = saturate(a);
- float satB = saturate(b);
- return satA + satB - (satA * satB);
- }
-
- /**
* Trims the string, removing all whitespace at the beginning and end of the string.
* Non-breaking whitespaces are also removed.
*/
@@ -521,6 +421,11 @@
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
+ /** Converts a dp value to pixels for a certain density. */
+ public static int dpToPx(float dp, int densityDpi) {
+ float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+ return (int) (dp * densityRatio);
+ }
public static int pxFromSp(float size, DisplayMetrics metrics) {
return pxFromSp(size, metrics, 1f);
@@ -531,7 +436,6 @@
return ResourceUtils.roundPxValueFromFloat(value);
}
-
public static String createDbSelectionQuery(String columnName, IntArray values) {
return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, values.toConcatString());
}
@@ -555,18 +459,6 @@
}
/**
- * Using the view's bounds and icon size, calculate where the icon bounds will
- * be if it was positioned at the center of the view.
- */
- public static void setRectToViewCenter(View iconView, int iconSize, Rect outBounds) {
- int top = (iconView.getHeight() - iconSize) / 2;
- int left = (iconView.getWidth() - iconSize) / 2;
- int right = left + iconSize;
- int bottom = top + iconSize;
- outBounds.set(left, top, right, bottom);
- }
-
- /**
* Ensures that a value is within given bounds. Specifically:
* If value is less than lowerBound, return lowerBound; else if value is greater than upperBound,
* return upperBound; else return value unchanged.
@@ -616,18 +508,6 @@
return spanned;
}
- public static SharedPreferences getPrefs(Context context) {
- // Use application context for shared preferences, so that we use a single cached instance
- return context.getApplicationContext().getSharedPreferences(
- LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
- }
-
- public static SharedPreferences getDevicePrefs(Context context) {
- // Use application context for shared preferences, so that we use a single cached instance
- return context.getApplicationContext().getSharedPreferences(
- LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE);
- }
-
public static boolean isWallpaperSupported(Context context) {
return context.getSystemService(WallpaperManager.class).isWallpaperSupported();
}
@@ -641,42 +521,6 @@
|| e.getCause() instanceof DeadObjectException;
}
- public static boolean isGridOptionsEnabled(Context context) {
- return isComponentEnabled(context.getPackageManager(),
- context.getPackageName(),
- GridCustomizationsProvider.class.getName());
- }
-
- private static boolean isComponentEnabled(PackageManager pm, String pkgName, String clsName) {
- ComponentName componentName = new ComponentName(pkgName, clsName);
- int componentEnabledSetting = pm.getComponentEnabledSetting(componentName);
-
- switch (componentEnabledSetting) {
- case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
- return false;
- case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
- return true;
- case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
- default:
- // We need to get the application info to get the component's default state
- try {
- PackageInfo packageInfo = pm.getPackageInfo(pkgName,
- PackageManager.GET_PROVIDERS | PackageManager.GET_DISABLED_COMPONENTS);
-
- if (packageInfo.providers != null) {
- return Arrays.stream(packageInfo.providers).anyMatch(
- pi -> pi.name.equals(clsName) && pi.isEnabled());
- }
-
- // the component is not declared in the AndroidManifest
- return false;
- } catch (PackageManager.NameNotFoundException e) {
- // the package isn't installed on the device
- return false;
- }
- }
- }
-
/**
* Utility method to post a runnable on the handler, skipping the synchronization barriers.
*/
@@ -686,12 +530,6 @@
handler.sendMessage(msg);
}
- public static void unregisterReceiverSafely(Context context, BroadcastReceiver receiver) {
- try {
- context.unregisterReceiver(receiver);
- } catch (IllegalArgumentException e) {}
- }
-
/**
* Returns the full drawable for info without any flattening or pre-processing.
*
@@ -789,14 +627,6 @@
}
}
- /**
- * @return true is the extra is either null or is of type {@param type}
- */
- public static boolean isValidExtraType(Intent intent, String key, Class type) {
- Object extra = intent.getParcelableExtra(key);
- return extra == null || type.isInstance(extra);
- }
-
public static float squaredHypot(float x, float y) {
return x * x + y * y;
}
@@ -807,18 +637,6 @@
}
/**
- * Helper method to create a content provider
- */
- public static ContentObserver newContentObserver(Handler handler, Consumer<Uri> command) {
- return new ContentObserver(handler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- command.accept(uri);
- }
- };
- }
-
- /**
* Rotates `inOutBounds` by `delta` 90-degree increments. Rotation is visually CCW. Parent
* sizes represent the "space" that will rotate carrying inOutBounds along with it to determine
* the final bounds.
@@ -866,16 +684,6 @@
ColorUtils.blendARGB(0, color, tintAmount));
}
- /**
- * Sets start margin on the provided {@param view} to be {@param margin}.
- * Assumes {@param view} is a child of {@link LinearLayout}
- */
- public static void setStartMarginForView(View view, int margin) {
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
- lp.setMarginStart(margin);
- view.setLayoutParams(lp);
- }
-
public static Rect getViewBounds(@NonNull View v) {
int[] pos = new int[2];
v.getLocationOnScreen(pos);
@@ -916,12 +724,4 @@
}
return options;
}
-
- public static boolean bothNull(@Nullable Object a, @Nullable Object b) {
- return a == null && b == null;
- }
-
- public static boolean bothNonNull(@Nullable Object a, @Nullable Object b) {
- return a != null && b != null;
- }
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b31db82..27c9e98 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -107,8 +107,9 @@
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.WallpaperOffsetInterpolator;
-import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherWidgetHolder;
+import com.android.launcher3.widget.LauncherWidgetHolder.ProviderChangedListener;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -1073,13 +1074,14 @@
mXDown = ev.getX();
mYDown = ev.getY();
if (mFirstPagePinnedItem != null) {
- mTempFXY[0] = mXDown + getScrollX();
- mTempFXY[1] = mYDown + getScrollY();
- Utilities.mapCoordInSelfToDescendant(mFirstPagePinnedItem, this, mTempFXY);
- mIsEventOverFirstPagePinnedItem = mFirstPagePinnedItem.getLeft() <= mTempFXY[0]
- && mFirstPagePinnedItem.getRight() >= mTempFXY[0]
- && mFirstPagePinnedItem.getTop() <= mTempFXY[1]
- && mFirstPagePinnedItem.getBottom() >= mTempFXY[1];
+ final float[] tempFXY = new float[2];
+ tempFXY[0] = mXDown;
+ tempFXY[1] = mYDown;
+ Utilities.mapCoordInSelfToDescendant(mFirstPagePinnedItem, this, tempFXY);
+ mIsEventOverFirstPagePinnedItem = mFirstPagePinnedItem.getLeft() <= tempFXY[0]
+ && mFirstPagePinnedItem.getRight() >= tempFXY[0]
+ && mFirstPagePinnedItem.getTop() <= tempFXY[1]
+ && mFirstPagePinnedItem.getBottom() >= tempFXY[1];
} else {
mIsEventOverFirstPagePinnedItem = false;
}
@@ -2350,7 +2352,7 @@
}
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
- (int) mDragViewVisualCenter[1], minSpanX, minSpanY,
+ (int) mDragViewVisualCenter[1], item.spanX, item.spanY,
mDragTargetLayout, mTargetCell);
int reorderX = mTargetCell[0];
int reorderY = mTargetCell[1];
@@ -2366,7 +2368,8 @@
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
item.spanY, child, mTargetCell);
- manageReorderOnDragOver(d, targetCellDistance, nearestDropOccupied, minSpanX, minSpanY);
+ manageReorderOnDragOver(d, targetCellDistance, nearestDropOccupied, minSpanX, minSpanY,
+ reorderX, reorderY);
if (mDragMode == DRAG_MODE_CREATE_FOLDER || mDragMode == DRAG_MODE_ADD_TO_FOLDER ||
!nearestDropOccupied) {
@@ -2378,26 +2381,26 @@
}
protected void manageReorderOnDragOver(DragObject d, float targetCellDistance,
- boolean nearestDropOccupied, int minSpanX, int minSpanY) {
+ boolean nearestDropOccupied, int minSpanX, int minSpanY, int reorderX, int reorderY) {
ItemInfo item = d.dragInfo;
final View child = (mDragInfo == null) ? null : mDragInfo.cell;
- int reorderX = mTargetCell[0];
- int reorderY = mTargetCell[1];
- if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
- && (mLastReorderX != reorderX || mLastReorderY != reorderY)
- && targetCellDistance < mDragTargetLayout.getReorderRadius(mTargetCell, item.spanX,
- item.spanY)) {
+ if (!nearestDropOccupied) {
mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY,
child, mTargetCell, new int[2], CellLayout.MODE_SHOW_REORDER_HINT);
- }
-
- if (!nearestDropOccupied) {
mDragTargetLayout.visualizeDropLocation(mTargetCell[0], mTargetCell[1],
item.spanX, item.spanY, d);
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
- && !mReorderAlarm.alarmPending()) {
+ && !mReorderAlarm.alarmPending()
+ && (mLastReorderX != reorderX || mLastReorderY != reorderY)
+ && targetCellDistance < mDragTargetLayout.getReorderRadius(mTargetCell, item.spanX,
+ item.spanY)) {
+ mLastReorderX = reorderX;
+ mLastReorderY = reorderY;
+ mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY,
+ child, mTargetCell, new int[2], CellLayout.MODE_SHOW_REORDER_HINT);
// Otherwise, if we aren't adding to or creating a folder and there's no pending
// reorder, then we schedule a reorder
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
@@ -2602,8 +2605,6 @@
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout,
mTargetCell);
- mLastReorderX = mTargetCell[0];
- mLastReorderY = mTargetCell[1];
mTargetCell = mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index dd47592..063b82e 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -1,5 +1,7 @@
package com.android.launcher3.accessibility;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -172,7 +174,11 @@
mContext.getDragLayer().getDescendantRectRelativeToSelf(host, pos);
ArrowPopup popup = OptionsPopupView.show(mContext, new RectF(pos), actions, false);
popup.requestFocus();
- popup.setOnCloseCallback(host::requestFocus);
+ popup.setOnCloseCallback(() -> {
+ host.requestFocus();
+ host.sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
+ host.performAccessibilityAction(ACTION_ACCESSIBILITY_FOCUS, null);
+ });
return true;
} else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
BubbleTextView btv = host instanceof BubbleTextView ? (BubbleTextView) host
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 08b42cd..c86f08d 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -102,6 +102,16 @@
}
}
+ /**
+ * Sets results list for search.
+ *
+ * @param searchResultCode indicates if the result is final or intermediate for a given query
+ * since we can get search results from multiple sources.
+ */
+ public void setSearchResults(ArrayList<AdapterItem> results, int searchResultCode) {
+ setSearchResults(results);
+ }
+
private void animateToSearchState(boolean goingToSearch) {
animateToSearchState(goingToSearch, DEFAULT_SEARCH_TRANSITION_DURATION_MS);
}
@@ -311,7 +321,7 @@
layoutParams.topMargin =
includeTabsMargin
? getContext().getResources().getDimensionPixelSize(
- R.dimen.all_apps_header_pill_height)
+ R.dimen.all_apps_header_pill_height)
: 0;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 368a373..e34d4c8 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -31,6 +31,7 @@
import com.android.launcher3.util.ScrollableLayoutManager;
import com.android.launcher3.views.ActivityContext;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -43,6 +44,31 @@
public static final String TAG = "AppsGridAdapter";
private final AppsGridLayoutManager mGridLayoutMgr;
+ private final List<OnLayoutCompletedListener> mOnLayoutCompletedListeners = new ArrayList<>();
+
+ /**
+ * Listener for {@link RecyclerView.LayoutManager#onLayoutCompleted(RecyclerView.State)}
+ */
+ public interface OnLayoutCompletedListener {
+ void onLayoutCompleted();
+ }
+
+ /**
+ * Adds a {@link OnLayoutCompletedListener} to receive a callback when {@link
+ * RecyclerView.LayoutManager#onLayoutCompleted(RecyclerView.State)} is called
+ */
+ public void addOnLayoutCompletedListener(OnLayoutCompletedListener listener) {
+ mOnLayoutCompletedListeners.add(listener);
+ }
+
+ /**
+ * Removes a {@link OnLayoutCompletedListener} to not receive a callback when {@link
+ * RecyclerView.LayoutManager#onLayoutCompleted(RecyclerView.State)} is called
+ */
+ public void removeOnLayoutCompletedListener(OnLayoutCompletedListener listener) {
+ mOnLayoutCompletedListeners.remove(listener);
+ }
+
public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
@@ -133,6 +159,14 @@
}
@Override
+ public void onLayoutCompleted(RecyclerView.State state) {
+ super.onLayoutCompleted(state);
+ for (OnLayoutCompletedListener listener : mOnLayoutCompletedListeners) {
+ listener.onLayoutCompleted();
+ }
+ }
+
+ @Override
protected int incrementTotalHeight(Adapter adapter, int position, int heightUntilLastPos) {
AllAppsGridAdapter.AdapterItem item = mApps.getAdapterItems().get(position);
// only account for the first icon in the row since they are the same size within a row
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index fa2c6e9..9930abe 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -141,6 +141,9 @@
private final Launcher mLauncher;
private boolean mIsVerticalLayout;
+ // Whether this class should take care of closing the keyboard.
+ private boolean mShouldControlKeyboard;
+
// Animation in this class is controlled by a single variable {@link mProgress}.
// Visually, it represents top y coordinate of the all apps container if multiplied with
// {@link mShiftRange}.
@@ -238,7 +241,7 @@
StateAnimationConfig config, PendingAnimation builder) {
if (mLauncher.isInState(ALL_APPS) && !ALL_APPS.equals(toState)) {
// For atomic animations, we close the keyboard immediately.
- if (!config.userControlled && !mLauncher.getSearchConfig().isKeyboardSyncEnabled()) {
+ if (!config.userControlled && mShouldControlKeyboard) {
mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
}
@@ -252,7 +255,7 @@
// the keyboard open and then changes their mind and swipes back up, we want the
// keyboard to remain open. However an onCancel signal is sent to the listeners
// (success = false), so we need to check for that.
- if (config.userControlled && success) {
+ if (config.userControlled && success && mShouldControlKeyboard) {
mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
}
});
@@ -317,6 +320,8 @@
mAppsViewAlpha.setUpdateVisibility(true);
mAppsViewTranslationY = new MultiPropertyFactory<>(
mAppsView, VIEW_TRANSLATE_Y, APPS_VIEW_INDEX_COUNT, Float::sum);
+
+ mShouldControlKeyboard = !mLauncher.getSearchConfig().isKeyboardSyncEnabled();
}
/**
@@ -333,7 +338,9 @@
private void onProgressAnimationEnd() {
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.reset(false /* animate */);
- mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
+ if (mShouldControlKeyboard) {
+ mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
+ }
}
}
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index da86d98..8e519c1 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -54,6 +54,7 @@
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Insettable;
import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
@@ -148,7 +149,7 @@
mWorkManager = new WorkProfileManager(
mActivityContext.getSystemService(UserManager.class),
- this, Utilities.getPrefs(mActivityContext));
+ this, LauncherPrefs.getPrefs(mActivityContext));
mAH = Arrays.asList(null, null, null);
mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN));
mAH.set(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK));
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
index 9c3dab4..495f5c3 100644
--- a/src/com/android/launcher3/allapps/SearchTransitionController.java
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -32,6 +32,7 @@
import android.util.FloatProperty;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
import android.view.animation.Interpolator;
import com.android.launcher3.BubbleTextView;
@@ -39,6 +40,7 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
/** Coordinates the transition between Search and A-Z in All Apps. */
@@ -225,16 +227,35 @@
numSearchResultsAnimated++;
}
- searchResultView.setAlpha(contentAlpha);
- // Apply background alpha to decorator if possible.
- if (adapterPosition != NO_POSITION) {
- searchRecyclerView.getApps().getAdapterItems()
- .get(adapterPosition).setDecorationFillAlpha((int) (255 * backgroundAlpha));
- }
- // Apply background alpha to view's background (e.g. for Search Edu card).
+
Drawable background = searchResultView.getBackground();
- if (background != null) {
+ if (background != null
+ && searchResultView instanceof ViewGroup
+ && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
+ searchResultView.setAlpha(1f);
+
+ // Apply content alpha to each child, since the view needs to be fully opaque for
+ // the background to show properly.
+ ViewGroup searchResultViewGroup = (ViewGroup) searchResultView;
+ for (int j = 0; j < searchResultViewGroup.getChildCount(); j++) {
+ searchResultViewGroup.getChildAt(j).setAlpha(contentAlpha);
+ }
+
+ // Apply background alpha to the background drawable directly.
background.setAlpha((int) (255 * backgroundAlpha));
+ } else {
+ searchResultView.setAlpha(contentAlpha);
+
+ // Apply background alpha to decorator if possible.
+ if (adapterPosition != NO_POSITION) {
+ searchRecyclerView.getApps().getAdapterItems().get(adapterPosition)
+ .setDecorationFillAlpha((int) (255 * backgroundAlpha));
+ }
+
+ // Apply background alpha to view's background (e.g. for Search Edu card).
+ if (background != null) {
+ background.setAlpha((int) (255 * backgroundAlpha));
+ }
}
float scaleY = 1;
@@ -304,6 +325,13 @@
getSearchRecyclerView().getApps().getAdapterItems().get(adapterPosition)
.setDecorationFillAlpha(255);
}
+ if (child instanceof ViewGroup
+ && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
+ ViewGroup childGroup = (ViewGroup) child;
+ for (int i = 0; i < childGroup.getChildCount(); i++) {
+ childGroup.getChildAt(i).setAlpha(1f);
+ }
+ }
if (child.getBackground() != null) {
child.getBackground().setAlpha(255);
}
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 968a556..b3245ee 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -26,8 +26,8 @@
import android.widget.FrameLayout;
import android.widget.TextView;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.views.ActivityContext;
@@ -85,7 +85,7 @@
@Override
public void onClick(View view) {
startAnimation(mDismissAnim);
- Utilities.getPrefs(getContext()).edit().putInt(WorkProfileManager.KEY_WORK_EDU_STEP,
+ LauncherPrefs.getPrefs(getContext()).edit().putInt(WorkProfileManager.KEY_WORK_EDU_STEP,
1).apply();
}
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index 0a938b2..2272cdc 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -154,6 +154,7 @@
private void updateVisibility() {
clearAnimation();
+ onApplyWindowInsets(getRootWindowInsets());
if (mWorkEnabled && mOnWorkTab) {
setFlag(FLAG_FADE_ONGOING);
setVisibility(VISIBLE);
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 4c461aa..4d58eb0 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -15,9 +15,6 @@
*/
package com.android.launcher3.allapps.search;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME;
-
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -125,10 +122,6 @@
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO) {
- mLauncher.getStatsLogManager().logger()
- .log(actionId == EditorInfo.IME_ACTION_SEARCH
- ? LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME
- : LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 4287779..22bc88d 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -17,6 +17,7 @@
package com.android.launcher3.config;
import android.content.Context;
+import android.content.SharedPreferences;
import com.android.launcher3.BuildConfig;
import com.android.launcher3.Utilities;
@@ -78,10 +79,6 @@
public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(
"PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps");
- // TODO: b/206508141: Long pressing on some icons on home screen cause launcher to crash.
- public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
- "ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
-
public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
"KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
@@ -257,13 +254,29 @@
getDebugFlag("ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", false,
"Enable splitting from fullscreen app with keyboard shortcuts");
+ public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
+ "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", false,
+ "Enable initiating split screen from workspace to workspace.");
+
public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(
"ENABLE_NEW_MIGRATION_LOGIC", true,
"Enable the new grid migration logic, keeping pages when src < dest");
+ public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(
+ "ENABLE_WIDGET_HOST_IN_BACKGROUND", false,
+ "Enable background widget updates listening for widget holder");
+
public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
"ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
+ public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = new DeviceFlag(
+ "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", false,
+ "Enable option to replace decorator-based search result backgrounds with drawables");
+
+ public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = new DeviceFlag(
+ "TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,
+ "Use 2 rows of app predictions in All Apps search zero-state");
+
public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = new DeviceFlag(
"ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
"Enable option to show keyboard when going to all-apps");
@@ -313,6 +326,10 @@
"HOME_GARDENING_WORKSPACE_BUTTONS", false,
"Change workspace edit buttons to reflect home gardening");
+ public static final BooleanFlag ENABLE_TASKBAR_REVISED_THRESHOLDS = getDebugFlag(
+ "ENABLE_TASKBAR_REVISED_THRESHOLDS", false,
+ "Uses revised thresholds for transient taskbar.");
+
public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(
"ENABLE_TRANSIENT_TASKBAR", false, "Enables transient taskbar.");
@@ -323,12 +340,39 @@
public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(
"SHOW_DOT_PAGINATION", false, "Enable showing dot pagination in workspace");
+ public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(
+ "LARGE_SCREEN_WIDGET_PICKER", false, "Enable new widget picker that takes "
+ + "advantage of large screen format");
+
+ public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(
+ "ENABLE_NEW_GESTURE_NAV_TUTORIAL", false,
+ "Enable the redesigned gesture navigation tutorial");
+
+ public static final BooleanFlag ENABLE_TOAST_IMPRESSION_LOGGING = getDebugFlag(
+ "ENABLE_TOAST_IMPRESSION_LOGGING", false, "Enable toast impression logging");
+
+ public static final BooleanFlag ENABLE_DEVICE_PROFILE_LOGGING = new DeviceFlag(
+ "ENABLE_DEVICE_PROFILE_LOGGING", false, "Allows DeviceProfile logging");
+
+ public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(
+ "ENABLE_LAUNCH_FROM_STAGED_APP", false,
+ "Enable the ability to tap a staged app during split select to launch it in full screen"
+ );
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
flag.initialize(context);
}
- sDebugFlags.sort((f1, f2) -> f1.key.compareToIgnoreCase(f2.key));
+
+ sDebugFlags.sort((f1, f2) -> {
+ // Sort first by any prefs that the user has changed, then alphabetically.
+ int changeComparison = Boolean.compare(f2.mHasBeenChangedAtLeastOnce,
+ f1.mHasBeenChangedAtLeastOnce);
+ return changeComparison != 0
+ ? changeComparison
+ : f1.key.compareToIgnoreCase(f2.key);
+ });
}
}
@@ -384,6 +428,7 @@
public static class DebugFlag extends BooleanFlag {
public final String description;
+ protected boolean mHasBeenChangedAtLeastOnce;
protected boolean mCurrentValue;
public DebugFlag(String key, boolean defaultValue, String description) {
@@ -401,8 +446,10 @@
}
public void initialize(Context context) {
- mCurrentValue = context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
- .getBoolean(key, defaultValue);
+ SharedPreferences prefs =
+ context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+ mHasBeenChangedAtLeastOnce = prefs.contains(key);
+ mCurrentValue = prefs.getBoolean(key, defaultValue);
}
@Override
diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
index 6729f74..2eb6e6d 100644
--- a/src/com/android/launcher3/config/FlagTogglerPrefUi.java
+++ b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
@@ -52,12 +52,17 @@
public void putBoolean(String key, boolean value) {
for (DebugFlag flag : FeatureFlags.getDebugFlags()) {
if (flag.key.equals(key)) {
- SharedPreferences.Editor editor = mContext.getSharedPreferences(
- FLAGS_PREF_NAME, Context.MODE_PRIVATE).edit();
- if (value == flag.defaultValue) {
+ SharedPreferences prefs = mContext.getSharedPreferences(
+ FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ // We keep the key in the prefs even if it has the default value, because it's a
+ // signal that it has been changed at one point.
+ if (!prefs.contains(key) && value == flag.defaultValue) {
editor.remove(key).apply();
+ flag.mHasBeenChangedAtLeastOnce = false;
} else {
editor.putBoolean(key, value).apply();
+ flag.mHasBeenChangedAtLeastOnce = true;
}
updateMenu();
}
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 05b1984..5a49f4a 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -53,6 +53,8 @@
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.BaseActivity;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
@@ -69,8 +71,8 @@
import com.android.launcher3.views.AbstractSlideInView;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.AddItemWidgetsBottomSheet;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -105,7 +107,8 @@
private WidgetCell mWidgetCell;
// Widget request specific options.
- private LauncherAppWidgetHost mAppWidgetHost;
+ @Nullable
+ private LauncherWidgetHolder mAppWidgetHolder = null;
private WidgetManagerHelper mAppWidgetManager;
private int mPendingBindWidgetId;
private Bundle mWidgetOptions;
@@ -284,7 +287,7 @@
mWidgetCell.setRemoteViewsPreview(PinItemDragListener.getPreview(mRequest));
mAppWidgetManager = new WidgetManagerHelper(this);
- mAppWidgetHost = new LauncherAppWidgetHost(this);
+ mAppWidgetHolder = new LauncherWidgetHolder(this);
PendingAddWidgetInfo pendingInfo =
new PendingAddWidgetInfo(widgetInfo, CONTAINER_PIN_WIDGETS);
@@ -338,7 +341,7 @@
return;
}
- mPendingBindWidgetId = mAppWidgetHost.allocateAppWidgetId();
+ mPendingBindWidgetId = mAppWidgetHolder.allocateAppWidgetId();
AppWidgetProviderInfo widgetProviderInfo = mRequest.getAppWidgetProviderInfo(this);
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
mPendingBindWidgetId, widgetProviderInfo, mWidgetOptions);
@@ -349,7 +352,7 @@
}
// request bind widget
- mAppWidgetHost.startBindFlow(this, mPendingBindWidgetId,
+ mAppWidgetHolder.startBindFlow(this, mPendingBindWidgetId,
mRequest.getAppWidgetProviderInfo(this), REQUEST_BIND_APPWIDGET);
}
@@ -363,6 +366,15 @@
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mAppWidgetHolder != null) {
+ // Necessary to destroy the holder to free up possible activity context
+ mAppWidgetHolder.destroy();
+ }
+ }
+
+ @Override
public void onBackPressed() {
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_BACK);
mSlideInView.close(/* animate= */ true);
@@ -378,7 +390,7 @@
acceptWidget(widgetId);
} else {
// Simply wait it out.
- mAppWidgetHost.deleteAppWidgetId(widgetId);
+ mAppWidgetHolder.deleteAppWidgetId(widgetId);
mPendingBindWidgetId = -1;
}
return;
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 1ee7fc1..366870b 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -56,7 +56,6 @@
import com.android.launcher3.folder.Folder;
import com.android.launcher3.graphics.Scrim;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
-import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
@@ -474,16 +473,6 @@
return mWorkspaceDragScrim;
}
- /**
- * Called when one handed mode state changed.
- * @param activated true if one handed mode activated, false otherwise.
- */
- public void onOneHandedModeStateChanged(boolean activated) {
- for (TouchController controller : mControllers) {
- controller.onOneHandedModeStateChanged(activated);
- }
- }
-
@Override
public void onOverlayScrollChanged(float progress) {
float alpha = 1 - Interpolators.DEACCEL_3.getInterpolation(progress);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 7e14912..99822da 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -292,7 +292,7 @@
mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);
- mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
+ mFooterHeight = dp.folderFooterHeightPx;
if (Utilities.ATLEAST_R) {
mKeyboardInsetAnimationCallback = new KeyboardInsetAnimationCallback(this);
@@ -1167,14 +1167,6 @@
mContent.setFixedSize(contentWidth, contentHeight);
mContent.measure(contentAreaWidthSpec, contentAreaHeightSpec);
- if (mContent.getChildCount() > 0) {
- int cellIconGap = (mContent.getPageAt(0).getCellWidth()
- - mActivityContext.getDeviceProfile().iconSizePx) / 2;
- mFooter.setPadding(mContent.getPaddingLeft() + cellIconGap,
- mFooter.getPaddingTop(),
- mContent.getPaddingRight() + cellIconGap,
- mFooter.getPaddingBottom());
- }
mFooter.measure(contentAreaWidthSpec,
MeasureSpec.makeMeasureSpec(mFooterHeight, MeasureSpec.EXACTLY));
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index d5ef9df..05ad57a 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -168,9 +168,11 @@
final int paddingOffsetY = (int) (mContent.getPaddingTop() * initialScale);
int initialX = folderIconPos.left + mFolder.getPaddingLeft()
- + mPreviewBackground.getOffsetX() - paddingOffsetX - previewItemOffsetX;
+ + Math.round(mPreviewBackground.getOffsetX() * scaleRelativeToDragLayer)
+ - paddingOffsetX - previewItemOffsetX;
int initialY = folderIconPos.top + mFolder.getPaddingTop()
- + mPreviewBackground.getOffsetY() - paddingOffsetY;
+ + Math.round(mPreviewBackground.getOffsetY() * scaleRelativeToDragLayer)
+ - paddingOffsetY;
final float xDistance = initialX - lp.x;
final float yDistance = initialY - lp.y;
@@ -234,9 +236,9 @@
mFolder, startRect, endRect, finalRadius, !mIsOpening));
// Create reveal animator for the folder content (capture the top 4 icons 2x2)
- int width = mDeviceProfile.folderCellLayoutBorderSpacePx.x
+ int width = mDeviceProfile.folderCellLayoutBorderSpacePx
+ mDeviceProfile.folderCellWidthPx * 2;
- int height = mDeviceProfile.folderCellLayoutBorderSpacePx.y
+ int height = mDeviceProfile.folderCellLayoutBorderSpacePx
+ mDeviceProfile.folderCellHeightPx * 2;
int page = mIsOpening ? mContent.getCurrentPage() : mContent.getDestinationPage();
int left = mContent.getPaddingLeft() + page * lp.width;
@@ -313,7 +315,7 @@
addPreviewItemAnimators(a, initialScale / scaleRelativeToDragLayer,
// Background can have a scaled radius in drag and drop mode, so we need to add the
// difference to keep the preview items centered.
- previewItemOffsetX + radiusDiff, radiusDiff);
+ (int) (previewItemOffsetX / scaleRelativeToDragLayer) + radiusDiff, radiusDiff);
return a;
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index e8759da..dd00f07 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -616,11 +616,14 @@
public void drawDot(Canvas canvas) {
if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) {
Rect iconBounds = mDotParams.iconBounds;
+ // FolderIcon draws the icon to be top-aligned (with padding) & horizontally-centered
+ int iconSize = mActivity.getDeviceProfile().iconSizePx;
+ iconBounds.left = (getWidth() - iconSize) / 2;
+ iconBounds.right = iconBounds.left + iconSize;
+ iconBounds.top = getPaddingTop();
+ iconBounds.bottom = iconBounds.top + iconSize;
- Utilities.setRectToViewCenter(this, mActivity.getDeviceProfile().iconSizePx,
- iconBounds);
- iconBounds.offsetTo(iconBounds.left, getPaddingTop());
- float iconScale = (float) mBackground.previewSize / iconBounds.width();
+ float iconScale = (float) mBackground.previewSize / iconSize;
Utilities.scaleRectAboutCenter(iconBounds, iconScale);
// If we are animating to the accepting state, animate the dot out.
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index c28bab5..feadafa 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -1,6 +1,6 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.Utilities.getPrefs;
+import static com.android.launcher3.LauncherPrefs.getPrefs;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS;
import static com.android.launcher3.util.Themes.isThemedIconEnabled;
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 482e923..2361907 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -99,8 +99,8 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.BaseLauncherAppWidgetHostView;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.launcher3.widget.LocalColorExtractor;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.custom.CustomWidgetManager;
@@ -554,7 +554,7 @@
private class LauncherPreviewAppWidgetHost extends AppWidgetHost {
private LauncherPreviewAppWidgetHost(Context context) {
- super(context, LauncherAppWidgetHost.APPWIDGET_HOST_ID);
+ super(context, LauncherWidgetHolder.APPWIDGET_HOST_ID);
}
@Override
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 287b976..85c0a7a 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -50,7 +50,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
import com.android.launcher3.model.BgDataModel;
-import com.android.launcher3.model.GridSizeMigrationTaskV2;
+import com.android.launcher3.model.GridSizeMigrationUtil;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
@@ -241,10 +241,10 @@
@WorkerThread
private boolean doGridMigrationIfNecessary() {
- if (!GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp)) {
+ if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) {
return false;
}
- return GridSizeMigrationTaskV2.migrateGridIfNeeded(mContext, mIdp);
+ return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp);
}
@UiThread
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index 26ddc0b..9a86ede 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -16,7 +16,7 @@
package com.android.launcher3.icons;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
import android.content.ComponentName;
import android.content.Context;
@@ -101,7 +101,7 @@
* Launcher specific checks
*/
public static Drawable getIcon(Context context, ShortcutInfo shortcutInfo, int density) {
- if (GO_DISABLE_SHORTCUTS) {
+ if (GO_DISABLE_WIDGETS) {
return null;
}
try {
diff --git a/src/com/android/launcher3/logging/InstanceId.java b/src/com/android/launcher3/logging/InstanceId.java
index 3c4a644..5bbe07c 100644
--- a/src/com/android/launcher3/logging/InstanceId.java
+++ b/src/com/android/launcher3/logging/InstanceId.java
@@ -47,7 +47,6 @@
this(in.readInt());
}
- @VisibleForTesting
public int getId() {
return mId;
}
diff --git a/src/com/android/launcher3/logging/KeyboardStateManager.java b/src/com/android/launcher3/logging/KeyboardStateManager.java
index 3103af1..6dc0a0b 100644
--- a/src/com/android/launcher3/logging/KeyboardStateManager.java
+++ b/src/com/android/launcher3/logging/KeyboardStateManager.java
@@ -24,6 +24,7 @@
*/
public class KeyboardStateManager {
private long mUpdatedTime;
+ private int mImeHeight;
public enum KeyboardState {
NO_IME_ACTION,
@@ -58,4 +59,18 @@
mUpdatedTime = SystemClock.elapsedRealtime();
mKeyboardState = keyboardState;
}
+
+ /**
+ * Returns keyboard's current height.
+ */
+ public int getImeHeight() {
+ return mImeHeight;
+ }
+
+ /**
+ * Setter method to set keyboard height.
+ */
+ public void setImeHeight(int imeHeight) {
+ mImeHeight = imeHeight;
+ }
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index fcc5d86..0e42d58 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -32,9 +32,12 @@
import com.android.launcher3.logger.LauncherAtom.FromState;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.views.ActivityContext;
+import java.util.List;
+
/**
* Handles the user event logging in R+.
*
@@ -839,6 +842,77 @@
}
/**
+ * Helps to construct and log impression event.
+ */
+ public interface StatsImpressionLogger {
+
+ enum State {
+ UNKNOWN(0),
+ ALLAPPS(1),
+ SEARCHBOX_WIDGET(2);
+ private final int mLauncherState;
+
+ State(int id) {
+ this.mLauncherState = id;
+ }
+
+ public int getLauncherState() {
+ return mLauncherState;
+ }
+ }
+
+ /**
+ * Sets {@link InstanceId} of log message.
+ */
+ default StatsImpressionLogger withInstanceId(InstanceId instanceId) {
+ return this;
+ }
+
+ /**
+ * Sets {@link State} of impression event.
+ */
+ default StatsImpressionLogger withState(State state) {
+ return this;
+ }
+
+ /**
+ * Sets query length of the event.
+ */
+ default StatsImpressionLogger withQueryLength(int queryLength) {
+ return this;
+ }
+
+ /**
+ * Sets list of {@link com.android.app.search.ResultType} for the impression event.
+ */
+ default StatsImpressionLogger withResultType(IntArray resultType) {
+ return this;
+ }
+
+ /**
+ * Sets list of count for each of {@link com.android.app.search.ResultType} for the
+ * impression event.
+ */
+ default StatsImpressionLogger withResultCount(IntArray resultCount) {
+ return this;
+ }
+
+ /**
+ * Sets list of boolean for each of {@link com.android.app.search.ResultType} that indicates
+ * if this result is above keyboard or not for the impression event.
+ */
+ default StatsImpressionLogger withAboveKeyboard(List<Boolean> aboveKeyboard) {
+ return this;
+ }
+
+ /**
+ * Builds the final message and logs it as {@link EventEnum}.
+ */
+ default void log(EventEnum event) {
+ }
+ }
+
+ /**
* Returns new logger object.
*/
public StatsLogger logger() {
@@ -861,6 +935,17 @@
}
/**
+ * Returns new impression logger object.
+ */
+ public StatsImpressionLogger impressionLogger() {
+ StatsImpressionLogger logger = createImpressionLogger();
+ if (mInstanceId != null) {
+ logger.withInstanceId(mInstanceId);
+ }
+ return logger;
+ }
+
+ /**
* Returns a singleton KeyboardStateManager.
*/
public KeyboardStateManager keyboardStateManager() {
@@ -880,6 +965,11 @@
};
}
+ protected StatsImpressionLogger createImpressionLogger() {
+ return new StatsImpressionLogger() {
+ };
+ }
+
/**
* Sets InstanceId to every new {@link StatsLogger} object returned by {@link #logger()} when
* not-null.
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 5b6f9f6..74a2c5d 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -118,8 +118,7 @@
}
public void bindExtraContainerItems(@NonNull final FixedContainerItems item) {
- FixedContainerItems copy = item.clone();
- scheduleCallbackTask(c -> c.bindExtraContainerItems(copy));
+ scheduleCallbackTask(c -> c.bindExtraContainerItems(item));
}
public void bindDeepShortcuts(@NonNull final BgDataModel dataModel) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index ffb0f2f..b0f6e13 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -17,7 +17,7 @@
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
import static com.android.launcher3.shortcuts.ShortcutRequest.PINNED;
import static java.util.stream.Collectors.groupingBy;
@@ -286,7 +286,7 @@
* shortcuts and unpinning any extra shortcuts.
*/
public synchronized void updateShortcutPinnedState(Context context, UserHandle user) {
- if (GO_DISABLE_SHORTCUTS) {
+ if (GO_DISABLE_WIDGETS) {
return;
}
@@ -433,26 +433,9 @@
public final int containerId;
public final List<ItemInfo> items;
- public FixedContainerItems(int containerId) {
- this(containerId, new ArrayList<>());
- }
-
public FixedContainerItems(int containerId, List<ItemInfo> items) {
this.containerId = containerId;
- this.items = items;
- }
-
- @Override
- public FixedContainerItems clone() {
- return new FixedContainerItems(containerId, new ArrayList<>(items));
- }
-
- public void setItems(List<ItemInfo> newItems) {
- items.clear();
- newItems.forEach(item -> {
- item.container = containerId;
- items.add(item);
- });
+ this.items = Collections.unmodifiableList(items);
}
}
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index 46f0b0b..85d54c0 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -29,7 +29,7 @@
import android.text.TextUtils;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import java.util.Locale;
@@ -58,7 +58,7 @@
}
public DeviceGridState(Context context) {
- SharedPreferences prefs = Utilities.getPrefs(context);
+ SharedPreferences prefs = LauncherPrefs.getPrefs(context);
mGridSizeString = prefs.getString(KEY_WORKSPACE_SIZE, "");
mNumHotseat = prefs.getInt(KEY_HOTSEAT_COUNT, -1);
mDeviceType = prefs.getInt(KEY_DEVICE_TYPE, TYPE_PHONE);
@@ -90,7 +90,7 @@
* Stores the device state to shared preferences
*/
public void writeToPrefs(Context context) {
- Utilities.getPrefs(context).edit()
+ LauncherPrefs.getPrefs(context).edit()
.putString(KEY_WORKSPACE_SIZE, mGridSizeString)
.putInt(KEY_HOTSEAT_COUNT, mNumHotseat)
.putInt(KEY_DEVICE_TYPE, mDeviceType)
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
similarity index 75%
rename from src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
rename to src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 341372e..d63408b 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -32,7 +32,6 @@
import android.util.Log;
import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -64,42 +63,13 @@
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
* result of restoring from a larger device or device density change.
*/
-public class GridSizeMigrationTaskV2 {
+public class GridSizeMigrationUtil {
- private static final String TAG = "GridSizeMigrationTaskV2";
+ private static final String TAG = "GridSizeMigrationUtil";
private static final boolean DEBUG = false;
- private final Context mContext;
- private final SQLiteDatabase mDb;
- private final DbReader mSrcReader;
- private final DbReader mDestReader;
-
- private final List<DbEntry> mHotseatItems;
- private final List<DbEntry> mWorkspaceItems;
-
- private final List<DbEntry> mHotseatDiff;
- private final List<DbEntry> mWorkspaceDiff;
-
- private final int mDestHotseatSize;
- private final int mTrgX, mTrgY;
-
- @VisibleForTesting
- protected GridSizeMigrationTaskV2(Context context, SQLiteDatabase db, DbReader srcReader,
- DbReader destReader, int destHotseatSize, Point targetSize) {
- mContext = context;
- mDb = db;
- mSrcReader = srcReader;
- mDestReader = destReader;
-
- mHotseatItems = destReader.loadHotseatEntries();
- mWorkspaceItems = destReader.loadAllWorkspaceEntries();
-
- mHotseatDiff = calcDiff(mSrcReader.loadHotseatEntries(), mHotseatItems);
- mWorkspaceDiff = calcDiff(mSrcReader.loadAllWorkspaceEntries(), mWorkspaceItems);
- mDestHotseatSize = destHotseatSize;
-
- mTrgX = targetSize.x;
- mTrgY = targetSize.y;
+ private GridSizeMigrationUtil() {
+ // Util class should not be instantiated
}
/**
@@ -187,9 +157,8 @@
context, validPackages);
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
- GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(context, t.getDb(),
- srcReader, destReader, destDeviceState.getNumHotseat(), targetSize);
- task.migrate(srcDeviceState, destDeviceState);
+ migrate(context, t.getDb(), srcReader, destReader, destDeviceState.getNumHotseat(),
+ targetSize, srcDeviceState, destDeviceState);
if (!migrateForPreview) {
dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
@@ -212,25 +181,39 @@
}
}
- @VisibleForTesting
- protected boolean migrate(DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
- if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
+ public static boolean migrate(
+ @NonNull final Context context, @NonNull final SQLiteDatabase db,
+ @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
+ final int destHotseatSize, @NonNull final Point targetSize,
+ @NonNull final DeviceGridState srcDeviceState,
+ @NonNull final DeviceGridState destDeviceState) {
+
+ final List<DbEntry> hotseatItems = destReader.loadHotseatEntries();
+ final List<DbEntry> workspaceItems = destReader.loadAllWorkspaceEntries();
+ final List<DbEntry> hotseatDiff =
+ calcDiff(srcReader.loadHotseatEntries(), hotseatItems);
+ final List<DbEntry> workspaceDiff =
+ calcDiff(srcReader.loadAllWorkspaceEntries(), workspaceItems);
+
+ final int trgX = targetSize.x;
+ final int trgY = targetSize.y;
+
+ if (hotseatDiff.isEmpty() && workspaceDiff.isEmpty()) {
return false;
}
// Sort the items by the reading order.
- Collections.sort(mHotseatDiff);
- Collections.sort(mWorkspaceDiff);
+ Collections.sort(hotseatDiff);
+ Collections.sort(workspaceDiff);
// Migrate hotseat
- HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
- hotseatSolution.find();
+ solveHotseatPlacement(db, srcReader,
+ destReader, context, destHotseatSize, hotseatItems, hotseatDiff);
// Migrate workspace.
// First we create a collection of the screens
List<Integer> screens = new ArrayList<>();
- for (int screenId = 0; screenId <= mDestReader.mLastScreenId; screenId++) {
+ for (int screenId = 0; screenId <= destReader.mLastScreenId; screenId++) {
screens.add(screenId);
}
@@ -245,22 +228,19 @@
if (DEBUG) {
Log.d(TAG, "Migrating " + screenId);
}
- GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff, false);
- workspaceSolution.find();
- if (mWorkspaceDiff.isEmpty()) {
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceDiff, false);
+ if (workspaceDiff.isEmpty()) {
break;
}
}
// In case the new grid is smaller, there might be some leftover items that don't fit on
// any of the screens, in this case we add them to new screens until all of them are placed.
- int screenId = mDestReader.mLastScreenId + 1;
- while (!mWorkspaceDiff.isEmpty()) {
- GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff,
- preservePages);
- workspaceSolution.find();
+ int screenId = destReader.mLastScreenId + 1;
+ while (!workspaceDiff.isEmpty()) {
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceDiff, preservePages);
screenId++;
}
@@ -365,144 +345,88 @@
return validPackages;
}
- protected static class GridPlacementSolution {
-
- private final SQLiteDatabase mDb;
- private final DbReader mSrcReader;
- private final DbReader mDestReader;
- private final Context mContext;
- private final GridOccupancy mOccupied;
- private final int mScreenId;
- private final int mTrgX;
- private final int mTrgY;
- private final List<DbEntry> mSortedItemsToPlace;
- private final boolean mMatchingScreenIdOnly;
-
- private int mNextStartX;
- private int mNextStartY;
-
- GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
- Context context, int screenId, int trgX, int trgY, List<DbEntry> sortedItemsToPlace,
- boolean matchingScreenIdOnly) {
- mDb = db;
- mSrcReader = srcReader;
- mDestReader = destReader;
- mContext = context;
- mOccupied = new GridOccupancy(trgX, trgY);
- mScreenId = screenId;
- mTrgX = trgX;
- mTrgY = trgY;
- mNextStartX = 0;
- mNextStartY = mScreenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN
- ? 1 /* smartspace */ : 0;
- List<DbEntry> existedEntries = mDestReader.mWorkspaceEntriesByScreenId.get(screenId);
- if (existedEntries != null) {
- for (DbEntry entry : existedEntries) {
- mOccupied.markCells(entry, true);
- }
- }
- mSortedItemsToPlace = sortedItemsToPlace;
- mMatchingScreenIdOnly = matchingScreenIdOnly;
- }
-
- public void find() {
- Iterator<DbEntry> iterator = mSortedItemsToPlace.iterator();
- while (iterator.hasNext()) {
- final DbEntry entry = iterator.next();
- if (mMatchingScreenIdOnly && entry.screenId < mScreenId) continue;
- if (mMatchingScreenIdOnly && entry.screenId > mScreenId) break;
- if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
- iterator.remove();
- continue;
- }
- if (findPlacement(entry)) {
- insertEntryInDb(mDb, mContext, entry, mSrcReader.mTableName,
- mDestReader.mTableName);
- iterator.remove();
- }
+ private static void solveGridPlacement(@NonNull final SQLiteDatabase db,
+ @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
+ @NonNull final Context context, final int screenId, final int trgX, final int trgY,
+ @NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
+ final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
+ final Point trg = new Point(trgX, trgY);
+ final Point next = new Point(0, screenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN
+ ? 1 /* smartspace */ : 0);
+ List<DbEntry> existedEntries = destReader.mWorkspaceEntriesByScreenId.get(screenId);
+ if (existedEntries != null) {
+ for (DbEntry entry : existedEntries) {
+ occupied.markCells(entry, true);
}
}
-
- /**
- * Search for the next possible placement of an icon. (mNextStartX, mNextStartY) serves as
- * a memoization of last placement, we can start our search for next placement from there
- * to speed up the search.
- */
- private boolean findPlacement(DbEntry entry) {
- for (int y = mNextStartY; y < mTrgY; y++) {
- for (int x = mNextStartX; x < mTrgX; x++) {
- boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
- boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,
- entry.minSpanY);
- if (minFits) {
- entry.spanX = entry.minSpanX;
- entry.spanY = entry.minSpanY;
- }
- if (fits || minFits) {
- entry.screenId = mScreenId;
- entry.cellX = x;
- entry.cellY = y;
- mOccupied.markCells(entry, true);
- mNextStartX = x + entry.spanX;
- mNextStartY = y;
- return true;
- }
- }
- mNextStartX = 0;
+ Iterator<DbEntry> iterator = sortedItemsToPlace.iterator();
+ while (iterator.hasNext()) {
+ final DbEntry entry = iterator.next();
+ if (matchingScreenIdOnly && entry.screenId < screenId) continue;
+ if (matchingScreenIdOnly && entry.screenId > screenId) break;
+ if (entry.minSpanX > trgX || entry.minSpanY > trgY) {
+ iterator.remove();
+ continue;
}
- return false;
+ if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
+ iterator.remove();
+ }
}
}
- protected static class HotseatPlacementSolution {
-
- private final SQLiteDatabase mDb;
- private final DbReader mSrcReader;
- private final DbReader mDestReader;
- private final Context mContext;
- private final HotseatOccupancy mOccupied;
- private final List<DbEntry> mItemsToPlace;
-
- HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
- Context context, int hotseatSize, List<DbEntry> placedHotseatItems,
- List<DbEntry> itemsToPlace) {
- mDb = db;
- mSrcReader = srcReader;
- mDestReader = destReader;
- mContext = context;
- mOccupied = new HotseatOccupancy(hotseatSize);
- for (DbEntry entry : placedHotseatItems) {
- mOccupied.markCells(entry, true);
- }
- mItemsToPlace = itemsToPlace;
- }
-
- public void find() {
- for (int i = 0; i < mOccupied.mCells.length; i++) {
- if (!mOccupied.mCells[i] && !mItemsToPlace.isEmpty()) {
- DbEntry entry = mItemsToPlace.remove(0);
- entry.screenId = i;
- // These values does not affect the item position, but we should set them
- // to something other than -1.
- entry.cellX = i;
- entry.cellY = 0;
- insertEntryInDb(mDb, mContext, entry, mSrcReader.mTableName,
- mDestReader.mTableName);
- mOccupied.markCells(entry, true);
+ /**
+ * Search for the next possible placement of an icon. (mNextStartX, mNextStartY) serves as
+ * a memoization of last placement, we can start our search for next placement from there
+ * to speed up the search.
+ */
+ private static boolean findPlacementForEntry(@NonNull final DbEntry entry,
+ @NonNull final Point next, @NonNull final Point trg,
+ @NonNull final GridOccupancy occupied, final int screenId) {
+ for (int y = next.y; y < trg.y; y++) {
+ for (int x = next.x; x < trg.x; x++) {
+ boolean fits = occupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
+ boolean minFits = occupied.isRegionVacant(x, y, entry.minSpanX,
+ entry.minSpanY);
+ if (minFits) {
+ entry.spanX = entry.minSpanX;
+ entry.spanY = entry.minSpanY;
+ }
+ if (fits || minFits) {
+ entry.screenId = screenId;
+ entry.cellX = x;
+ entry.cellY = y;
+ occupied.markCells(entry, true);
+ next.set(x + entry.spanX, y);
+ return true;
}
}
+ next.set(0, next.y);
+ }
+ return false;
+ }
+
+ private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db,
+ @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
+ @NonNull final Context context, final int hotseatSize,
+ @NonNull final List<DbEntry> placedHotseatItems,
+ @NonNull final List<DbEntry> itemsToPlace) {
+
+ final boolean[] occupied = new boolean[hotseatSize];
+ for (DbEntry entry : placedHotseatItems) {
+ occupied[entry.screenId] = true;
}
- private class HotseatOccupancy {
-
- private final boolean[] mCells;
-
- private HotseatOccupancy(int hotseatSize) {
- mCells = new boolean[hotseatSize];
- }
-
- private void markCells(ItemInfo item, boolean value) {
- mCells[item.screenId] = value;
+ for (int i = 0; i < occupied.length; i++) {
+ if (!occupied[i] && !itemsToPlace.isEmpty()) {
+ DbEntry entry = itemsToPlace.remove(0);
+ entry.screenId = i;
+ // These values does not affect the item position, but we should set them
+ // to something other than -1.
+ entry.cellX = i;
+ entry.cellY = 0;
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
+ occupied[entry.screenId] = true;
}
}
}
@@ -515,8 +439,6 @@
private final Set<String> mValidPackages;
private int mLastScreenId = -1;
- private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
- private final ArrayList<DbEntry> mWorkspaceEntries = new ArrayList<>();
private final Map<Integer, ArrayList<DbEntry>> mWorkspaceEntriesByScreenId =
new ArrayMap<>();
@@ -528,7 +450,8 @@
mValidPackages = validPackages;
}
- protected ArrayList<DbEntry> loadHotseatEntries() {
+ protected List<DbEntry> loadHotseatEntries() {
+ final List<DbEntry> hotseatEntries = new ArrayList<>();
Cursor c = queryWorkspace(
new String[]{
LauncherSettings.Favorites._ID, // 0
@@ -577,14 +500,15 @@
entriesToRemove.add(entry.id);
continue;
}
- mHotseatEntries.add(entry);
+ hotseatEntries.add(entry);
}
removeEntryFromDb(mDb, mTableName, entriesToRemove);
c.close();
- return mHotseatEntries;
+ return hotseatEntries;
}
- protected ArrayList<DbEntry> loadAllWorkspaceEntries() {
+ protected List<DbEntry> loadAllWorkspaceEntries() {
+ final List<DbEntry> workspaceEntries = new ArrayList<>();
Cursor c = queryWorkspace(
new String[]{
LauncherSettings.Favorites._ID, // 0
@@ -599,10 +523,6 @@
LauncherSettings.Favorites.APPWIDGET_ID}, // 9
LauncherSettings.Favorites.CONTAINER + " = "
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
- return loadWorkspaceEntries(c);
- }
-
- private ArrayList<DbEntry> loadWorkspaceEntries(Cursor c) {
final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
@@ -678,7 +598,7 @@
entriesToRemove.add(entry.id);
continue;
}
- mWorkspaceEntries.add(entry);
+ workspaceEntries.add(entry);
if (!mWorkspaceEntriesByScreenId.containsKey(entry.screenId)) {
mWorkspaceEntriesByScreenId.put(entry.screenId, new ArrayList<>());
}
@@ -686,7 +606,7 @@
}
removeEntryFromDb(mDb, mTableName, entriesToRemove);
c.close();
- return mWorkspaceEntries;
+ return workspaceEntries;
}
private int getFolderItemsCount(DbEntry entry) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index b644b6b..1d6971e 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -349,7 +349,7 @@
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
boolean clearDb = false;
- if (!GridSizeMigrationTaskV2.migrateGridIfNeeded(context)) {
+ if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) {
// Migration failed. Clear workspace.
clearDb = true;
}
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
index 1ced0b1..c21fc38 100644
--- a/src/com/android/launcher3/model/ModelUtils.java
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.Utilities.isValidExtraType;
-
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -149,4 +147,12 @@
info.intent = launchIntent;
return info;
}
+
+ /**
+ * @return true if the extra is either null or is of type {@param type}
+ */
+ private static boolean isValidExtraType(Intent intent, String key, Class type) {
+ Object extra = intent.getParcelableExtra(key);
+ return extra == null || type.isInstance(extra);
+ }
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 514e7b2..f444bd5 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -36,7 +36,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
-import com.android.launcher3.LauncherWidgetHolder;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
@@ -49,6 +48,7 @@
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 16bb868..150bca4 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -16,7 +16,7 @@
package com.android.launcher3.pm;
-import static com.android.launcher3.Utilities.getPrefs;
+import static com.android.launcher3.LauncherPrefs.getPrefs;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 196cc56..9a745ab 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -21,14 +21,12 @@
import static com.android.launcher3.anim.Interpolators.ACCELERATED_EASE;
import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_LOCAL_COLOR_POPUPS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
@@ -36,15 +34,12 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
-import android.os.Build;
import android.util.AttributeSet;
import android.util.Pair;
-import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
@@ -52,21 +47,17 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.Workspace;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
-import com.android.launcher3.widget.LocalColorExtractor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
/**
* A container for shortcuts to deep links and notifications associated with an app.
@@ -89,10 +80,6 @@
protected int CLOSE_CHILD_FADE_START_DELAY = 0;
protected int CLOSE_CHILD_FADE_DURATION = 140;
- // Index used to get background color when using local wallpaper color extraction,
- private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_neutral2_800;
- private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
-
protected final Rect mTempRect = new Rect();
protected final LayoutInflater mInflater;
@@ -124,10 +111,8 @@
// The rect string of the view that the arrow is attached to, in screen reference frame.
protected int mArrowColor;
- protected final List<LocalColorExtractor> mColorExtractors;
protected final float mElevation;
- private final int mBackgroundColor;
private final String mIterateChildrenTag;
@@ -140,8 +125,8 @@
mActivityContext = ActivityContext.lookupContext(context);
mIsRtl = Utilities.isRtl(getResources());
- mBackgroundColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
- mArrowColor = mBackgroundColor;
+ int backgroundColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
+ mArrowColor = backgroundColor;
mElevation = getResources().getDimension(R.dimen.deep_shortcuts_elevation);
// Initialize arrow view
@@ -158,25 +143,18 @@
int smallerRadius = resources.getDimensionPixelSize(R.dimen.popup_smaller_radius);
mRoundedTop = new GradientDrawable();
- mRoundedTop.setColor(mBackgroundColor);
+ mRoundedTop.setColor(backgroundColor);
mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius,
mOutlineRadius, smallerRadius, smallerRadius, smallerRadius, smallerRadius});
mRoundedBottom = new GradientDrawable();
- mRoundedBottom.setColor(mBackgroundColor);
+ mRoundedBottom.setColor(backgroundColor);
mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius,
smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius});
mIterateChildrenTag = getContext().getString(R.string.popup_container_iterate_children);
- boolean shouldUseColorExtraction = mActivityContext.shouldUseColorExtractionForPopup();
- if (shouldUseColorExtraction && Utilities.ATLEAST_S && ENABLE_LOCAL_COLOR_POPUPS.get()) {
- mColorExtractors = new ArrayList<>();
- } else {
- mColorExtractors = null;
- }
-
- if (shouldUseColorExtraction) {
+ if (mActivityContext.shouldUseColorExtractionForPopup()) {
mColorIds = new int[]{R.color.popup_shade_first, R.color.popup_shade_second,
R.color.popup_shade_third};
} else {
@@ -220,11 +198,6 @@
}
/**
- * Called when all view inflation and reordering in complete.
- */
- protected void onInflationComplete(boolean isReversed) { }
-
- /**
* Set the margins and radius of backgrounds after views are properly ordered.
*/
public void assignMarginsAndBackgrounds(ViewGroup viewGroup) {
@@ -271,13 +244,9 @@
backgroundColor = colors[numVisibleChild % colors.length];
}
- if (!ENABLE_LOCAL_COLOR_POPUPS.get()) {
- // Arrow color matches the first child or the last child.
- if (!mIsAboveIcon && numVisibleChild == 0 && viewGroup == this) {
- mArrowColor = backgroundColor;
- } else if (mIsAboveIcon) {
- mArrowColor = backgroundColor;
- }
+ // Arrow color matches the first child or the last child.
+ if (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this)) {
+ mArrowColor = backgroundColor;
}
if (view instanceof ViewGroup && mIterateChildrenTag.equals(view.getTag())) {
@@ -301,10 +270,7 @@
}
}
- if (!ENABLE_LOCAL_COLOR_POPUPS.get()) {
- setChildColor(view, backgroundColor, colorAnimator);
- }
-
+ setChildColor(view, backgroundColor, colorAnimator);
numVisibleChild++;
}
}
@@ -320,85 +286,6 @@
return view instanceof DeepShortcutView;
}
- @TargetApi(Build.VERSION_CODES.S)
- private int getExtractedColor(SparseIntArray colors) {
- int index = Utilities.isDarkTheme(getContext())
- ? DARK_COLOR_EXTRACTION_INDEX
- : LIGHT_COLOR_EXTRACTION_INDEX;
- return colors.get(index, mBackgroundColor);
- }
-
- protected void addPreDrawForColorExtraction(Launcher launcher) {
- getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- getViewTreeObserver().removeOnPreDrawListener(this);
- initColorExtractionLocations(launcher);
- return true;
- }
- });
- }
-
- /**
- * Returns list of child views that will receive local color extraction treatment.
- * Note: Order should match the view hierarchy.
- */
- protected List<View> getChildrenForColorExtraction() {
- return Collections.emptyList();
- }
-
- private void initColorExtractionLocations(Launcher launcher) {
- if (mColorExtractors == null) {
- return;
- }
- Workspace<?> workspace = launcher.getWorkspace();
- if (workspace == null) {
- return;
- }
-
- boolean firstVisibleChild = true;
- int screenId = workspace.getScreenIdForPageIndex(workspace.getCurrentPage());
- DragLayer dragLayer = launcher.getDragLayer();
-
- final View[] viewAlignedWithArrow = new View[1];
-
- // Order matters here, since we need the arrow to match the color of its adjacent view.
- for (final View view : getChildrenForColorExtraction()) {
- if (view != null && view.getVisibility() == VISIBLE) {
- Rect pos = new Rect();
- dragLayer.getDescendantRectRelativeToSelf(view, pos);
- if (!pos.isEmpty()) {
- LocalColorExtractor extractor = LocalColorExtractor.newInstance(launcher);
- extractor.setWorkspaceLocation(pos, dragLayer, screenId);
- extractor.setListener(extractedColors -> {
- AnimatorSet colors = new AnimatorSet();
- int newColor = getExtractedColor(extractedColors);
- setChildColor(view, newColor, colors);
- int numChildren = view instanceof ViewGroup
- ? ((ViewGroup) view).getChildCount() : 0;
- for (int i = 0; i < numChildren; ++i) {
- View childView = ((ViewGroup) view).getChildAt(i);
- setChildColor(childView, newColor, colors);
- }
- if (viewAlignedWithArrow[0] == view) {
- mArrowColor = newColor;
- updateArrowColor();
- }
- colors.setDuration(150);
- view.post(colors::start);
- });
- mColorExtractors.add(extractor);
-
- if (mIsAboveIcon || firstVisibleChild) {
- viewAlignedWithArrow[0] = view;
- }
- firstVisibleChild = false;
- }
- }
- }
-
- }
-
/**
* Sets the background color of the child.
*/
@@ -425,7 +312,6 @@
if (reverseOrder) {
reverseOrder(viewsToFlip);
}
- onInflationComplete(reverseOrder);
assignMarginsAndBackgrounds(this);
if (shouldAddArrow()) {
addArrow();
@@ -438,7 +324,6 @@
*/
public void show() {
setupForDisplay();
- onInflationComplete(false);
assignMarginsAndBackgrounds(this);
if (shouldAddArrow()) {
addArrow();
@@ -819,9 +704,6 @@
if (mOnCloseCallback != null) {
mOnCloseCallback.run();
}
- if (mColorExtractors != null) {
- mColorExtractors.forEach(e -> e.setListener(null));
- }
}
/**
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 8e7a10c..4da588e 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -69,7 +69,6 @@
import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -236,13 +235,6 @@
mPopupItemDragHandler = new LauncherPopupItemDragHandler(launcher, this);
mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(launcher);
launcher.getDragController().addDragListener(this);
- addPreDrawForColorExtraction(launcher);
- }
-
- @Override
- protected List<View> getChildrenForColorExtraction() {
- return Arrays.asList(mSystemShortcutContainer, mWidgetContainer, mDeepShortcutContainer,
- mNotificationContainer);
}
private void initializeSystemShortcuts(List<SystemShortcut> shortcuts) {
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 48b3acf..a45e835 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -36,6 +36,7 @@
import com.android.launcher3.AppWidgetsRestoredReceiver;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherProvider.DatabaseHelper;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
@@ -47,6 +48,7 @@
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.LogConfig;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import java.io.InvalidObjectException;
import java.util.Arrays;
@@ -85,7 +87,7 @@
// Set is pending to false irrespective of the result, so that it doesn't get
// executed again.
- Utilities.getPrefs(context).edit().remove(RESTORED_DEVICE_TYPE).commit();
+ LauncherPrefs.getPrefs(context).edit().remove(RESTORED_DEVICE_TYPE).commit();
idp.reinitializeAfterRestore(context);
}
@@ -238,7 +240,7 @@
}
// If restored from a single display backup, remove gaps between screenIds
- if (Utilities.getPrefs(context).getInt(RESTORED_DEVICE_TYPE, TYPE_PHONE)
+ if (LauncherPrefs.getPrefs(context).getInt(RESTORED_DEVICE_TYPE, TYPE_PHONE)
!= TYPE_MULTI_DISPLAY) {
removeScreenIdGaps(db);
}
@@ -337,7 +339,7 @@
}
public static boolean isPending(Context context) {
- return Utilities.getPrefs(context).contains(RESTORED_DEVICE_TYPE);
+ return LauncherPrefs.getPrefs(context).contains(RESTORED_DEVICE_TYPE);
}
/**
@@ -345,17 +347,20 @@
*/
public static void setPending(Context context) {
FileLog.d(TAG, "Restore data received through full backup ");
- Utilities.getPrefs(context).edit()
+ LauncherPrefs.getPrefs(context).edit()
.putInt(RESTORED_DEVICE_TYPE, new DeviceGridState(context).getDeviceType())
.commit();
}
private void restoreAppWidgetIdsIfExists(Context context) {
- SharedPreferences prefs = Utilities.getPrefs(context);
+ SharedPreferences prefs = LauncherPrefs.getPrefs(context);
if (prefs.contains(APPWIDGET_OLD_IDS) && prefs.contains(APPWIDGET_IDS)) {
+ LauncherWidgetHolder holder = new LauncherWidgetHolder(context);
AppWidgetsRestoredReceiver.restoreAppWidgetIds(context,
IntArray.fromConcatString(prefs.getString(APPWIDGET_OLD_IDS, "")).toArray(),
- IntArray.fromConcatString(prefs.getString(APPWIDGET_IDS, "")).toArray());
+ IntArray.fromConcatString(prefs.getString(APPWIDGET_IDS, "")).toArray(),
+ holder);
+ holder.destroy();
} else {
FileLog.d(TAG, "No app widget ids to restore.");
}
@@ -366,7 +371,7 @@
public static void setRestoredAppWidgetIds(Context context, @NonNull int[] oldIds,
@NonNull int[] newIds) {
- Utilities.getPrefs(context).edit()
+ LauncherPrefs.getPrefs(context).edit()
.putString(APPWIDGET_OLD_IDS, IntArray.wrap(oldIds).toConcatString())
.putString(APPWIDGET_IDS, IntArray.wrap(newIds).toConcatString())
.commit();
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index 23ee251..f295204 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -43,8 +43,8 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.FragmentWithPreview;
import com.android.launcher3.widget.util.WidgetSizes;
@@ -200,7 +200,7 @@
Context context = getContext();
AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
- int widgetId = Utilities.getPrefs(context).getInt(mKeyWidgetId, -1);
+ int widgetId = LauncherPrefs.getPrefs(context).getInt(mKeyWidgetId, -1);
AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId);
boolean isWidgetBound = (widgetInfo != null) &&
widgetInfo.provider.equals(mWidgetInfo.provider);
@@ -244,7 +244,7 @@
}
private void saveWidgetId(int widgetId) {
- Utilities.getPrefs(getContext()).edit().putInt(mKeyWidgetId, widgetId).apply();
+ LauncherPrefs.getPrefs(getContext()).edit().putInt(mKeyWidgetId, widgetId).apply();
}
@Override
diff --git a/src/com/android/launcher3/search/SearchCallback.java b/src/com/android/launcher3/search/SearchCallback.java
index 495a303..cf7ab10 100644
--- a/src/com/android/launcher3/search/SearchCallback.java
+++ b/src/com/android/launcher3/search/SearchCallback.java
@@ -24,6 +24,11 @@
*/
public interface SearchCallback<T> {
+ // Search Result Codes
+ int UNKNOWN = 0;
+ int INTERMEDIATE = 1;
+ int FINAL = 2;
+
/**
* Called when the search from primary source is complete.
*
@@ -32,6 +37,17 @@
void onSearchResult(String query, ArrayList<T> items);
/**
+ * Called when the search from primary source is complete.
+ *
+ * @param items list of search results
+ * @param searchResultCode indicates if the result is final or intermediate for a given query
+ * since we can get search results from multiple sources.
+ */
+ default void onSearchResult(String query, ArrayList<T> items, int searchResultCode) {
+ onSearchResult(query, items);
+ }
+
+ /**
* Called when the search results should be cleared.
*/
void clearSearchResult();
diff --git a/src/com/android/launcher3/search/StringMatcherUtility.java b/src/com/android/launcher3/search/StringMatcherUtility.java
index acab52b..c66f3a1 100644
--- a/src/com/android/launcher3/search/StringMatcherUtility.java
+++ b/src/com/android/launcher3/search/StringMatcherUtility.java
@@ -24,8 +24,8 @@
public class StringMatcherUtility {
/**
- * Returns {@code true} is {@code query} is a prefix substring of a complete word/phrase in
- * {@code target}.
+ * Returns {@code true} if {@code query} is a prefix of a substring in {@code target}. How to
+ * break target to valid substring is defined in the given {@code matcher}.
*/
public static boolean matches(String query, String target, StringMatcher matcher) {
int queryLength = query.length();
@@ -50,7 +50,7 @@
thisType = nextType;
nextType = i < (targetLength - 1)
? Character.getType(target.codePointAt(i + 1)) : Character.UNASSIGNED;
- if (isBreak(thisType, lastType, nextType)
+ if (matcher.isBreak(thisType, lastType, nextType)
&& matcher.matches(query, target.substring(i, i + queryLength))) {
return true;
}
@@ -59,52 +59,6 @@
}
/**
- * Returns true if the current point should be a break point. Following cases
- * are considered as break points:
- * 1) Any non space character after a space character
- * 2) Any digit after a non-digit character
- * 3) Any capital character after a digit or small character
- * 4) Any capital character before a small character
- */
- private static boolean isBreak(int thisType, int prevType, int nextType) {
- switch (prevType) {
- case Character.UNASSIGNED:
- case Character.SPACE_SEPARATOR:
- case Character.LINE_SEPARATOR:
- case Character.PARAGRAPH_SEPARATOR:
- return true;
- }
- switch (thisType) {
- case Character.UPPERCASE_LETTER:
- if (nextType == Character.UPPERCASE_LETTER) {
- return true;
- }
- // Follow through
- case Character.TITLECASE_LETTER:
- // Break point if previous was not a upper case
- return prevType != Character.UPPERCASE_LETTER;
- case Character.LOWERCASE_LETTER:
- // Break point if previous was not a letter.
- return prevType > Character.OTHER_LETTER || prevType <= Character.UNASSIGNED;
- case Character.DECIMAL_DIGIT_NUMBER:
- case Character.LETTER_NUMBER:
- case Character.OTHER_NUMBER:
- // Break point if previous was not a number
- return !(prevType == Character.DECIMAL_DIGIT_NUMBER
- || prevType == Character.LETTER_NUMBER
- || prevType == Character.OTHER_NUMBER);
- case Character.MATH_SYMBOL:
- case Character.CURRENCY_SYMBOL:
- case Character.OTHER_PUNCTUATION:
- case Character.DASH_PUNCTUATION:
- // Always a break point for a symbol
- return true;
- default:
- return false;
- }
- }
-
- /**
* Performs locale sensitive string comparison using {@link Collator}.
*/
public static class StringMatcher {
@@ -142,6 +96,75 @@
public static StringMatcher getInstance() {
return new StringMatcher();
}
+
+ /**
+ * Returns true if the current point should be a break point.
+ *
+ * Following cases are considered as break points:
+ * 1) Any non space character after a space character
+ * 2) Any digit after a non-digit character
+ * 3) Any capital character after a digit or small character
+ * 4) Any capital character before a small character
+ *
+ * E.g., "YouTube" matches the input "you" and "tube", but not "out".
+ */
+ protected boolean isBreak(int thisType, int prevType, int nextType) {
+ switch (prevType) {
+ case Character.UNASSIGNED:
+ case Character.SPACE_SEPARATOR:
+ case Character.LINE_SEPARATOR:
+ case Character.PARAGRAPH_SEPARATOR:
+ return true;
+ }
+ switch (thisType) {
+ case Character.UPPERCASE_LETTER:
+ if (nextType == Character.UPPERCASE_LETTER) {
+ return true;
+ }
+ // Follow through
+ case Character.TITLECASE_LETTER:
+ // Break point if previous was not a upper case
+ return prevType != Character.UPPERCASE_LETTER;
+ case Character.LOWERCASE_LETTER:
+ // Break point if previous was not a letter.
+ return prevType > Character.OTHER_LETTER || prevType <= Character.UNASSIGNED;
+ case Character.DECIMAL_DIGIT_NUMBER:
+ case Character.LETTER_NUMBER:
+ case Character.OTHER_NUMBER:
+ // Break point if previous was not a number
+ return !(prevType == Character.DECIMAL_DIGIT_NUMBER
+ || prevType == Character.LETTER_NUMBER
+ || prevType == Character.OTHER_NUMBER);
+ case Character.MATH_SYMBOL:
+ case Character.CURRENCY_SYMBOL:
+ case Character.OTHER_PUNCTUATION:
+ case Character.DASH_PUNCTUATION:
+ // Always a break point for a symbol
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Subclass of {@code StringMatcher} using simple space break for prefix matching.
+ * E.g., "YouTube" matches the input "you". "Play Store" matches the input "play".
+ */
+ public static class StringMatcherSpace extends StringMatcher {
+
+ public static StringMatcherSpace getInstance() {
+ return new StringMatcherSpace();
+ }
+
+ /**
+ * The first character or any character after a space is considered as a break point.
+ * Returns true if the current point should be a break point.
+ */
+ @Override
+ protected boolean isBreak(int thisType, int prevType, int nextType) {
+ return prevType == Character.UNASSIGNED || prevType == Character.SPACE_SEPARATOR;
+ }
}
/**
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 7b32d8b..dbab700 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -35,9 +35,9 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
@@ -87,7 +87,7 @@
super.onCreate(savedInstanceState);
mModel = LauncherAppState.getInstance(this).getModel();
mDragController = new SecondaryDragController(this);
- mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
+ mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
mSecondaryDisplayPredictions = SecondaryDisplayPredictions.newInstance(this);
if (getWindow().getDecorView().isAttachedToWindow()) {
initUi();
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 5eac01e..c8455b8 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -38,12 +38,14 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
/**
* DragLayer for Secondary launcher
@@ -194,15 +196,21 @@
return false;
}
+ List<SystemShortcut> systemShortcuts = new ArrayList<>();
+
+ // Hide redundant pin shortcut for app drawer icons if drag-n-drop is enabled.
+ if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
+ systemShortcuts.add(mPinnedAppsAdapter.getSystemShortcut(item, v));
+ }
+ systemShortcuts.add(APP_INFO.getShortcut(mActivity, item, v));
+
final PopupContainerWithArrow container =
(PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
R.layout.popup_container, mActivity.getDragLayer(), false);
container.populateAndShow((BubbleTextView) v,
popupDataProvider.getShortcutCountForItem(item),
- Collections.emptyList(),
- Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item, v),
- APP_INFO.getShortcut(mActivity, item, v)));
+ Collections.emptyList(), systemShortcuts);
container.requestFocus();
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
index 6057586..c81214e 100644
--- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
+++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
@@ -59,8 +59,8 @@
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FlagTogglerPrefUi;
import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
@@ -392,7 +392,8 @@
onboardingPref.setTitle(title);
onboardingPref.setSummary("Tap to reset");
onboardingPref.setOnPreferenceClickListener(preference -> {
- SharedPreferences.Editor sharedPrefsEdit = Utilities.getPrefs(getContext()).edit();
+ SharedPreferences.Editor sharedPrefsEdit = LauncherPrefs.getPrefs(getContext())
+ .edit();
for (String key : keys) {
sharedPrefsEdit.remove(key);
}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 49d27b7..4cb4348 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -18,6 +18,7 @@
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
+import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
import android.content.Intent;
@@ -45,6 +46,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
@@ -112,7 +114,8 @@
// Display the fragment as the main content.
fm.beginTransaction().replace(R.id.content_frame, f).commit();
}
- Utilities.getPrefs(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
+ LauncherPrefs.getPrefs(getApplicationContext())
+ .registerOnSharedPreferenceChangeListener(this);
}
/**
@@ -207,7 +210,11 @@
PreferenceScreen screen = getPreferenceScreen();
for (int i = screen.getPreferenceCount() - 1; i >= 0; i--) {
Preference preference = screen.getPreference(i);
- if (!initPreference(preference)) {
+ if (initPreference(preference)) {
+ if (IS_STUDIO_BUILD && preference == mDeveloperOptionPref) {
+ preference.setOrder(0);
+ }
+ } else {
screen.removePreference(preference);
}
}
diff --git a/src/com/android/launcher3/shortcuts/ShortcutRequest.java b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
index 07d3292..5291ce4 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutRequest.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
@@ -16,7 +16,7 @@
package com.android.launcher3.shortcuts;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
import android.content.ComponentName;
import android.content.Context;
@@ -46,7 +46,7 @@
| ShortcutQuery.FLAG_MATCH_MANIFEST;
public static final int PINNED = ShortcutQuery.FLAG_MATCH_PINNED;
- private final ShortcutQuery mQuery = GO_DISABLE_SHORTCUTS ? null : new ShortcutQuery();
+ private final ShortcutQuery mQuery = GO_DISABLE_WIDGETS ? null : new ShortcutQuery();
private final Context mContext;
private final UserHandle mUserHandle;
@@ -73,7 +73,7 @@
* @return A list of ShortcutInfo's associated with the given package.
*/
public ShortcutRequest forPackage(String packageName, @Nullable List<String> shortcutIds) {
- if (!GO_DISABLE_SHORTCUTS && packageName != null) {
+ if (!GO_DISABLE_WIDGETS && packageName != null) {
mQuery.setPackage(packageName);
mQuery.setShortcutIds(shortcutIds);
}
@@ -81,7 +81,7 @@
}
public ShortcutRequest withContainer(@Nullable ComponentName activity) {
- if (!GO_DISABLE_SHORTCUTS) {
+ if (!GO_DISABLE_WIDGETS) {
if (activity == null) {
mFailed = true;
} else {
@@ -92,7 +92,7 @@
}
public QueryResult query(int flags) {
- if (GO_DISABLE_SHORTCUTS || mFailed) {
+ if (GO_DISABLE_WIDGETS || mFailed) {
return QueryResult.DEFAULT;
}
mQuery.setQueryFlags(flags);
@@ -108,7 +108,7 @@
public static class QueryResult extends ArrayList<ShortcutInfo> {
- static final QueryResult DEFAULT = new QueryResult(GO_DISABLE_SHORTCUTS);
+ static final QueryResult DEFAULT = new QueryResult(GO_DISABLE_WIDGETS);
private final boolean mWasSuccess;
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index b94ea07..642bdcd 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -36,7 +36,7 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.util.DisplayController;
/**
@@ -104,7 +104,7 @@
mIgnoreAutoRotateSettings = ignoreAutoRotateSettings;
if (!mIgnoreAutoRotateSettings) {
if (mSharedPrefs == null) {
- mSharedPrefs = Utilities.getPrefs(mActivity);
+ mSharedPrefs = LauncherPrefs.getPrefs(mActivity);
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
}
mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java
index 3fbce88..46e5891 100644
--- a/src/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/src/com/android/launcher3/testing/shared/TestProtocol.java
@@ -84,6 +84,10 @@
public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list";
public static final String REQUEST_ENABLE_MANUAL_TASKBAR_STASHING = "enable-taskbar-stashing";
public static final String REQUEST_DISABLE_MANUAL_TASKBAR_STASHING = "disable-taskbar-stashing";
+ public static final String REQUEST_ENABLE_BLOCK_TIMEOUT = "enable-block-timeout";
+ public static final String REQUEST_DISABLE_BLOCK_TIMEOUT = "disable-block-timeout";
+ public static final String REQUEST_ENABLE_TRANSIENT_TASKBAR = "enable-transient-taskbar";
+ public static final String REQUEST_DISABLE_TRANSIENT_TASKBAR = "disable-transient-taskbar";
public static final String REQUEST_UNSTASH_TASKBAR_IF_STASHED = "unstash-taskbar-if-stashed";
public static final String REQUEST_STASHED_TASKBAR_HEIGHT = "stashed-taskbar-height";
public static final String REQUEST_RECREATE_TASKBAR = "recreate-taskbar";
@@ -144,6 +148,7 @@
public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String TASKBAR_IN_APP_STATE = "b/227657604";
public static final String INCORRECT_INFO_UPDATED = "b/239465630";
+ public static final String NPE_TRANSIENT_TASKBAR = "b/257549303";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index af689dc..78e17d8 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -585,7 +585,6 @@
@Override
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
SplitBounds splitInfo, int desiredStagePosition) {
- boolean isLandscape = dp.isLandscape;
float topLeftTaskPercent = splitInfo.appsStackedVertically
? splitInfo.topTaskPercent
: splitInfo.leftTaskPercent;
@@ -593,18 +592,24 @@
? splitInfo.dividerHeightPercent
: splitInfo.dividerWidthPercent;
+ int deviceHeightWithoutTaskbar = dp.availableHeightPx - dp.taskbarSize;
+ float scale = (float) outRect.height() / deviceHeightWithoutTaskbar;
+ float topTaskHeight = dp.availableHeightPx * topLeftTaskPercent;
+ float scaledTopTaskHeight = topTaskHeight * scale;
+ float dividerHeight = dp.availableHeightPx * dividerBarPercent;
+ float scaledDividerHeight = dividerHeight * scale;
+
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
- if (isLandscape) {
- outRect.right = outRect.left + Math.round(outRect.width() * topLeftTaskPercent);
+ if (splitInfo.appsStackedVertically) {
+ outRect.bottom = Math.round(outRect.top + scaledTopTaskHeight);
} else {
- outRect.bottom = outRect.top + Math.round(outRect.height() * topLeftTaskPercent);
+ outRect.right = outRect.left + Math.round(outRect.width() * topLeftTaskPercent);
}
} else {
- if (isLandscape) {
- outRect.left += Math.round(outRect.width()
- * (topLeftTaskPercent + dividerBarPercent));
+ if (splitInfo.appsStackedVertically) {
+ outRect.top += Math.round(scaledTopTaskHeight + scaledDividerHeight);
} else {
- outRect.top += Math.round(outRect.height()
+ outRect.left += Math.round(outRect.width()
* (topLeftTaskPercent + dividerBarPercent));
}
}
@@ -617,7 +622,7 @@
int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
int dividerBar = Math.round(splitBoundsConfig.appsStackedVertically
- ? splitBoundsConfig.dividerHeightPercent * totalThumbnailHeight
+ ? splitBoundsConfig.dividerHeightPercent * dp.availableHeightPx
: splitBoundsConfig.dividerWidthPercent * parentWidth);
int primarySnapshotHeight;
int primarySnapshotWidth;
@@ -641,12 +646,18 @@
}
secondarySnapshot.setTranslationY(spaceAboveSnapshot);
} else {
+ int deviceHeightWithoutTaskbar = dp.availableHeightPx - dp.taskbarSize;
+ float scale = (float) totalThumbnailHeight / deviceHeightWithoutTaskbar;
+ float topTaskHeight = dp.availableHeightPx * taskPercent;
+ float finalDividerHeight = dividerBar * scale;
+ float scaledTopTaskHeight = topTaskHeight * scale;
primarySnapshotWidth = parentWidth;
- primarySnapshotHeight = Math.round(totalThumbnailHeight * taskPercent);
+ primarySnapshotHeight = Math.round(scaledTopTaskHeight);
secondarySnapshotWidth = parentWidth;
- secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar;
- int translationY = primarySnapshotHeight + spaceAboveSnapshot + dividerBar;
+ secondarySnapshotHeight = Math.round(totalThumbnailHeight - primarySnapshotHeight
+ - finalDividerHeight);
+ float translationY = primarySnapshotHeight + spaceAboveSnapshot + finalDividerHeight;
secondarySnapshot.setTranslationY(translationY);
FrameLayout.LayoutParams primaryParams =
diff --git a/src/com/android/launcher3/util/BgObjectWithLooper.java b/src/com/android/launcher3/util/BgObjectWithLooper.java
index 1483c43..adc3c7d 100644
--- a/src/com/android/launcher3/util/BgObjectWithLooper.java
+++ b/src/com/android/launcher3/util/BgObjectWithLooper.java
@@ -15,10 +15,15 @@
*/
package com.android.launcher3.util;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
import android.os.Looper;
import androidx.annotation.WorkerThread;
+import java.util.function.Consumer;
+
/**
* Utility class to define an object which does most of it's processing on a
* dedicated background thread.
@@ -43,4 +48,16 @@
*/
@WorkerThread
protected abstract void onInitialized(Looper looper);
+
+ /**
+ * Helper method to create a content provider
+ */
+ protected static ContentObserver newContentObserver(Handler handler, Consumer<Uri> command) {
+ return new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ command.accept(uri);
+ }
+ };
+ }
}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index f9f7ac0..226f2d9 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -42,6 +42,7 @@
import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.window.CachedDisplayInfo;
@@ -63,6 +64,7 @@
private static final String TAG = "DisplayController";
private static final boolean DEBUG = false;
+ private static boolean sTransientTaskbarStatusForTests;
public static final MainThreadInitializedObject<DisplayController> INSTANCE =
new MainThreadInitializedObject<>(DisplayController::new);
@@ -128,8 +130,18 @@
* Returns whether taskbar is transient.
*/
public static boolean isTransientTaskbar(Context context) {
- return ENABLE_TRANSIENT_TASKBAR.get()
- && getNavigationMode(context) == NavigationMode.NO_BUTTON;
+ return getNavigationMode(context) == NavigationMode.NO_BUTTON
+ && (Utilities.IS_RUNNING_IN_TEST_HARNESS
+ ? sTransientTaskbarStatusForTests
+ : ENABLE_TRANSIENT_TASKBAR.get());
+ }
+
+ /**
+ * Enables transient taskbar status for tests.
+ */
+ @VisibleForTesting
+ public static void enableTransientTaskbarForTests(boolean enable) {
+ sTransientTaskbarStatusForTests = enable;
}
@Override
diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java
index 79cafa0..91cf835 100644
--- a/src/com/android/launcher3/util/ShortcutUtil.java
+++ b/src/com/android/launcher3/util/ShortcutUtil.java
@@ -34,7 +34,7 @@
* Returns true when we should show depp shortcuts in shortcut menu for the item.
*/
public static boolean supportsDeepShortcuts(ItemInfo info) {
- return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_SHORTCUTS;
+ return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_WIDGETS;
}
/**
diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
index 4dfa5cc..0a23506 100644
--- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
+++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
@@ -52,4 +52,15 @@
}
context.registerReceiver(this, filter, flags);
}
+
+ /**
+ * Unregisters the receiver ignoring any errors
+ */
+ public void unregisterReceiverSafely(Context context) {
+ try {
+ context.unregisterReceiver(this);
+ } catch (IllegalArgumentException e) {
+ // It was probably never registered or already unregistered. Ignore.
+ }
+ }
}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index 1728f4d..585bea9 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -30,6 +30,7 @@
import android.util.SparseArray;
import android.util.TypedValue;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.GraphicsUtils;
@@ -73,7 +74,7 @@
* Returns true if workspace icon theming is enabled
*/
public static boolean isThemedIconEnabled(Context context) {
- return Utilities.getPrefs(context).getBoolean(KEY_THEMED_ICONS, false);
+ return LauncherPrefs.getPrefs(context).getBoolean(KEY_THEMED_ICONS, false);
}
public static String getDefaultBodyFont(Context context) {
diff --git a/src/com/android/launcher3/util/TouchController.java b/src/com/android/launcher3/util/TouchController.java
index 9c397c0..fc1d819 100644
--- a/src/com/android/launcher3/util/TouchController.java
+++ b/src/com/android/launcher3/util/TouchController.java
@@ -32,10 +32,5 @@
*/
boolean onControllerInterceptTouchEvent(MotionEvent ev);
- /**
- * Called when one handed mode state changed
- */
- default void onOneHandedModeStateChanged(boolean activated) { }
-
default void dump(String prefix, PrintWriter writer) { }
}
diff --git a/src/com/android/launcher3/views/AppLauncher.java b/src/com/android/launcher3/views/AppLauncher.java
index dc07e45..19e66ab 100644
--- a/src/com/android/launcher3/views/AppLauncher.java
+++ b/src/com/android/launcher3/views/AppLauncher.java
@@ -16,7 +16,7 @@
package com.android.launcher3.views;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_SHORTCUTS;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
@@ -190,7 +190,7 @@
*/
default void startShortcut(String packageName, String id, Rect sourceBounds,
Bundle startActivityOptions, UserHandle user) {
- if (GO_DISABLE_SHORTCUTS) {
+ if (GO_DISABLE_WIDGETS) {
return;
}
try {
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index d301925..622516f 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -15,9 +15,6 @@
*/
package com.android.launcher3.views;
-import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_FLAVOR;
-import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_LAUNCH_SOURCE;
-import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_OFFSET;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS;
@@ -51,6 +48,7 @@
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import java.util.ArrayList;
@@ -62,6 +60,13 @@
public class OptionsPopupView extends ArrowPopup<Launcher>
implements OnClickListener, OnLongClickListener {
+ // An intent extra to indicate the horizontal scroll of the wallpaper.
+ private static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
+ private static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
+ // An intent extra to indicate the launch source by launcher.
+ private static final String EXTRA_WALLPAPER_LAUNCH_SOURCE =
+ "com.android.wallpaper.LAUNCH_SOURCE";
+
private final ArrayMap<View, OptionItem> mItemMap = new ArrayMap<>();
private RectF mTargetRect;
private boolean mShouldAddArrow;
@@ -134,14 +139,13 @@
mTargetRect.roundOut(outPos);
}
- public static OptionsPopupView show(
- Launcher launcher, RectF targetRect, List<OptionItem> items, boolean shouldAddArrow) {
+ public static OptionsPopupView show(AppLauncher launcher, RectF targetRect,
+ List<OptionItem> items, boolean shouldAddArrow) {
return show(launcher, targetRect, items, shouldAddArrow, 0 /* width */);
}
- public static OptionsPopupView show(
- Launcher launcher, RectF targetRect, List<OptionItem> items, boolean shouldAddArrow,
- int width) {
+ public static OptionsPopupView show(AppLauncher launcher, RectF targetRect,
+ List<OptionItem> items, boolean shouldAddArrow, int width) {
OptionsPopupView popup = (OptionsPopupView) launcher.getLayoutInflater()
.inflate(R.layout.longpress_options_menu, launcher.getDragLayer(), false);
popup.mTargetRect = targetRect;
@@ -160,30 +164,20 @@
popup.mItemMap.put(view, item);
}
- popup.addPreDrawForColorExtraction(launcher);
popup.show();
return popup;
}
- @Override
- protected List<View> getChildrenForColorExtraction() {
- int childCount = getChildCount();
- ArrayList<View> children = new ArrayList<>(childCount);
- for (int i = 0; i < childCount; ++i) {
- children.add(getChildAt(i));
- }
- return children;
- }
-
/**
* Returns the list of supported actions
*/
public static ArrayList<OptionItem> getOptions(Launcher launcher) {
ArrayList<OptionItem> options = new ArrayList<>();
- int resString = Utilities.existsStyleWallpapers(launcher) ?
- R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
- int resDrawable = Utilities.existsStyleWallpapers(launcher) ?
- R.drawable.ic_palette : R.drawable.ic_wallpaper;
+ boolean styleWallpaperExists = styleWallpapersExists(launcher);
+ int resString = styleWallpaperExists
+ ? R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
+ int resDrawable = styleWallpaperExists
+ ? R.drawable.ic_palette : R.drawable.ic_wallpaper;
options.add(new OptionItem(launcher,
resString,
resDrawable,
@@ -251,7 +245,7 @@
.putExtra(EXTRA_WALLPAPER_OFFSET,
launcher.getWorkspace().getWallpaperOffsetForCenterPage())
.putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher");
- if (!Utilities.existsStyleWallpapers(launcher)) {
+ if (!styleWallpapersExists(launcher)) {
intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only");
} else {
intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
@@ -299,4 +293,9 @@
this.clickListener = clickListener;
}
}
+
+ private static boolean styleWallpapersExists(Context context) {
+ return context.getPackageManager().resolveActivity(
+ PackageManagerHelper.getStyleWallpapersIntent(context), 0) != null;
+ }
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
index fff8fbb..9c21ea2 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
@@ -16,301 +16,87 @@
package com.android.launcher3.widget;
-import static android.app.Activity.RESULT_CANCELED;
+import static com.android.launcher3.widget.LauncherWidgetHolder.APPWIDGET_HOST_ID;
-import android.app.PendingIntent;
import android.appwidget.AppWidgetHost;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.RemoteViews;
-import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.WidgetsModel;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.testing.TestLogging;
-import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
import java.util.function.IntConsumer;
-
/**
* Specific {@link AppWidgetHost} that creates our {@link LauncherAppWidgetHostView}
* which correctly captures all long-press events. This ensures that users can
* always pick up and move widgets.
*/
-public class LauncherAppWidgetHost extends AppWidgetHost {
+class LauncherAppWidgetHost extends AppWidgetHost {
+ @NonNull
+ private final ArrayList<LauncherWidgetHolder.ProviderChangedListener>
+ mProviderChangeListeners = new ArrayList<>();
- private static final int FLAG_LISTENING = 1;
- private static final int FLAG_STATE_IS_NORMAL = 1 << 1;
- private static final int FLAG_ACTIVITY_STARTED = 1 << 2;
- private static final int FLAG_ACTIVITY_RESUMED = 1 << 3;
- private static final int FLAGS_SHOULD_LISTEN =
- FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED | FLAG_ACTIVITY_RESUMED;
- // TODO(b/191735836): Replace with ActivityOptions.KEY_SPLASH_SCREEN_STYLE when un-hidden
- private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle";
- // TODO(b/191735836): Replace with SplashScreen.SPLASH_SCREEN_STYLE_EMPTY when un-hidden
- private static final int SPLASH_SCREEN_STYLE_EMPTY = 0;
-
- public static final int APPWIDGET_HOST_ID = 1024;
-
- private final ArrayList<ProviderChangedListener> mProviderChangeListeners = new ArrayList<>();
- private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
- private final SparseArray<PendingAppWidgetHostView> mPendingViews = new SparseArray<>();
- private final SparseArray<LauncherAppWidgetHostView> mDeferredViews = new SparseArray<>();
- private final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();
-
+ @NonNull
private final Context mContext;
- private int mFlags = FLAG_STATE_IS_NORMAL;
- private IntConsumer mAppWidgetRemovedCallback = null;
+ @Nullable
+ private final IntConsumer mAppWidgetRemovedCallback;
- /**
- * This serves for the purpose of getting rid of the hidden API calling of InteractionHandler
- */
- public interface LauncherWidgetInteractionHandler {
- /**
- * Invoked when the user performs an interaction on the View.
- *
- * @param view the View with which the user interacted
- * @param pendingIntent the base PendingIntent associated with the view
- * @param response the response to the interaction, which knows how to fill in the
- * attached PendingIntent
- */
- boolean onInteraction(
- View view,
- PendingIntent pendingIntent,
- RemoteViews.RemoteResponse response);
- }
+ @NonNull
+ private final LauncherWidgetHolder mHolder;
- public LauncherAppWidgetHost(Context context) {
- this(context, null);
- }
-
- public LauncherAppWidgetHost(Context context,
- IntConsumer appWidgetRemovedCallback) {
+ public LauncherAppWidgetHost(@NonNull Context context,
+ @Nullable IntConsumer appWidgetRemovedCallback, @NonNull LauncherWidgetHolder holder) {
super(context, APPWIDGET_HOST_ID);
mContext = context;
mAppWidgetRemovedCallback = appWidgetRemovedCallback;
- }
-
- @Override
- protected LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
- AppWidgetProviderInfo appWidget) {
- final LauncherAppWidgetHostView view;
- if (mPendingViews.get(appWidgetId) != null) {
- view = mPendingViews.get(appWidgetId);
- mPendingViews.remove(appWidgetId);
- } else if (mDeferredViews.get(appWidgetId) != null) {
- // In case the widget view is deferred, we will simply return the deferred view as
- // opposed to instantiate a new instance of LauncherAppWidgetHostView since launcher
- // already added the former to the workspace.
- view = mDeferredViews.get(appWidgetId);
- } else {
- view = new LauncherAppWidgetHostView(context);
- }
- mViews.put(appWidgetId, view);
- return view;
- }
-
- @Override
- public void startListening() {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- return;
- }
- mFlags |= FLAG_LISTENING;
- try {
- super.startListening();
- } catch (Exception e) {
- if (!Utilities.isBinderSizeError(e)) {
- throw new RuntimeException(e);
- }
- // We're willing to let this slide. The exception is being caused by the list of
- // RemoteViews which is being passed back. The startListening relationship will
- // have been established by this point, and we will end up populating the
- // widgets upon bind anyway. See issue 14255011 for more context.
- }
-
- // We go in reverse order and inflate any deferred or cached widget
- for (int i = mViews.size() - 1; i >= 0; i--) {
- LauncherAppWidgetHostView view = mViews.valueAt(i);
- if (view instanceof DeferredAppWidgetHostView) {
- view.reInflate();
- }
- if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
- final int appWidgetId = mViews.keyAt(i);
- if (view == mDeferredViews.get(appWidgetId)) {
- // If the widget view was deferred, we'll need to call super.createView here
- // to make the binder call to system process to fetch cumulative updates to this
- // widget, as well as setting up this view for future updates.
- super.createView(view.mLauncher, appWidgetId, view.getAppWidgetInfo());
- // At this point #onCreateView should have been called, which in turn returned
- // the deferred view. There's no reason to keep the reference anymore, so we
- // removed it here.
- mDeferredViews.remove(appWidgetId);
- }
- }
- }
- }
-
- @Override
- public void stopListening() {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- return;
- }
- mFlags &= ~FLAG_LISTENING;
- super.stopListening();
- }
-
- public boolean isListening() {
- return (mFlags & FLAG_LISTENING) != 0;
+ mHolder = holder;
}
/**
- * Sets or unsets a flag the can change whether the widget host should be in the listening
- * state.
+ * Add a listener that is triggered when the providers of the widgets are changed
+ * @param listener The listener that notifies when the providers changed
*/
- private void setShouldListenFlag(int flag, boolean on) {
- if (on) {
- mFlags |= flag;
- } else {
- mFlags &= ~flag;
- }
-
- final boolean listening = isListening();
- if (!listening && (mFlags & FLAGS_SHOULD_LISTEN) == FLAGS_SHOULD_LISTEN) {
- // Postpone starting listening until all flags are on.
- startListening();
- } else if (listening && (mFlags & FLAG_ACTIVITY_STARTED) == 0) {
- // Postpone stopping listening until the activity is stopped.
- stopListening();
- }
+ public void addProviderChangeListener(
+ @NonNull LauncherWidgetHolder.ProviderChangedListener listener) {
+ mProviderChangeListeners.add(listener);
}
/**
- * Registers an "entering/leaving Normal state" event.
+ * Remove the specified listener from the host
+ * @param listener The listener that is to be removed from the host
*/
- public void setStateIsNormal(boolean isNormal) {
- setShouldListenFlag(FLAG_STATE_IS_NORMAL, isNormal);
- }
-
- /**
- * Registers an "activity started/stopped" event.
- */
- public void setActivityStarted(boolean isStarted) {
- setShouldListenFlag(FLAG_ACTIVITY_STARTED, isStarted);
- }
-
- /**
- * Registers an "activity paused/resumed" event.
- */
- public void setActivityResumed(boolean isResumed) {
- setShouldListenFlag(FLAG_ACTIVITY_RESUMED, isResumed);
+ public void removeProviderChangeListener(
+ LauncherWidgetHolder.ProviderChangedListener listener) {
+ mProviderChangeListeners.remove(listener);
}
@Override
- public int allocateAppWidgetId() {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- return AppWidgetManager.INVALID_APPWIDGET_ID;
- }
-
- return super.allocateAppWidgetId();
- }
-
- public void addProviderChangeListener(ProviderChangedListener callback) {
- mProviderChangeListeners.add(callback);
- }
-
- public void removeProviderChangeListener(ProviderChangedListener callback) {
- mProviderChangeListeners.remove(callback);
- }
-
protected void onProvidersChanged() {
if (!mProviderChangeListeners.isEmpty()) {
- for (ProviderChangedListener callback : new ArrayList<>(mProviderChangeListeners)) {
+ for (LauncherWidgetHolder.ProviderChangedListener callback :
+ new ArrayList<>(mProviderChangeListeners)) {
callback.notifyWidgetProvidersChanged();
}
}
}
- public void addPendingView(int appWidgetId, PendingAppWidgetHostView view) {
- mPendingViews.put(appWidgetId, view);
- }
-
- public AppWidgetHostView createView(Context context, int appWidgetId,
- LauncherAppWidgetProviderInfo appWidget) {
- if (appWidget.isCustomWidget()) {
- LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
- lahv.setAppWidget(0, appWidget);
- CustomWidgetManager.INSTANCE.get(context).onViewCreated(lahv);
- return lahv;
- } else if ((mFlags & FLAG_LISTENING) == 0) {
- // Since the launcher hasn't started listening to widget updates, we can't simply call
- // super.createView here because the later will make a binder call to retrieve
- // RemoteViews from system process.
- // TODO: have launcher always listens to widget updates in background so that this
- // check can be removed altogether.
- if (FeatureFlags.ENABLE_CACHED_WIDGET.get()
- && mCachedRemoteViews.get(appWidgetId) != null) {
- // We've found RemoteViews from cache for this widget, so we will instantiate a
- // widget host view and populate it with the cached RemoteViews.
- final LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
- view.setAppWidget(appWidgetId, appWidget);
- view.updateAppWidget(mCachedRemoteViews.get(appWidgetId));
- mDeferredViews.put(appWidgetId, view);
- mViews.put(appWidgetId, view);
- return view;
- } else {
- // When cache misses, a placeholder for the widget will be returned instead.
- DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
- view.setAppWidget(appWidgetId, appWidget);
- mViews.put(appWidgetId, view);
- return view;
- }
- } else {
- try {
- return super.createView(context, appWidgetId, appWidget);
- } catch (Exception e) {
- if (!Utilities.isBinderSizeError(e)) {
- throw new RuntimeException(e);
- }
-
- // If the exception was thrown while fetching the remote views, let the view stay.
- // This will ensure that if the widget posts a valid update later, the view
- // will update.
- LauncherAppWidgetHostView view = mViews.get(appWidgetId);
- if (view == null) {
- view = onCreateView(mContext, appWidgetId, appWidget);
- }
- view.setAppWidget(appWidgetId, appWidget);
- view.switchToErrorView();
- return view;
- }
- }
+ @Override
+ @NonNull
+ public LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
+ AppWidgetProviderInfo appWidget) {
+ return mHolder.onCreateView(context, appWidgetId, appWidget);
}
/**
* Called when the AppWidget provider for a AppWidget has been upgraded to a new apk.
*/
@Override
- protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
+ protected void onProviderChanged(int appWidgetId, @NonNull AppWidgetProviderInfo appWidget) {
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo(
mContext, appWidget);
super.onProviderChanged(appWidgetId, info);
@@ -324,6 +110,7 @@
*
* @param appWidgetId TODO: make this override when SDK is updated
*/
+ @Override
public void onAppWidgetRemoved(int appWidgetId) {
if (mAppWidgetRemovedCallback == null) {
return;
@@ -331,92 +118,12 @@
mAppWidgetRemovedCallback.accept(appWidgetId);
}
- @Override
- public void deleteAppWidgetId(int appWidgetId) {
- super.deleteAppWidgetId(appWidgetId);
- mViews.remove(appWidgetId);
- }
-
+ /**
+ * The same as super.clearViews(), except with the scope exposed
+ */
@Override
public void clearViews() {
super.clearViews();
- if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
- // First, we clear any previously cached content from existing widgets
- mCachedRemoteViews.clear();
- mDeferredViews.clear();
- // Then we proceed to cache the content from the widgets
- for (int i = 0; i < mViews.size(); i++) {
- final int appWidgetId = mViews.keyAt(i);
- final LauncherAppWidgetHostView view = mViews.get(appWidgetId);
- mCachedRemoteViews.put(appWidgetId, view.mLastRemoteViews);
- }
- }
- mViews.clear();
}
- public void startBindFlow(BaseActivity activity,
- int appWidgetId, AppWidgetProviderInfo info, int requestCode) {
-
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- sendActionCancelled(activity, requestCode);
- return;
- }
-
- Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND)
- .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
- .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider)
- .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, info.getProfile());
- // TODO: we need to make sure that this accounts for the options bundle.
- // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
- activity.startActivityForResult(intent, requestCode);
- }
-
- /**
- * Launches an app widget's configuration activity.
- * @param activity The activity from which to launch the configuration activity
- * @param widgetId The id of the bound app widget to be configured
- * @param requestCode An optional request code to be returned with the result
- */
- public void startConfigActivity(BaseDraggingActivity activity, int widgetId, int requestCode) {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- sendActionCancelled(activity, requestCode);
- return;
- }
-
- try {
- TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: startConfigActivity");
- startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode,
- getConfigurationActivityOptions(activity, widgetId));
- } catch (ActivityNotFoundException | SecurityException e) {
- Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- sendActionCancelled(activity, requestCode);
- }
- }
-
- /**
- * Returns an {@link android.app.ActivityOptions} bundle from the {code activity} for launching
- * the configuration of the {@code widgetId} app widget, or null of options cannot be produced.
- */
- @Nullable
- private Bundle getConfigurationActivityOptions(BaseDraggingActivity activity, int widgetId) {
- LauncherAppWidgetHostView view = mViews.get(widgetId);
- if (view == null) return null;
- Object tag = view.getTag();
- if (!(tag instanceof ItemInfo)) return null;
- Bundle bundle = activity.getActivityLaunchOptions(view, (ItemInfo) tag).toBundle();
- bundle.putInt(KEY_SPLASH_SCREEN_STYLE, SPLASH_SCREEN_STYLE_EMPTY);
- return bundle;
- }
-
- private void sendActionCancelled(final BaseActivity activity, final int requestCode) {
- new Handler().post(() -> activity.onActivityResult(requestCode, RESULT_CANCELED, null));
- }
-
- /**
- * Listener for getting notifications on provider changes.
- */
- public interface ProviderChangedListener {
-
- void notifyWidgetProvidersChanged();
- }
}
diff --git a/src/com/android/launcher3/widget/LauncherWidgetHolder.java b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
new file mode 100644
index 0000000..5497729
--- /dev/null
+++ b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
@@ -0,0 +1,508 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget;
+
+import static android.app.Activity.RESULT_CANCELED;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
+
+import java.util.function.IntConsumer;
+
+/**
+ * A wrapper for LauncherAppWidgetHost. This class is created so the AppWidgetHost could run in
+ * background.
+ */
+public class LauncherWidgetHolder {
+ public static final int APPWIDGET_HOST_ID = 1024;
+
+ private static final int FLAG_LISTENING = 1;
+ private static final int FLAG_STATE_IS_NORMAL = 1 << 1;
+ private static final int FLAG_ACTIVITY_STARTED = 1 << 2;
+ private static final int FLAG_ACTIVITY_RESUMED = 1 << 3;
+ private static final int FLAGS_SHOULD_LISTEN =
+ FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED | FLAG_ACTIVITY_RESUMED;
+
+ @NonNull
+ private final Context mContext;
+
+ @NonNull
+ private final AppWidgetHost mWidgetHost;
+
+ @NonNull
+ private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
+ @NonNull
+ private final SparseArray<PendingAppWidgetHostView> mPendingViews = new SparseArray<>();
+ @NonNull
+ private final SparseArray<LauncherAppWidgetHostView> mDeferredViews = new SparseArray<>();
+ @NonNull
+ private final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();
+
+ private int mFlags = FLAG_STATE_IS_NORMAL;
+
+ // TODO(b/191735836): Replace with ActivityOptions.KEY_SPLASH_SCREEN_STYLE when un-hidden
+ private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle";
+ // TODO(b/191735836): Replace with SplashScreen.SPLASH_SCREEN_STYLE_EMPTY when un-hidden
+ private static final int SPLASH_SCREEN_STYLE_EMPTY = 0;
+
+ public LauncherWidgetHolder(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public LauncherWidgetHolder(@NonNull Context context,
+ @Nullable IntConsumer appWidgetRemovedCallback) {
+ mContext = context;
+ mWidgetHost = createHost(context, appWidgetRemovedCallback);
+ }
+
+ protected AppWidgetHost createHost(
+ Context context, @Nullable IntConsumer appWidgetRemovedCallback) {
+ return new LauncherAppWidgetHost(context, appWidgetRemovedCallback, this);
+ }
+
+ /**
+ * Starts listening to the widget updates from the server side
+ */
+ public void startListening() {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ return;
+ }
+ setListeningFlag(true);
+ try {
+ mWidgetHost.startListening();
+ } catch (Exception e) {
+ if (!Utilities.isBinderSizeError(e)) {
+ throw new RuntimeException(e);
+ }
+ // We're willing to let this slide. The exception is being caused by the list of
+ // RemoteViews which is being passed back. The startListening relationship will
+ // have been established by this point, and we will end up populating the
+ // widgets upon bind anyway. See issue 14255011 for more context.
+ }
+
+ // We go in reverse order and inflate any deferred or cached widget
+ for (int i = mViews.size() - 1; i >= 0; i--) {
+ LauncherAppWidgetHostView view = mViews.valueAt(i);
+ if (view instanceof DeferredAppWidgetHostView) {
+ view.reInflate();
+ }
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ final int appWidgetId = mViews.keyAt(i);
+ if (view == mDeferredViews.get(appWidgetId)) {
+ // If the widget view was deferred, we'll need to call super.createView here
+ // to make the binder call to system process to fetch cumulative updates to this
+ // widget, as well as setting up this view for future updates.
+ mWidgetHost.createView(view.mLauncher, appWidgetId,
+ view.getAppWidgetInfo());
+ // At this point #onCreateView should have been called, which in turn returned
+ // the deferred view. There's no reason to keep the reference anymore, so we
+ // removed it here.
+ mDeferredViews.remove(appWidgetId);
+ }
+ }
+ }
+ }
+
+ /**
+ * Registers an "activity started/stopped" event.
+ */
+ public void setActivityStarted(boolean isStarted) {
+ setShouldListenFlag(FLAG_ACTIVITY_STARTED, isStarted);
+ }
+
+ /**
+ * Registers an "activity paused/resumed" event.
+ */
+ public void setActivityResumed(boolean isResumed) {
+ setShouldListenFlag(FLAG_ACTIVITY_RESUMED, isResumed);
+ }
+
+ /**
+ * Set the NORMAL state of the widget host
+ * @param isNormal True if setting the host to be in normal state, false otherwise
+ */
+ public void setStateIsNormal(boolean isNormal) {
+ setShouldListenFlag(FLAG_STATE_IS_NORMAL, isNormal);
+ }
+
+ /**
+ * Delete the specified app widget from the host
+ * @param appWidgetId The ID of the app widget to be deleted
+ */
+ public void deleteAppWidgetId(int appWidgetId) {
+ mWidgetHost.deleteAppWidgetId(appWidgetId);
+ mViews.remove(appWidgetId);
+ }
+
+ /**
+ * Add the pending view to the host for complete configuration in further steps
+ * @param appWidgetId The ID of the specified app widget
+ * @param view The {@link PendingAppWidgetHostView} of the app widget
+ */
+ public void addPendingView(int appWidgetId, @NonNull PendingAppWidgetHostView view) {
+ mPendingViews.put(appWidgetId, view);
+ }
+
+ /**
+ * @param appWidgetId The app widget id of the specified widget
+ * @return The {@link PendingAppWidgetHostView} of the widget if it exists, null otherwise
+ */
+ @Nullable
+ protected PendingAppWidgetHostView getPendingView(int appWidgetId) {
+ return mPendingViews.get(appWidgetId);
+ }
+
+ protected void removePendingView(int appWidgetId) {
+ mPendingViews.remove(appWidgetId);
+ }
+
+ /**
+ * Called when the launcher is destroyed
+ */
+ public void destroy() {
+ // No-op
+ }
+
+ /**
+ * @return The allocated app widget id if allocation is successful, returns -1 otherwise
+ */
+ public int allocateAppWidgetId() {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ return AppWidgetManager.INVALID_APPWIDGET_ID;
+ }
+
+ return mWidgetHost.allocateAppWidgetId();
+ }
+
+ /**
+ * Add a listener that is triggered when the providers of the widgets are changed
+ * @param listener The listener that notifies when the providers changed
+ */
+ public void addProviderChangeListener(@NonNull ProviderChangedListener listener) {
+ LauncherAppWidgetHost tempHost = (LauncherAppWidgetHost) mWidgetHost;
+ tempHost.addProviderChangeListener(listener);
+ }
+
+ /**
+ * Remove the specified listener from the host
+ * @param listener The listener that is to be removed from the host
+ */
+ public void removeProviderChangeListener(ProviderChangedListener listener) {
+ LauncherAppWidgetHost tempHost = (LauncherAppWidgetHost) mWidgetHost;
+ tempHost.removeProviderChangeListener(listener);
+ }
+
+ /**
+ * Starts the configuration activity for the widget
+ * @param activity The activity in which to start the configuration page
+ * @param widgetId The ID of the widget
+ * @param requestCode The request code
+ */
+ public void startConfigActivity(@NonNull BaseDraggingActivity activity, int widgetId,
+ int requestCode) {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ sendActionCancelled(activity, requestCode);
+ return;
+ }
+
+ try {
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: startConfigActivity");
+ mWidgetHost.startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode,
+ getConfigurationActivityOptions(activity, widgetId));
+ } catch (ActivityNotFoundException | SecurityException e) {
+ Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+ sendActionCancelled(activity, requestCode);
+ }
+ }
+
+ private void sendActionCancelled(final BaseActivity activity, final int requestCode) {
+ MAIN_EXECUTOR.execute(
+ () -> activity.onActivityResult(requestCode, RESULT_CANCELED, null));
+ }
+
+ /**
+ * Returns an {@link android.app.ActivityOptions} bundle from the {code activity} for launching
+ * the configuration of the {@code widgetId} app widget, or null of options cannot be produced.
+ */
+ @Nullable
+ protected Bundle getConfigurationActivityOptions(@NonNull BaseDraggingActivity activity,
+ int widgetId) {
+ LauncherAppWidgetHostView view = mViews.get(widgetId);
+ if (view == null) return null;
+ Object tag = view.getTag();
+ if (!(tag instanceof ItemInfo)) return null;
+ Bundle bundle = activity.getActivityLaunchOptions(view, (ItemInfo) tag).toBundle();
+ bundle.putInt(KEY_SPLASH_SCREEN_STYLE, SPLASH_SCREEN_STYLE_EMPTY);
+ return bundle;
+ }
+
+ /**
+ * Starts the binding flow for the widget
+ * @param activity The activity for which to bind the widget
+ * @param appWidgetId The ID of the widget
+ * @param info The {@link AppWidgetProviderInfo} of the widget
+ * @param requestCode The request code
+ */
+ public void startBindFlow(@NonNull BaseActivity activity,
+ int appWidgetId, @NonNull AppWidgetProviderInfo info, int requestCode) {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ sendActionCancelled(activity, requestCode);
+ return;
+ }
+
+ Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND)
+ .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider)
+ .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, info.getProfile());
+ // TODO: we need to make sure that this accounts for the options bundle.
+ // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+ activity.startActivityForResult(intent, requestCode);
+ }
+
+ /**
+ * Stop the host from listening to the widget updates
+ */
+ public void stopListening() {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ return;
+ }
+
+ mWidgetHost.stopListening();
+ setListeningFlag(false);
+ }
+
+ protected void setListeningFlag(final boolean isListening) {
+ if (isListening) {
+ mFlags |= FLAG_LISTENING;
+ return;
+ }
+ mFlags &= ~FLAG_LISTENING;
+ }
+
+ /**
+ * Set the interaction handler for the widget host
+ * @param handler The interaction handler
+ */
+ public void setInteractionHandler(
+ @Nullable LauncherWidgetInteractionHandler handler) {
+ ApiWrapper.setHostInteractionHandler(mWidgetHost, handler);
+ }
+
+ /**
+ * Delete the host
+ */
+ public void deleteHost() {
+ mWidgetHost.deleteHost();
+ }
+
+ /**
+ * @return The app widget ids
+ */
+ @NonNull
+ public int[] getAppWidgetIds() {
+ return mWidgetHost.getAppWidgetIds();
+ }
+
+ /**
+ * Create a view for the specified app widget
+ * @param context The activity context for which the view is created
+ * @param appWidgetId The ID of the widget
+ * @param appWidget The {@link LauncherAppWidgetProviderInfo} of the widget
+ * @return A view for the widget
+ */
+ @NonNull
+ public AppWidgetHostView createView(@NonNull Context context, int appWidgetId,
+ @NonNull LauncherAppWidgetProviderInfo appWidget) {
+ if (appWidget.isCustomWidget()) {
+ LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
+ lahv.setAppWidget(0, appWidget);
+ CustomWidgetManager.INSTANCE.get(context).onViewCreated(lahv);
+ return lahv;
+ } else if ((mFlags & FLAG_LISTENING) == 0) {
+ // Since the launcher hasn't started listening to widget updates, we can't simply call
+ // super.createView here because the later will make a binder call to retrieve
+ // RemoteViews from system process.
+ // TODO: have launcher always listens to widget updates in background so that this
+ // check can be removed altogether.
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()
+ && mCachedRemoteViews.get(appWidgetId) != null) {
+ // We've found RemoteViews from cache for this widget, so we will instantiate a
+ // widget host view and populate it with the cached RemoteViews.
+ final LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
+ view.setAppWidget(appWidgetId, appWidget);
+ view.updateAppWidget(mCachedRemoteViews.get(appWidgetId));
+ mDeferredViews.put(appWidgetId, view);
+ mViews.put(appWidgetId, view);
+ return view;
+ } else {
+ // When cache misses, a placeholder for the widget will be returned instead.
+ DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
+ view.setAppWidget(appWidgetId, appWidget);
+ mViews.put(appWidgetId, view);
+ return view;
+ }
+ } else {
+ try {
+ return mWidgetHost.createView(context, appWidgetId, appWidget);
+ } catch (Exception e) {
+ if (!Utilities.isBinderSizeError(e)) {
+ throw new RuntimeException(e);
+ }
+
+ // If the exception was thrown while fetching the remote views, let the view stay.
+ // This will ensure that if the widget posts a valid update later, the view
+ // will update.
+ LauncherAppWidgetHostView view = mViews.get(appWidgetId);
+ if (view == null) {
+ view = onCreateView(mContext, appWidgetId, appWidget);
+ }
+ view.setAppWidget(appWidgetId, appWidget);
+ view.switchToErrorView();
+ return view;
+ }
+ }
+ }
+
+ /**
+ * Listener for getting notifications on provider changes.
+ */
+ public interface ProviderChangedListener {
+ /**
+ * Notify the listener that the providers have changed
+ */
+ void notifyWidgetProvidersChanged();
+ }
+
+ /**
+ * Called to return a proper view when creating a view
+ * @param context The context for which the widget view is created
+ * @param appWidgetId The ID of the added widget
+ * @param appWidget The provider info of the added widget
+ * @return A view for the specified app widget
+ */
+ @NonNull
+ public LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
+ AppWidgetProviderInfo appWidget) {
+ final LauncherAppWidgetHostView view;
+ if (getPendingView(appWidgetId) != null) {
+ view = getPendingView(appWidgetId);
+ removePendingView(appWidgetId);
+ } else if (mDeferredViews.get(appWidgetId) != null) {
+ // In case the widget view is deferred, we will simply return the deferred view as
+ // opposed to instantiate a new instance of LauncherAppWidgetHostView since launcher
+ // already added the former to the workspace.
+ view = mDeferredViews.get(appWidgetId);
+ } else {
+ view = new LauncherAppWidgetHostView(context);
+ }
+ mViews.put(appWidgetId, view);
+ return view;
+ }
+
+ /**
+ * Clears all the views from the host
+ */
+ public void clearViews() {
+ LauncherAppWidgetHost tempHost = (LauncherAppWidgetHost) mWidgetHost;
+ tempHost.clearViews();
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ // First, we clear any previously cached content from existing widgets
+ mCachedRemoteViews.clear();
+ mDeferredViews.clear();
+ // Then we proceed to cache the content from the widgets
+ for (int i = 0; i < mViews.size(); i++) {
+ final int appWidgetId = mViews.keyAt(i);
+ final LauncherAppWidgetHostView view = mViews.get(appWidgetId);
+ mCachedRemoteViews.put(appWidgetId, view.mLastRemoteViews);
+ }
+ }
+ mViews.clear();
+ }
+
+ /**
+ * @return True if the host is listening to the updates, false otherwise
+ */
+ public boolean isListening() {
+ return (mFlags & FLAG_LISTENING) != 0;
+ }
+
+ /**
+ * Sets or unsets a flag the can change whether the widget host should be in the listening
+ * state.
+ */
+ private void setShouldListenFlag(int flag, boolean on) {
+ if (on) {
+ mFlags |= flag;
+ } else {
+ mFlags &= ~flag;
+ }
+
+ final boolean listening = isListening();
+ if (!listening && (mFlags & FLAGS_SHOULD_LISTEN) == FLAGS_SHOULD_LISTEN) {
+ // Postpone starting listening until all flags are on.
+ startListening();
+ } else if (listening && (mFlags & FLAG_ACTIVITY_STARTED) == 0) {
+ // Postpone stopping listening until the activity is stopped.
+ stopListening();
+ }
+ }
+
+ /**
+ * Set as a substitution for the hidden interaction handler in RemoteViews
+ */
+ public interface LauncherWidgetInteractionHandler {
+ /**
+ * Invoked when the user performs an interaction on the View.
+ *
+ * @param view the View with which the user interacted
+ * @param pendingIntent the base PendingIntent associated with the view
+ * @param response the response to the interaction, which knows how to fill in the
+ * attached PendingIntent
+ */
+ boolean onInteraction(
+ View view,
+ PendingIntent pendingIntent,
+ RemoteViews.RemoteResponse response);
+ }
+}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 21b2647..72ec629 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -65,7 +65,7 @@
import com.android.launcher3.views.StickyHeaderLayout;
import com.android.launcher3.views.WidgetsEduView;
import com.android.launcher3.widget.BaseWidgetSheet;
-import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
+import com.android.launcher3.widget.LauncherWidgetHolder.ProviderChangedListener;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.picker.search.SearchModeListener;
import com.android.launcher3.widget.picker.search.WidgetsSearchBar;
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 13ad7a4..702f343 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -62,8 +62,6 @@
// True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = false;
- // True is the shortcut support is disabled.
- public static final boolean GO_DISABLE_SHORTCUTS = false;
public static final boolean GO_DISABLE_NOTIFICATION_DOTS = false;
private static final String TAG = "WidgetsModel";
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
index ea0f5a3..02f4ece 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -24,7 +24,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.Utilities;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherWidgetHolder;
/**
* A wrapper for the hidden API calls
@@ -43,7 +43,7 @@
* @param handler InteractionHandler for the views in the host
*/
public static void setHostInteractionHandler(@NonNull AppWidgetHost host,
- @Nullable LauncherAppWidgetHost.LauncherWidgetInteractionHandler handler) {
+ @Nullable LauncherWidgetHolder.LauncherWidgetInteractionHandler handler) {
// No-op
}
}
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index 2c1cbdf..4e166ce 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -20,12 +20,11 @@
import android.graphics.Rect
import android.util.SparseArray
import androidx.test.core.app.ApplicationProvider
-import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER;
+import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER
import com.android.launcher3.util.DisplayController.Info
import com.android.launcher3.util.WindowBounds
import org.junit.Before
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.mock
import java.io.PrintWriter
import java.io.StringWriter
@@ -41,9 +40,6 @@
protected var transposeLayoutWithOrientation: Boolean = false
protected var useTwoPanels: Boolean = false
protected var isGestureMode: Boolean = true
- protected var devicePaddingsMock: DevicePaddings = mock(DevicePaddings::class.java)
- protected var staticdevicePaddingsMock: DevicePaddings.DevicePadding =
- mock(DevicePaddings.DevicePadding::class.java)
@Before
fun setUp() {
@@ -82,11 +78,6 @@
whenever(info.isTablet(any())).thenReturn(false)
whenever(info.getDensityDpi()).thenReturn(420)
whenever(info.smallestSizeDp(any())).thenReturn(411f)
- whenever(devicePaddingsMock.getDevicePadding(anyInt())).thenReturn(staticdevicePaddingsMock)
- whenever(staticdevicePaddingsMock.getWorkspaceTopPadding(anyInt())).thenReturn(95)
- whenever(staticdevicePaddingsMock.getWorkspaceBottomPadding(anyInt())).thenReturn(116)
- whenever(staticdevicePaddingsMock.maxEmptySpacePx)
- .thenReturn(if (isVerticalBar) if (isGestureMode) 131 else 184 else 315)
this.isGestureMode = isGestureMode
transposeLayoutWithOrientation = true
@@ -116,10 +107,7 @@
numFolderRows = 3
numFolderColumns = 3
- folderBorderSpaces = PointF(16f, 16f)
- folderTopPadding = 24f
- folderCellSize = PointF(80f, 94f)
-
+ folderStyle = R.style.FolderDefaultStyle
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_4_5
@@ -154,7 +142,7 @@
inlineQsb = BooleanArray(4) { false }
- devicePaddings = devicePaddingsMock
+ devicePaddingId = R.xml.paddings_handhelds
}
}
@@ -171,13 +159,6 @@
whenever(info.isTablet(any())).thenReturn(true)
whenever(info.getDensityDpi()).thenReturn(320)
whenever(info.smallestSizeDp(any())).thenReturn(800f)
- whenever(devicePaddingsMock.getDevicePadding(anyInt())).thenReturn(staticdevicePaddingsMock)
- whenever(staticdevicePaddingsMock.getWorkspaceTopPadding(anyInt()))
- .thenReturn(if (isLandscape) 32 else 159)
- whenever(staticdevicePaddingsMock.getWorkspaceBottomPadding(anyInt()))
- .thenReturn(if (isLandscape) 72 else 203)
- whenever(staticdevicePaddingsMock.maxEmptySpacePx).thenReturn(if (isLandscape) 200 else 19998)
-
this.isGestureMode = isGestureMode
useTwoPanels = false
@@ -207,9 +188,7 @@
numFolderRows = 3
numFolderColumns = 3
- folderBorderSpaces = PointF(16f, 16f)
- folderTopPadding = 24f
- folderCellSize = PointF(120f, 104f)
+ folderStyle = R.style.FolderDefaultStyle
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
@@ -241,7 +220,7 @@
numAllAppsColumns = 6
isScalable = true
- devicePaddingId = 2132148242 // "@xml/paddings_6x5"
+ devicePaddingId = R.xml.paddings_6x5
inlineQsb = booleanArrayOf(
false,
@@ -250,7 +229,7 @@
false
)
- devicePaddings = devicePaddingsMock
+ devicePaddingId = R.xml.paddings_handhelds
}
}
@@ -267,15 +246,6 @@
whenever(info.isTablet(any())).thenReturn(true)
whenever(info.getDensityDpi()).thenReturn(420)
whenever(info.smallestSizeDp(any())).thenReturn(700f)
- whenever(devicePaddingsMock.getDevicePadding(anyInt())).thenReturn(staticdevicePaddingsMock)
-
- val topPadding = if (isLandscape) 18 else 89
- val bottomPadding = if (isLandscape) 39 else 146
- val maxEmptySpace = if (isLandscape) 131 else 236
- whenever(staticdevicePaddingsMock.getWorkspaceTopPadding(anyInt())).thenReturn(topPadding)
- whenever(staticdevicePaddingsMock.getWorkspaceBottomPadding(anyInt()))
- .thenReturn(bottomPadding)
- whenever(staticdevicePaddingsMock.maxEmptySpacePx).thenReturn(maxEmptySpace)
this.isGestureMode = isGestureMode
useTwoPanels = true
@@ -305,9 +275,7 @@
numFolderRows = 3
numFolderColumns = 3
- folderBorderSpaces = PointF(16f, 16f)
- folderTopPadding = 24f
- folderCellSize = PointF(80f, 94f)
+ folderStyle = R.style.FolderDefaultStyle
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_4_4
@@ -348,7 +316,7 @@
false
)
- devicePaddings = devicePaddingsMock
+ devicePaddingId = R.xml.paddings_handhelds
}
}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
similarity index 89%
rename from tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt
rename to tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 90d7b43..85d7bf9 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -26,7 +26,7 @@
import com.android.launcher3.LauncherFiles
import com.android.launcher3.LauncherSettings.Favorites.*
import com.android.launcher3.config.FeatureFlags
-import com.android.launcher3.model.GridSizeMigrationTaskV2.DbReader
+import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
import com.android.launcher3.pm.UserCache
import com.android.launcher3.provider.LauncherDbUtils
import com.android.launcher3.util.LauncherModelHelper
@@ -37,10 +37,10 @@
import org.junit.Test
import org.junit.runner.RunWith
-/** Unit tests for [GridSizeMigrationTaskV2] */
+/** Unit tests for [GridSizeMigrationUtil] */
@SmallTest
@RunWith(AndroidJUnit4::class)
-class GridSizeMigrationTaskV2Test {
+class GridSizeMigrationUtilTest {
private lateinit var modelHelper: LauncherModelHelper
private lateinit var context: Context
private lateinit var db: SQLiteDatabase
@@ -122,15 +122,16 @@
idp.numRows = 4
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Check hotseat items
var c = context.contentResolver.query(
@@ -207,15 +208,16 @@
idp.numRows = 4
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Check hotseat items
val c = context.contentResolver.query(
@@ -262,15 +264,16 @@
idp.numRows = 4
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Check hotseat items
val c = context.contentResolver.query(
@@ -327,15 +330,16 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Get workspace items
val c = context.contentResolver.query(
@@ -387,15 +391,16 @@
idp.numRows = 5
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Get workspace items
val c = context.contentResolver.query(
@@ -448,15 +453,16 @@
idp.numRows = 4
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
- val task = GridSizeMigrationTaskV2(
- context,
- db,
- srcReader,
- destReader,
- idp.numDatabaseHotseatIcons,
- Point(idp.numColumns, idp.numRows)
+ GridSizeMigrationUtil.migrate(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows),
+ DeviceGridState(context),
+ DeviceGridState(idp)
)
- task.migrate(DeviceGridState(context), DeviceGridState(idp))
// Get workspace items
val c = context.contentResolver.query(
diff --git a/tests/src/com/android/launcher3/search/StringMatcherUtilityTest.java b/tests/src/com/android/launcher3/search/StringMatcherUtilityTest.java
index 413f404..3b53255 100644
--- a/tests/src/com/android/launcher3/search/StringMatcherUtilityTest.java
+++ b/tests/src/com/android/launcher3/search/StringMatcherUtilityTest.java
@@ -24,6 +24,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.search.StringMatcherUtility.StringMatcher;
+import com.android.launcher3.search.StringMatcherUtility.StringMatcherSpace;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,11 +35,12 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StringMatcherUtilityTest {
- private static final StringMatcher MATCHER =
- StringMatcher.getInstance();
+ private static final StringMatcher MATCHER = StringMatcher.getInstance();
+ private static final StringMatcherSpace MATCHER_SPACE = StringMatcherSpace.getInstance();
@Test
public void testMatches() {
+ assertTrue(matches("white", "white cow", MATCHER));
assertTrue(matches("white ", "white cow", MATCHER));
assertTrue(matches("white c", "white cow", MATCHER));
assertTrue(matches("cow", "white cow", MATCHER));
@@ -93,4 +95,47 @@
assertFalse(matches("ㄷ", "로드라이브", MATCHER));
assertFalse(matches("åç", "abc", MATCHER));
}
+
+ @Test
+ public void testMatchesWithSpaceBreakOnly() {
+ assertTrue(matches("white", "white cow", MATCHER_SPACE));
+ assertTrue(matches("white ", "white cow", MATCHER_SPACE));
+ assertTrue(matches("white c", "white cow", MATCHER_SPACE));
+ assertTrue(matches("cow", "white cow", MATCHER_SPACE));
+ assertTrue(matches("cow", "whitecow cow", MATCHER_SPACE));
+
+ assertFalse(matches("cow", "whiteCow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whiteCOW", MATCHER_SPACE));
+ assertFalse(matches("cow", "whitecowCOW", MATCHER_SPACE));
+ assertFalse(matches("cow", "white2cow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whitecow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whitEcow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whitecowCow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whitecowcow", MATCHER_SPACE));
+ assertFalse(matches("cow", "whit ecowcow", MATCHER_SPACE));
+
+ assertFalse(matches("dog", "cats&dogs", MATCHER_SPACE));
+ assertFalse(matches("dog", "cats&Dogs", MATCHER_SPACE));
+ assertFalse(matches("&", "cats&Dogs", MATCHER_SPACE));
+
+ assertFalse(matches("43", "2+43", MATCHER_SPACE));
+ assertFalse(matches("3", "2+43", MATCHER_SPACE));
+
+ assertTrue(matches("q", "Q", MATCHER_SPACE));
+ assertTrue(matches("q", " Q", MATCHER_SPACE));
+
+ // match lower case words
+ assertTrue(matches("e", "elephant", MATCHER_SPACE));
+ assertTrue(matches("eL", "Elephant", MATCHER_SPACE));
+
+ assertTrue(matches("电", "电子邮件", MATCHER_SPACE));
+ assertTrue(matches("电子", "电子邮件", MATCHER_SPACE));
+ assertTrue(matches("子", "电子邮件", MATCHER_SPACE));
+ assertTrue(matches("邮件", "电子邮件", MATCHER_SPACE));
+
+ assertFalse(matches("ba", "Bot", MATCHER_SPACE));
+ assertFalse(matches("ba", "bot", MATCHER_SPACE));
+ assertFalse(matches("phant", "elephant", MATCHER_SPACE));
+ assertFalse(matches("elephants", "elephant", MATCHER_SPACE));
+ }
}
diff --git a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
index 93fa705..082e243 100644
--- a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
+++ b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
@@ -15,39 +15,273 @@
*/
package com.android.launcher3.secondarydisplay;
-import static androidx.test.core.app.ActivityScenario.launch;
+import static android.content.Context.MODE_PRIVATE;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.view.MotionEvent.ACTION_DOWN;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.espresso.intent.Intents;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.LauncherModelHelper;
import org.junit.After;
-import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
- * Tests for {@link SecondaryDisplayLauncher}
+ * Tests for {@link SecondaryDisplayLauncher}.
+ * TODO (b/242776943): Remove anti-patterns & migrate prediction row tests to Quickstep directory
*/
-@MediumTest
+@LargeTest
@RunWith(AndroidJUnit4.class)
-public class SecondaryDisplayLauncherTest {
+public final class SecondaryDisplayLauncherTest extends AbstractLauncherUiTest {
+ private static final int WAIT_TIME_MS = 5000;
+ private static final int LONG_PRESS_DURATION_MS = 1000;
+ private static final int DRAG_TIME_MS = 160;
- @Before
- public void setUp() {
- Intents.init();
+ private static final String PINNED_APPS_KEY = "pinned_apps";
+
+ // Variables required to coordinate drag steps.
+ private Point mStartPoint;
+ private Point mEndPoint;
+ private long mDownTime;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ setDragNDropFlag(true);
}
@After
public void tearDown() {
- Intents.release();
+ mTargetContext.getSharedPreferences(PINNED_APPS_KEY, MODE_PRIVATE)
+ .edit().clear().commit();
}
@Test
- public void testAllAppsListOpens() {
- ActivityScenario<SecondaryDisplayLauncher> launcher =
- launch(SecondaryDisplayLauncher.class);
- launcher.onActivity(l -> l.showAppDrawer(true));
+ @Ignore
+ public void initializeSecondaryDisplayLauncher_allAppsButtonVisible() {
+ assertThat(findObjectByResourceName("all_apps_button")).isNotNull();
+ }
+
+ @Test
+ @Ignore
+ public void allAppsButtonTap_opensAppDrawer() {
+ openAppDrawer();
+ assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
+ }
+
+ @Test
+ @Ignore("Launcher3 without quickstep doesn't have a predictions row.")
+ public void appDrawerOpened_predictionRowAppDividerVisible() {
+ openAppDrawer();
+ assertThat(findObjectByResourceName("apps_divider_view")).isNotNull();
+ }
+
+ @Test
+ @Ignore
+ public void dragNDropDisabled_pinIconAddsToWorkspace() {
+ setDragNDropFlag(false);
+ openAppDrawer();
+ UiObject2 app = findDescendantByResourceName(
+ findObjectByResourceName("apps_list_view"), "icon");
+ app.click(LONG_PRESS_DURATION_MS);
+ UiObject2 popupContainer = findObjectByResourceName("popup_container");
+ assertThat(popupContainer).isNotNull();
+ UiObject2 pinIcon = findDescendantByTextOrDesc(popupContainer, "Add to home screen");
+ assertThat(pinIcon).isNotNull();
+ pinIcon.click();
+ String appName = app.getContentDescription();
+ assertThat(findAppInWorkspace(appName)).isNotNull();
+ }
+
+ @Test
+ @Ignore
+ public void pressBackFromAllApps_popupMenuOpen_returnsToWorkspace() {
+ openAppDrawer();
+ assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
+
+ findDescendantByResourceName(findObjectByResourceName("apps_list_view"), "icon")
+ .click(LONG_PRESS_DURATION_MS);
+ assertThat(findObjectByResourceName("popup_container")).isNotNull();
+
+ // First back press should close only popup menu.
+ mDevice.pressBack();
+ assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
+ assertThat(findObjectByResourceName("popup_container")).isNull();
+
+ // Second back press should close app drawer.
+ mDevice.pressBack();
+ assertThat(findObjectByResourceName("popup_container")).isNull();
+ assertThat(findObjectByResourceName("search_container_all_apps")).isNull();
+ }
+
+ @Test
+ @Ignore("Launcher3 without quickstep doesn't have a predictions row.")
+ public void dragNDropFromPredictionsRow_pinToGrid() {
+ openAppDrawer();
+ assertThat(findObjectByResourceName("prediction_row")).isNotNull();
+ String appName = startDragFromPredictionRow();
+ moveAppToCenterOfScreen();
+ dropApp();
+
+ // Ensure app was added.
+ assertThat(findAppInWorkspace(appName)).isNotNull();
+ }
+
+ @Test
+ @Ignore
+ public void dragNDropFromAppDrawer_pinToGrid() {
+ openAppDrawer();
+ String draggedAppName = startDragFromAllApps();
+ moveAppToCenterOfScreen();
+ dropApp();
+
+ // Ensure app was added.
+ assertThat(findAppInWorkspace(draggedAppName)).isNotNull();
+ }
+
+ @Test
+ @Ignore
+ public void tapRemoveButton_unpinApp() {
+ openAppDrawer();
+ String draggedAppName = startDragFromAllApps();
+ moveAppToCenterOfScreen();
+ dropApp();
+ removeAppByName(draggedAppName);
+ assertThat(findAppInWorkspace(draggedAppName)).isNull();
+ }
+
+ private void openAppDrawer() {
+ UiObject2 allAppsButton = findObjectByResourceName("all_apps_button");
+ assertThat(allAppsButton).isNotNull();
+ allAppsButton.click();
+ }
+
+ private String startDragFromAllApps() {
+ // Find app from app drawer.
+ UiObject2 allApps = findObjectByResourceName("apps_list_view");
+ assertThat(allApps).isNotNull();
+ UiObject2 icon = findDescendantByResourceName(allApps, "icon");
+ assertThat(icon).isNotNull();
+ String appName = icon.getContentDescription();
+
+ // Start drag action.
+ mDownTime = SystemClock.uptimeMillis();
+ mStartPoint = icon.getVisibleCenter();
+ mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
+ mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ assertThat(findObjectByResourceName("popup_container")).isNotNull();
+ return appName;
+ }
+
+ private String startDragFromPredictionRow() {
+ // Find app from predictions.
+ UiObject2 predictionRow = findObjectByResourceName("prediction_row");
+ assertThat(predictionRow).isNotNull();
+
+ UiObject2 icon = findDescendantByResourceName(predictionRow, "icon");
+ assertThat(icon).isNotNull();
+
+ String appName = icon.getContentDescription();
+ UiObject2 app = findDescendantByAppName(predictionRow, appName);
+ assertThat(app).isNotNull();
+
+ // Start drag action.
+ mDownTime = SystemClock.uptimeMillis();
+ mStartPoint = icon.getVisibleCenter();
+ mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
+ mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ assertThat(findObjectByResourceName("popup_container")).isNotNull();
+ return appName;
+ }
+
+ private void moveAppToCenterOfScreen() {
+ mEndPoint.set(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2);
+ mLauncher.movePointer(mDownTime, SystemClock.uptimeMillis(), DRAG_TIME_MS, true,
+ mStartPoint, mEndPoint, LauncherInstrumentation.GestureScope.INSIDE);
+ }
+
+ private void dropApp() {
+ mLauncher.sendPointer(mDownTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
+ mEndPoint, LauncherInstrumentation.GestureScope.INSIDE);
+ }
+
+ private void removeAppByName(String appName) {
+ // Find app within home screen.
+ UiObject2 app = findDescendantByAppName(findObjectByResourceName("workspace_grid"),
+ appName);
+ if (app == null) return;
+
+ // Open app's popup container.
+ app.click(LONG_PRESS_DURATION_MS);
+ UiObject2 popupContainer = findObjectByResourceName("popup_container");
+ assertThat(popupContainer).isNotNull();
+
+ // Grab & click remove button.
+ UiObject2 removeButton = findDescendantByTextOrDesc(popupContainer, "Remove");
+ assertThat(removeButton).isNotNull();
+ removeButton.click();
+ }
+
+ private UiObject2 findAppInWorkspace(String appName) {
+ UiObject2 workspace = findObjectByResourceName("workspace_grid");
+ return findDescendantByAppName(workspace, appName);
+ }
+
+ private UiObject2 findObjectByResourceName(String resourceName) {
+ return mDevice.wait(Until.findObject(By.res(mTargetPackage, resourceName)), WAIT_TIME_MS);
+ }
+
+ private UiObject2 findDescendantByResourceName(UiObject2 outerObject,
+ String resourceName) {
+ assertThat(outerObject).isNotNull();
+ return outerObject.findObject(By.res(mTargetPackage, resourceName));
+ }
+
+ private UiObject2 findDescendantByAppName(UiObject2 outerObject, String appName) {
+ assertThat(outerObject).isNotNull();
+ return outerObject.findObject(By.clazz(TextView.class).text(appName)
+ .pkg(mDevice.getLauncherPackageName()));
+ }
+
+ private UiObject2 findDescendantByTextOrDesc(UiObject2 outerObject, String content) {
+ assertThat(outerObject).isNotNull();
+ UiObject2 innerObject = outerObject.findObject(By.desc(content));
+ if (innerObject == null) innerObject = outerObject.findObject(By.text(content));
+ return innerObject;
+ }
+
+ private void startSecondaryDisplayActivity() {
+ mTargetContext.startActivity((
+ new Intent(mTargetContext, SecondaryDisplayLauncher.class).addFlags(
+ FLAG_ACTIVITY_NEW_TASK)));
+ }
+
+ private void setDragNDropFlag(Boolean status) {
+ Context context = new LauncherModelHelper().sandboxContext;
+ context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE).edit()
+ .putBoolean(FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.key, status)
+ .commit();
+ FeatureFlags.initialize(context);
+ startSecondaryDisplayActivity();
}
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 978e84c..50e0990 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -335,6 +335,7 @@
@IwTest(focusArea="launcher")
@Test
@PortraitLandscape
+ @ScreenRecord // b/256898879
public void testDragAppIcon() throws Throwable {
// 1. Open all apps and wait for load complete.
// 2. Drag icon to homescreen.
diff --git a/tests/src/com/android/launcher3/util/WidgetUtils.java b/tests/src/com/android/launcher3/util/WidgetUtils.java
index 6fc8491..e514142 100644
--- a/tests/src/com/android/launcher3/util/WidgetUtils.java
+++ b/tests/src/com/android/launcher3/util/WidgetUtils.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
@@ -32,8 +31,8 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -71,14 +70,19 @@
pendingInfo.minSpanY = item.minSpanY;
Bundle options = pendingInfo.getDefaultSizeOptions(targetContext);
- AppWidgetHost host = new LauncherAppWidgetHost(targetContext);
- int widgetId = host.allocateAppWidgetId();
- if (!new WidgetManagerHelper(targetContext)
- .bindAppWidgetIdIfAllowed(widgetId, info, options)) {
- host.deleteAppWidgetId(widgetId);
- throw new IllegalArgumentException("Unable to bind widget id");
+ LauncherWidgetHolder holder = new LauncherWidgetHolder(targetContext);
+ try {
+ int widgetId = holder.allocateAppWidgetId();
+ if (!new WidgetManagerHelper(targetContext)
+ .bindAppWidgetIdIfAllowed(widgetId, info, options)) {
+ holder.deleteAppWidgetId(widgetId);
+ throw new IllegalArgumentException("Unable to bind widget id");
+ }
+ item.appWidgetId = widgetId;
+ } finally {
+ // Necessary to destroy the holder to free up possible activity context
+ holder.destroy();
}
- item.appWidgetId = widgetId;
}
return item;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 6bbdf48..b0cf20f 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -16,6 +16,9 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.tapl.LauncherInstrumentation.DEFAULT_POLL_INTERVAL;
+import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
+
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
@@ -37,6 +40,9 @@
* Operations on AllApps opened from Home. Also a parent for All Apps opened from Overview.
*/
public abstract class AllApps extends LauncherInstrumentation.VisibleContainer {
+ // Defer updates flag used to defer all apps updates by a test's request.
+ private static final int DEFER_UPDATES_TEST = 1 << 1;
+
private static final int MAX_SCROLL_ATTEMPTS = 40;
private final int mHeight;
@@ -292,12 +298,16 @@
*/
public void unfreeze() {
mLauncher.getTestInfo(TestProtocol.REQUEST_UNFREEZE_APP_LIST);
- verifyNotFrozen("All apps freeze flags upon unfreezing");
}
private void verifyNotFrozen(String message) {
+ mLauncher.assertEquals(message, 0, getFreezeFlags() & DEFER_UPDATES_TEST);
+ mLauncher.assertTrue(message, mLauncher.waitAndGet(() -> getFreezeFlags() == 0,
+ WAIT_TIME_MS, DEFAULT_POLL_INTERVAL));
+ }
+
+ private int getFreezeFlags() {
final Bundle testInfo = mLauncher.getTestInfo(TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS);
- if (testInfo == null) return;
- mLauncher.assertEquals(message, 0, testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD));
+ return testInfo == null ? 0 : testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 15705e7..5a96d95 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -58,7 +58,7 @@
"want to switch from background to overview")) {
verifyActiveContainer();
goToOverviewUnchecked();
- return mLauncher.isFallbackOverview()
+ return mLauncher.is3PLauncher()
? new BaseOverview(mLauncher) : new Overview(mLauncher);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 4b02ecc..4a3507e 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -17,7 +17,9 @@
package com.android.launcher3.tapl;
import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID;
+import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
@@ -55,7 +57,7 @@
public Taskbar getTaskbar() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get the taskbar")) {
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
return new Taskbar(mLauncher);
}
@@ -67,7 +69,7 @@
public void assertTaskbarHidden() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"waiting for taskbar to be hidden")) {
- mLauncher.waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+ mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
}
}
@@ -77,7 +79,7 @@
public void assertTaskbarVisible() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"waiting for taskbar to be visible")) {
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
}
}
@@ -88,11 +90,12 @@
*/
public Taskbar showTaskbar() {
mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
+ mLauncher.getTestInfo(REQUEST_ENABLE_BLOCK_TIMEOUT);
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"want to show the taskbar")) {
- mLauncher.waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+ mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
final long downTime = SystemClock.uptimeMillis();
final int unstashTargetY = mLauncher.getRealDisplaySize().y
@@ -106,7 +109,7 @@
LauncherInstrumentation.log("showTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
@@ -114,6 +117,7 @@
}
} finally {
mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
+ mLauncher.getTestInfo(REQUEST_DISABLE_BLOCK_TIMEOUT);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 1c5c5fa..c3ea14a 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -83,6 +83,7 @@
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
+import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -181,6 +182,7 @@
static final String TASKBAR_RES_ID = "taskbar_view";
private static final String SPLIT_PLACEHOLDER_RES_ID = "split_placeholder";
public static final int WAIT_TIME_MS = 30000;
+ static final long DEFAULT_POLL_INTERVAL = 1000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final String ANDROID_PACKAGE = "android";
@@ -559,7 +561,7 @@
private String getVisibleStateMessage() {
if (hasLauncherObject(CONTEXT_MENU_RES_ID)) return "Context Menu";
if (hasLauncherObject(WIDGETS_RES_ID)) return "Widgets";
- if (hasLauncherObject(OVERVIEW_RES_ID)) return "Overview";
+ if (hasSystemLauncherObject(OVERVIEW_RES_ID)) return "Overview";
if (hasLauncherObject(WORKSPACE_RES_ID)) return "Workspace";
if (hasLauncherObject(APPS_RES_ID)) return "AllApps";
return "LaunchedApp (" + getVisiblePackages() + ")";
@@ -771,73 +773,89 @@
switch (containerType) {
case WORKSPACE: {
waitUntilLauncherObjectGone(APPS_RES_ID);
- waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+
+ if (is3PLauncher() && isTablet()) {
+ waitForSystemLauncherObject(TASKBAR_RES_ID);
+ } else {
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
+ }
return waitForLauncherObject(WORKSPACE_RES_ID);
}
case WIDGETS: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(APPS_RES_ID);
- waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+
+ if (is3PLauncher() && isTablet()) {
+ waitForSystemLauncherObject(TASKBAR_RES_ID);
+ } else {
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
+ }
return waitForLauncherObject(WIDGETS_RES_ID);
}
- case TASKBAR_ALL_APPS:
- case HOME_ALL_APPS: {
+ case TASKBAR_ALL_APPS: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
- waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
return waitForLauncherObject(APPS_RES_ID);
}
- case OVERVIEW: {
+ case HOME_ALL_APPS: {
+ waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
+ waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+ waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+
+ if (is3PLauncher() && isTablet()) {
+ waitForSystemLauncherObject(TASKBAR_RES_ID);
+ } else {
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
+ }
+
+ return waitForLauncherObject(APPS_RES_ID);
+ }
+ case OVERVIEW:
+ case FALLBACK_OVERVIEW: {
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
- return waitForLauncherObject(OVERVIEW_RES_ID);
+ return waitForSystemLauncherObject(OVERVIEW_RES_ID);
}
case SPLIT_SCREEN_SELECT: {
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
- waitForLauncherObject(SPLIT_PLACEHOLDER_RES_ID);
- return waitForLauncherObject(OVERVIEW_RES_ID);
- }
- case FALLBACK_OVERVIEW: {
- waitUntilLauncherObjectGone(APPS_RES_ID);
- waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
- waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
-
- return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
+ waitForSystemLauncherObject(SPLIT_PLACEHOLDER_RES_ID);
+ return waitForSystemLauncherObject(OVERVIEW_RES_ID);
}
case LAUNCHED_APP: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(APPS_RES_ID);
- waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
- waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
if (mIgnoreTaskbarVisibility) {
return null;
}
- if (isTablet() && !isFallbackOverview()) {
- waitForLauncherObject(TASKBAR_RES_ID);
+
+ if (isTablet()) {
+ waitForSystemLauncherObject(TASKBAR_RES_ID);
} else {
- waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+ waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
}
return null;
}
@@ -972,14 +990,9 @@
checkForAnomaly(false, true);
final Point displaySize = getRealDisplaySize();
- // The swipe up to home gesture starts from inside the launcher when the user is
- // already home. Otherwise, the gesture can start inside the launcher process if the
- // taskbar is visible.
- boolean gestureStartFromLauncher = isTablet()
- ? !isLauncher3()
- || hasLauncherObject(WORKSPACE_RES_ID)
- || hasLauncherObject(TASKBAR_RES_ID)
- : isLauncherVisible();
+
+ boolean gestureStartFromLauncher =
+ isTablet() ? !isLauncher3() : isLauncherVisible();
// CLose floating views before going back to home.
swipeUpToCloseFloatingView(gestureStartFromLauncher);
@@ -1012,7 +1025,7 @@
NORMAL_STATE_ORDINAL,
!hasLauncherObject(WORKSPACE_RES_ID)
&& (hasLauncherObject(APPS_RES_ID)
- || hasLauncherObject(OVERVIEW_RES_ID)),
+ || hasSystemLauncherObject(OVERVIEW_RES_ID)),
action);
}
try (LauncherInstrumentation.Closable c1 = addContextLayer(
@@ -1068,7 +1081,8 @@
boolean isLauncherContainerVisible() {
final String[] containerResources = {WORKSPACE_RES_ID, OVERVIEW_RES_ID, APPS_RES_ID};
- return Arrays.stream(containerResources).anyMatch(r -> hasLauncherObject(r));
+ return Arrays.stream(containerResources).anyMatch(
+ r -> r.equals(OVERVIEW_RES_ID) ? hasSystemLauncherObject(r) : hasLauncherObject(r));
}
/**
@@ -1151,6 +1165,14 @@
waitUntilGoneBySelector(getOverviewObjectSelector(resId));
}
+ void waitUntilSystemLauncherObjectGone(String resId) {
+ if (is3PLauncher()) {
+ waitUntilOverviewObjectGone(resId);
+ } else {
+ waitUntilLauncherObjectGone(resId);
+ }
+ }
+
void waitUntilLauncherObjectGone(BySelector selector) {
waitUntilGoneBySelector(makeLauncherSelector(selector));
}
@@ -1281,6 +1303,11 @@
return mDevice.hasObject(getLauncherObjectSelector(resId));
}
+ private boolean hasSystemLauncherObject(String resId) {
+ return mDevice.hasObject(is3PLauncher() ? getOverviewObjectSelector(resId)
+ : getLauncherObjectSelector(resId));
+ }
+
boolean hasLauncherObject(BySelector selector) {
return mDevice.hasObject(makeLauncherSelector(selector));
}
@@ -1300,6 +1327,12 @@
}
@NonNull
+ UiObject2 waitForSystemLauncherObject(String resName) {
+ return is3PLauncher() ? waitForOverviewObject(resName)
+ : waitForLauncherObject(resName);
+ }
+
+ @NonNull
UiObject2 waitForLauncherObject(BySelector selector) {
return waitForObjectBySelector(makeLauncherSelector(selector));
}
@@ -1310,11 +1343,6 @@
}
@NonNull
- UiObject2 waitForFallbackLauncherObject(String resName) {
- return waitForObjectBySelector(getOverviewObjectSelector(resName));
- }
-
- @NonNull
UiObject2 waitForAndroidObject(String resId) {
final UiObject2 object = TestHelpers.wait(
Until.findObject(By.res(ANDROID_PACKAGE, resId)), WAIT_TIME_MS);
@@ -1351,7 +1379,7 @@
return mDevice.getLauncherPackageName();
}
- boolean isFallbackOverview() {
+ boolean is3PLauncher() {
return !getOverviewPackageName().equals(getLauncherPackageName());
}
@@ -1822,6 +1850,20 @@
getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED);
}
+ /** Blocks the taskbar from automatically stashing based on time. */
+ public void enableBlockTimeout(boolean enable) {
+ getTestInfo(enable
+ ? TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT
+ : TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT);
+ }
+
+ /** Enables transient taskbar for testing purposes only. */
+ public void enableTransientTaskbar(boolean enable) {
+ getTestInfo(enable
+ ? TestProtocol.REQUEST_ENABLE_TRANSIENT_TASKBAR
+ : TestProtocol.REQUEST_DISABLE_TRANSIENT_TASKBAR);
+ }
+
/**
* Recreates the taskbar (outside of tests this is done for certain configuration changes).
* The expected behavior is that the taskbar retains its current state after being recreated.
@@ -1991,4 +2033,21 @@
mCallbackAtRunPoint.accept(runPoint);
}
}
+
+ /**
+ * Waits until a particular condition is true. Based on WaitMixin.
+ */
+ boolean waitAndGet(BooleanSupplier condition, long timeout, long interval) {
+ long startTime = SystemClock.uptimeMillis();
+
+ boolean result = condition.getAsBoolean();
+ for (long elapsedTime = 0; !result; elapsedTime = SystemClock.uptimeMillis() - startTime) {
+ if (elapsedTime >= timeout) {
+ break;
+ }
+ SystemClock.sleep(interval);
+ result = condition.getAsBoolean();
+ }
+ return result;
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
index 0f9d5f5..6ca7f4b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -52,7 +52,7 @@
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get a taskbar icon")) {
return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer(
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID),
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID),
AppIcon.getAppIconSelector(appName, mLauncher)));
}
}
@@ -68,7 +68,7 @@
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to hide the taskbar");
LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
final long downTime = SystemClock.uptimeMillis();
Point stashTarget = new Point(
@@ -79,7 +79,7 @@
LauncherInstrumentation.log("hideTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
- mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+ mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget,
LauncherInstrumentation.GestureScope.INSIDE);
}
@@ -97,7 +97,8 @@
LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer(
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID), getAllAppsButtonSelector()));
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID),
+ getAllAppsButtonSelector()));
return new AllAppsFromTaskbar(mLauncher);
}
@@ -108,7 +109,7 @@
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get all taskbar icons")) {
return mLauncher.waitForObjectsInContainer(
- mLauncher.waitForLauncherObject(TASKBAR_RES_ID),
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID),
AppIcon.getAnyAppIconSelector())
.stream()
.map(UiObject2::getText)